[BACK]Return to if_url.c CVS log [TXT][DIR] Up to [local] / sys / dev / usb

Annotation of sys/dev/usb/if_url.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: if_url.c,v 1.48 2007/06/14 10:11:15 mbalmer Exp $ */
                      2: /*     $NetBSD: if_url.c,v 1.6 2002/09/29 10:19:21 martin Exp $        */
                      3: /*
                      4:  * Copyright (c) 2001, 2002
                      5:  *     Shingo WATANABE <nabe@nabechan.org>.  All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. Neither the name of the author nor the names of any co-contributors
                     16:  *    may be used to endorse or promote products derived from this software
                     17:  *    without specific prior written permission.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     29:  * SUCH DAMAGE.
                     30:  *
                     31:  */
                     32:
                     33: /*
                     34:  * The RTL8150L(Realtek USB to fast ethernet controller) spec can be found at
                     35:  *   ftp://ftp.realtek.com.tw/lancard/data_sheet/8150/8150v14.pdf
                     36:  *   ftp://152.104.125.40/lancard/data_sheet/8150/8150v14.pdf
                     37:  */
                     38:
                     39: /*
                     40:  * TODO:
                     41:  *     Interrupt Endpoint support
                     42:  *     External PHYs
                     43:  *     powerhook() support?
                     44:  */
                     45:
                     46: #include "bpfilter.h"
                     47:
                     48: #include <sys/param.h>
                     49: #include <sys/systm.h>
                     50: #include <sys/rwlock.h>
                     51: #include <sys/mbuf.h>
                     52: #include <sys/kernel.h>
                     53: #include <sys/proc.h>
                     54: #include <sys/socket.h>
                     55:
                     56: #include <sys/device.h>
                     57:
                     58: #include <net/if.h>
                     59: #include <net/if_arp.h>
                     60: #include <net/if_dl.h>
                     61: #include <net/if_media.h>
                     62:
                     63: #if NBPFILTER > 0
                     64: #include <net/bpf.h>
                     65: #endif
                     66:
                     67: #ifdef INET
                     68: #include <netinet/in.h>
                     69: #include <netinet/in_systm.h>
                     70: #include <netinet/in_var.h>
                     71: #include <netinet/ip.h>
                     72: #include <netinet/if_ether.h>
                     73: #endif
                     74:
                     75: #include <dev/mii/mii.h>
                     76: #include <dev/mii/miivar.h>
                     77: #include <dev/mii/urlphyreg.h>
                     78:
                     79: #include <dev/usb/usb.h>
                     80: #include <dev/usb/usbdi.h>
                     81: #include <dev/usb/usbdi_util.h>
                     82: #include <dev/usb/usbdevs.h>
                     83:
                     84: #include <dev/usb/if_urlreg.h>
                     85:
                     86:
                     87: /* Function declarations */
                     88: int url_match(struct device *, void *, void *);
                     89: void url_attach(struct device *, struct device *, void *);
                     90: int url_detach(struct device *, int);
                     91: int url_activate(struct device *, enum devact);
                     92:
                     93: struct cfdriver url_cd = {
                     94:        NULL, "url", DV_IFNET
                     95: };
                     96:
                     97: const struct cfattach url_ca = {
                     98:        sizeof(struct url_softc),
                     99:        url_match,
                    100:        url_attach,
                    101:        url_detach,
                    102:        url_activate,
                    103: };
                    104:
                    105: int url_openpipes(struct url_softc *);
                    106: int url_rx_list_init(struct url_softc *);
                    107: int url_tx_list_init(struct url_softc *);
                    108: int url_newbuf(struct url_softc *, struct url_chain *, struct mbuf *);
                    109: void url_start(struct ifnet *);
                    110: int url_send(struct url_softc *, struct mbuf *, int);
                    111: void url_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
                    112: void url_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
                    113: void url_tick(void *);
                    114: void url_tick_task(void *);
                    115: int url_ioctl(struct ifnet *, u_long, caddr_t);
                    116: void url_stop_task(struct url_softc *);
                    117: void url_stop(struct ifnet *, int);
                    118: void url_watchdog(struct ifnet *);
                    119: int url_ifmedia_change(struct ifnet *);
                    120: void url_ifmedia_status(struct ifnet *, struct ifmediareq *);
                    121: void url_lock_mii(struct url_softc *);
                    122: void url_unlock_mii(struct url_softc *);
                    123: int url_int_miibus_readreg(struct device *, int, int);
                    124: void url_int_miibus_writereg(struct device *, int, int, int);
                    125: void url_miibus_statchg(struct device *);
                    126: int url_init(struct ifnet *);
                    127: void url_setmulti(struct url_softc *);
                    128: void url_reset(struct url_softc *);
                    129:
                    130: int url_csr_read_1(struct url_softc *, int);
                    131: int url_csr_read_2(struct url_softc *, int);
                    132: int url_csr_write_1(struct url_softc *, int, int);
                    133: int url_csr_write_2(struct url_softc *, int, int);
                    134: int url_csr_write_4(struct url_softc *, int, int);
                    135: int url_mem(struct url_softc *, int, int, void *, int);
                    136:
                    137: /* Macros */
                    138: #ifdef URL_DEBUG
                    139: #define DPRINTF(x)     do { if (urldebug) printf x; } while (0)
                    140: #define DPRINTFN(n,x)  do { if (urldebug >= (n)) printf x; } while (0)
                    141: int urldebug = 0;
                    142: #else
                    143: #define DPRINTF(x)
                    144: #define DPRINTFN(n,x)
                    145: #endif
                    146:
                    147: #define        URL_SETBIT(sc, reg, x)  \
                    148:        url_csr_write_1(sc, reg, url_csr_read_1(sc, reg) | (x))
                    149:
                    150: #define        URL_SETBIT2(sc, reg, x) \
                    151:        url_csr_write_2(sc, reg, url_csr_read_2(sc, reg) | (x))
                    152:
                    153: #define        URL_CLRBIT(sc, reg, x)  \
                    154:        url_csr_write_1(sc, reg, url_csr_read_1(sc, reg) & ~(x))
                    155:
                    156: #define        URL_CLRBIT2(sc, reg, x) \
                    157:        url_csr_write_2(sc, reg, url_csr_read_2(sc, reg) & ~(x))
                    158:
                    159: static const struct url_type {
                    160:        struct usb_devno url_dev;
                    161:        u_int16_t url_flags;
                    162: #define URL_EXT_PHY    0x0001
                    163: } url_devs [] = {
                    164:        {{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_LCS8138TX}, 0},
                    165:        {{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RTL8151}, 0},
                    166:        {{ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAKTX }, 0},
                    167:        {{ USB_VENDOR_MICRONET, USB_PRODUCT_MICRONET_SP128AR}, 0},
                    168:        {{ USB_VENDOR_OQO, USB_PRODUCT_OQO_ETHER01}, 0},
                    169:        {{ USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8150}, 0},
                    170:        {{ USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8151}, 0},
                    171:        {{ USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_PRESTIGE}, 0}
                    172: };
                    173: #define url_lookup(v, p) ((struct url_type *)usb_lookup(url_devs, v, p))
                    174:
                    175:
                    176: /* Probe */
                    177: int
                    178: url_match(struct device *parent, void *match, void *aux)
                    179: {
                    180:        struct usb_attach_arg *uaa = aux;
                    181:
                    182:        if (uaa->iface != NULL)
                    183:                return (UMATCH_NONE);
                    184:
                    185:        return (url_lookup(uaa->vendor, uaa->product) != NULL ?
                    186:                UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
                    187: }
                    188: /* Attach */
                    189: void
                    190: url_attach(struct device *parent, struct device *self, void *aux)
                    191: {
                    192:        struct url_softc *sc = (struct url_softc *)self;
                    193:        struct usb_attach_arg *uaa = aux;
                    194:        usbd_device_handle dev = uaa->device;
                    195:        usbd_interface_handle iface;
                    196:        usbd_status err;
                    197:        usb_interface_descriptor_t *id;
                    198:        usb_endpoint_descriptor_t *ed;
                    199:        char *devinfop;
                    200:        char *devname = sc->sc_dev.dv_xname;
                    201:        struct ifnet *ifp;
                    202:        struct mii_data *mii;
                    203:        u_char eaddr[ETHER_ADDR_LEN];
                    204:        int i, s;
                    205:
                    206:        devinfop = usbd_devinfo_alloc(dev, 0);
                    207:        printf("\n%s: %s\n", devname, devinfop);
                    208:        usbd_devinfo_free(devinfop);
                    209:
                    210:        /* Move the device into the configured state. */
                    211:        err = usbd_set_config_no(dev, URL_CONFIG_NO, 1);
                    212:        if (err) {
                    213:                printf("%s: setting config no failed\n", devname);
                    214:                goto bad;
                    215:        }
                    216:
                    217:        usb_init_task(&sc->sc_tick_task, url_tick_task, sc);
                    218:        rw_init(&sc->sc_mii_lock, "urlmii");
                    219:        usb_init_task(&sc->sc_stop_task, (void (*)(void *)) url_stop_task, sc);
                    220:
                    221:        /* get control interface */
                    222:        err = usbd_device2interface_handle(dev, URL_IFACE_INDEX, &iface);
                    223:        if (err) {
                    224:                printf("%s: failed to get interface, err=%s\n", devname,
                    225:                       usbd_errstr(err));
                    226:                goto bad;
                    227:        }
                    228:
                    229:        sc->sc_udev = dev;
                    230:        sc->sc_ctl_iface = iface;
                    231:        sc->sc_flags = url_lookup(uaa->vendor, uaa->product)->url_flags;
                    232:
                    233:        /* get interface descriptor */
                    234:        id = usbd_get_interface_descriptor(sc->sc_ctl_iface);
                    235:
                    236:        /* find endpoints */
                    237:        sc->sc_bulkin_no = sc->sc_bulkout_no = sc->sc_intrin_no = -1;
                    238:        for (i = 0; i < id->bNumEndpoints; i++) {
                    239:                ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i);
                    240:                if (ed == NULL) {
                    241:                        printf("%s: couldn't get endpoint %d\n", devname, i);
                    242:                        goto bad;
                    243:                }
                    244:                if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK &&
                    245:                    UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
                    246:                        sc->sc_bulkin_no = ed->bEndpointAddress; /* RX */
                    247:                else if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK &&
                    248:                         UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT)
                    249:                        sc->sc_bulkout_no = ed->bEndpointAddress; /* TX */
                    250:                else if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT &&
                    251:                         UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
                    252:                        sc->sc_intrin_no = ed->bEndpointAddress; /* Status */
                    253:        }
                    254:
                    255:        if (sc->sc_bulkin_no == -1 || sc->sc_bulkout_no == -1 ||
                    256:            sc->sc_intrin_no == -1) {
                    257:                printf("%s: missing endpoint\n", devname);
                    258:                goto bad;
                    259:        }
                    260:
                    261:        s = splnet();
                    262:
                    263:        /* reset the adapter */
                    264:        url_reset(sc);
                    265:
                    266:        /* Get Ethernet Address */
                    267:        err = url_mem(sc, URL_CMD_READMEM, URL_IDR0, (void *)eaddr,
                    268:                      ETHER_ADDR_LEN);
                    269:        if (err) {
                    270:                printf("%s: read MAC address failed\n", devname);
                    271:                splx(s);
                    272:                goto bad;
                    273:        }
                    274:
                    275:        /* Print Ethernet Address */
                    276:        printf("%s: address %s\n", devname, ether_sprintf(eaddr));
                    277:
                    278:        bcopy(eaddr, (char *)&sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN);
                    279:        /* initialize interface information */
                    280:        ifp = GET_IFP(sc);
                    281:        ifp->if_softc = sc;
                    282:        strlcpy(ifp->if_xname, devname, IFNAMSIZ);
                    283:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
                    284:        ifp->if_start = url_start;
                    285:        ifp->if_ioctl = url_ioctl;
                    286:        ifp->if_watchdog = url_watchdog;
                    287:
                    288:        IFQ_SET_READY(&ifp->if_snd);
                    289:
                    290:        /*
                    291:         * Do ifmedia setup.
                    292:         */
                    293:        mii = &sc->sc_mii;
                    294:        mii->mii_ifp = ifp;
                    295:        mii->mii_readreg = url_int_miibus_readreg;
                    296:        mii->mii_writereg = url_int_miibus_writereg;
                    297: #if 0
                    298:        if (sc->sc_flags & URL_EXT_PHY) {
                    299:                mii->mii_readreg = url_ext_miibus_readreg;
                    300:                mii->mii_writereg = url_ext_miibus_writereg;
                    301:        }
                    302: #endif
                    303:        mii->mii_statchg = url_miibus_statchg;
                    304:        mii->mii_flags = MIIF_AUTOTSLEEP;
                    305:        ifmedia_init(&mii->mii_media, 0,
                    306:                     url_ifmedia_change, url_ifmedia_status);
                    307:        mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0);
                    308:        if (LIST_FIRST(&mii->mii_phys) == NULL) {
                    309:                ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
                    310:                ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE);
                    311:        } else
                    312:                ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
                    313:
                    314:        /* attach the interface */
                    315:        if_attach(ifp);
                    316:        ether_ifattach(ifp);
                    317:
                    318:        timeout_set(&sc->sc_stat_ch, NULL, NULL);
                    319:        sc->sc_attached = 1;
                    320:        splx(s);
                    321:
                    322:        usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, &sc->sc_dev);
                    323:
                    324:        return;
                    325:
                    326:  bad:
                    327:        sc->sc_dying = 1;
                    328: }
                    329:
                    330: /* detach */
                    331: int
                    332: url_detach(struct device *self, int flags)
                    333: {
                    334:        struct url_softc *sc = (struct url_softc *)self;
                    335:        struct ifnet *ifp = GET_IFP(sc);
                    336:        int s;
                    337:
                    338:        DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                    339:
                    340:        /* Detached before attached finished */
                    341:        if (!sc->sc_attached)
                    342:                return (0);
                    343:
                    344:        timeout_del(&sc->sc_stat_ch);
                    345:
                    346:        /* Remove any pending tasks */
                    347:        usb_rem_task(sc->sc_udev, &sc->sc_tick_task);
                    348:        usb_rem_task(sc->sc_udev, &sc->sc_stop_task);
                    349:
                    350:        s = splusb();
                    351:
                    352:        if (--sc->sc_refcnt >= 0) {
                    353:                /* Wait for processes to go away */
                    354:                usb_detach_wait(&sc->sc_dev);
                    355:        }
                    356:
                    357:        if (ifp->if_flags & IFF_RUNNING)
                    358:                url_stop(GET_IFP(sc), 1);
                    359:
                    360:        mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
                    361:        ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
                    362:        ether_ifdetach(ifp);
                    363:        if_detach(ifp);
                    364:
                    365: #ifdef DIAGNOSTIC
                    366:        if (sc->sc_pipe_tx != NULL)
                    367:                printf("%s: detach has active tx endpoint.\n",
                    368:                       sc->sc_dev.dv_xname);
                    369:        if (sc->sc_pipe_rx != NULL)
                    370:                printf("%s: detach has active rx endpoint.\n",
                    371:                       sc->sc_dev.dv_xname);
                    372:        if (sc->sc_pipe_intr != NULL)
                    373:                printf("%s: detach has active intr endpoint.\n",
                    374:                       sc->sc_dev.dv_xname);
                    375: #endif
                    376:
                    377:        sc->sc_attached = 0;
                    378:
                    379:        splx(s);
                    380:
                    381:        usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
                    382:                           &sc->sc_dev);
                    383:
                    384:        return (0);
                    385: }
                    386:
                    387: /* read/write memory */
                    388: int
                    389: url_mem(struct url_softc *sc, int cmd, int offset, void *buf, int len)
                    390: {
                    391:        usb_device_request_t req;
                    392:        usbd_status err;
                    393:
                    394:        if (sc == NULL)
                    395:                return (0);
                    396:
                    397:        DPRINTFN(0x200,
                    398:                ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                    399:
                    400:        if (sc->sc_dying)
                    401:                return (0);
                    402:
                    403:        if (cmd == URL_CMD_READMEM)
                    404:                req.bmRequestType = UT_READ_VENDOR_DEVICE;
                    405:        else
                    406:                req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
                    407:        req.bRequest = URL_REQ_MEM;
                    408:        USETW(req.wValue, offset);
                    409:        USETW(req.wIndex, 0x0000);
                    410:        USETW(req.wLength, len);
                    411:
                    412:        sc->sc_refcnt++;
                    413:        err = usbd_do_request(sc->sc_udev, &req, buf);
                    414:        if (--sc->sc_refcnt < 0)
                    415:                usb_detach_wakeup(&sc->sc_dev);
                    416:        if (err) {
                    417:                DPRINTF(("%s: url_mem(): %s failed. off=%04x, err=%d\n",
                    418:                         sc->sc_dev.dv_xname,
                    419:                         cmd == URL_CMD_READMEM ? "read" : "write",
                    420:                         offset, err));
                    421:        }
                    422:
                    423:        return (err);
                    424: }
                    425:
                    426: /* read 1byte from register */
                    427: int
                    428: url_csr_read_1(struct url_softc *sc, int reg)
                    429: {
                    430:        u_int8_t val = 0;
                    431:
                    432:        DPRINTFN(0x100,
                    433:                 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                    434:
                    435:        if (sc->sc_dying)
                    436:                return (0);
                    437:
                    438:        return (url_mem(sc, URL_CMD_READMEM, reg, &val, 1) ? 0 : val);
                    439: }
                    440:
                    441: /* read 2bytes from register */
                    442: int
                    443: url_csr_read_2(struct url_softc *sc, int reg)
                    444: {
                    445:        uWord val;
                    446:
                    447:        DPRINTFN(0x100,
                    448:                 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                    449:
                    450:        if (sc->sc_dying)
                    451:                return (0);
                    452:
                    453:        USETW(val, 0);
                    454:        return (url_mem(sc, URL_CMD_READMEM, reg, &val, 2) ? 0 : UGETW(val));
                    455: }
                    456:
                    457: /* write 1byte to register */
                    458: int
                    459: url_csr_write_1(struct url_softc *sc, int reg, int aval)
                    460: {
                    461:        u_int8_t val = aval;
                    462:
                    463:        DPRINTFN(0x100,
                    464:                 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                    465:
                    466:        if (sc->sc_dying)
                    467:                return (0);
                    468:
                    469:        return (url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 1) ? -1 : 0);
                    470: }
                    471:
                    472: /* write 2bytes to register */
                    473: int
                    474: url_csr_write_2(struct url_softc *sc, int reg, int aval)
                    475: {
                    476:        uWord val;
                    477:
                    478:        DPRINTFN(0x100,
                    479:                 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                    480:
                    481:        USETW(val, aval);
                    482:
                    483:        if (sc->sc_dying)
                    484:                return (0);
                    485:
                    486:        return (url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 2) ? -1 : 0);
                    487: }
                    488:
                    489: /* write 4bytes to register */
                    490: int
                    491: url_csr_write_4(struct url_softc *sc, int reg, int aval)
                    492: {
                    493:        uDWord val;
                    494:
                    495:        DPRINTFN(0x100,
                    496:                 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                    497:
                    498:        USETDW(val, aval);
                    499:
                    500:        if (sc->sc_dying)
                    501:                return (0);
                    502:
                    503:        return (url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 4) ? -1 : 0);
                    504: }
                    505:
                    506: int
                    507: url_init(struct ifnet *ifp)
                    508: {
                    509:        struct url_softc *sc = ifp->if_softc;
                    510:        struct mii_data *mii = GET_MII(sc);
                    511:        u_char *eaddr;
                    512:        int i, s;
                    513:
                    514:        DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                    515:
                    516:        if (sc->sc_dying)
                    517:                return (EIO);
                    518:
                    519:        s = splnet();
                    520:
                    521:        /* Cancel pending I/O and free all TX/RX buffers */
                    522:        url_stop(ifp, 1);
                    523:
                    524:        eaddr = sc->sc_ac.ac_enaddr;
                    525:        for (i = 0; i < ETHER_ADDR_LEN; i++)
                    526:                url_csr_write_1(sc, URL_IDR0 + i, eaddr[i]);
                    527:
                    528:        /* Init transmission control register */
                    529:        URL_CLRBIT(sc, URL_TCR,
                    530:                   URL_TCR_TXRR1 | URL_TCR_TXRR0 |
                    531:                   URL_TCR_IFG1 | URL_TCR_IFG0 |
                    532:                   URL_TCR_NOCRC);
                    533:
                    534:        /* Init receive control register */
                    535:        URL_SETBIT2(sc, URL_RCR, URL_RCR_TAIL | URL_RCR_AD);
                    536:        if (ifp->if_flags & IFF_BROADCAST)
                    537:                URL_SETBIT2(sc, URL_RCR, URL_RCR_AB);
                    538:        else
                    539:                URL_CLRBIT2(sc, URL_RCR, URL_RCR_AB);
                    540:
                    541:        /* If we want promiscuous mode, accept all physical frames. */
                    542:        if (ifp->if_flags & IFF_PROMISC)
                    543:                URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP);
                    544:        else
                    545:                URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP);
                    546:
                    547:
                    548:        /* Initialize transmit ring */
                    549:        if (url_tx_list_init(sc) == ENOBUFS) {
                    550:                printf("%s: tx list init failed\n", sc->sc_dev.dv_xname);
                    551:                splx(s);
                    552:                return (EIO);
                    553:        }
                    554:
                    555:        /* Initialize receive ring */
                    556:        if (url_rx_list_init(sc) == ENOBUFS) {
                    557:                printf("%s: rx list init failed\n", sc->sc_dev.dv_xname);
                    558:                splx(s);
                    559:                return (EIO);
                    560:        }
                    561:
                    562:        /* Load the multicast filter */
                    563:        url_setmulti(sc);
                    564:
                    565:        /* Enable RX and TX */
                    566:        URL_SETBIT(sc, URL_CR, URL_CR_TE | URL_CR_RE);
                    567:
                    568:        mii_mediachg(mii);
                    569:
                    570:        if (sc->sc_pipe_tx == NULL || sc->sc_pipe_rx == NULL) {
                    571:                if (url_openpipes(sc)) {
                    572:                        splx(s);
                    573:                        return (EIO);
                    574:                }
                    575:        }
                    576:
                    577:        ifp->if_flags |= IFF_RUNNING;
                    578:        ifp->if_flags &= ~IFF_OACTIVE;
                    579:
                    580:        splx(s);
                    581:
                    582:        timeout_del(&sc->sc_stat_ch);
                    583:        timeout_set(&sc->sc_stat_ch, url_tick, sc);
                    584:        timeout_add(&sc->sc_stat_ch, hz);
                    585:
                    586:        return (0);
                    587: }
                    588:
                    589: void
                    590: url_reset(struct url_softc *sc)
                    591: {
                    592:        int i;
                    593:
                    594:        DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                    595:
                    596:        if (sc->sc_dying)
                    597:                return;
                    598:
                    599:        URL_SETBIT(sc, URL_CR, URL_CR_SOFT_RST);
                    600:
                    601:        for (i = 0; i < URL_TX_TIMEOUT; i++) {
                    602:                if (!(url_csr_read_1(sc, URL_CR) & URL_CR_SOFT_RST))
                    603:                        break;
                    604:                delay(10);      /* XXX */
                    605:        }
                    606:
                    607:        delay(10000);           /* XXX */
                    608: }
                    609:
                    610: int
                    611: url_activate(struct device *self, enum devact act)
                    612: {
                    613:        struct url_softc *sc = (struct url_softc *)self;
                    614:
                    615:        DPRINTF(("%s: %s: enter, act=%d\n", sc->sc_dev.dv_xname,
                    616:                 __func__, act));
                    617:
                    618:        switch (act) {
                    619:        case DVACT_ACTIVATE:
                    620:                break;
                    621:
                    622:        case DVACT_DEACTIVATE:
                    623:                sc->sc_dying = 1;
                    624:                break;
                    625:        }
                    626:
                    627:        return (0);
                    628: }
                    629:
                    630: #define url_calchash(addr) (ether_crc32_be((addr), ETHER_ADDR_LEN) >> 26)
                    631:
                    632:
                    633: void
                    634: url_setmulti(struct url_softc *sc)
                    635: {
                    636:        struct ifnet *ifp;
                    637:        struct ether_multi *enm;
                    638:        struct ether_multistep step;
                    639:        u_int32_t hashes[2] = { 0, 0 };
                    640:        int h = 0;
                    641:        int mcnt = 0;
                    642:
                    643:        DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                    644:
                    645:        if (sc->sc_dying)
                    646:                return;
                    647:
                    648:        ifp = GET_IFP(sc);
                    649:
                    650:        if (ifp->if_flags & IFF_PROMISC) {
                    651:                URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP);
                    652:                return;
                    653:        } else if (ifp->if_flags & IFF_ALLMULTI) {
                    654:        allmulti:
                    655:                ifp->if_flags |= IFF_ALLMULTI;
                    656:                URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM);
                    657:                URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAP);
                    658:                return;
                    659:        }
                    660:
                    661:        /* first, zot all the existing hash bits */
                    662:        url_csr_write_4(sc, URL_MAR0, 0);
                    663:        url_csr_write_4(sc, URL_MAR4, 0);
                    664:
                    665:        /* now program new ones */
                    666:        ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
                    667:        while (enm != NULL) {
                    668:                if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
                    669:                           ETHER_ADDR_LEN) != 0)
                    670:                        goto allmulti;
                    671:
                    672:                h = url_calchash(enm->enm_addrlo);
                    673:                if (h < 32)
                    674:                        hashes[0] |= (1 << h);
                    675:                else
                    676:                        hashes[1] |= (1 << (h -32));
                    677:                mcnt++;
                    678:                ETHER_NEXT_MULTI(step, enm);
                    679:        }
                    680:
                    681:        ifp->if_flags &= ~IFF_ALLMULTI;
                    682:
                    683:        URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP);
                    684:
                    685:        if (mcnt){
                    686:                URL_SETBIT2(sc, URL_RCR, URL_RCR_AM);
                    687:        } else {
                    688:                URL_CLRBIT2(sc, URL_RCR, URL_RCR_AM);
                    689:        }
                    690:        url_csr_write_4(sc, URL_MAR0, hashes[0]);
                    691:        url_csr_write_4(sc, URL_MAR4, hashes[1]);
                    692: }
                    693:
                    694: int
                    695: url_openpipes(struct url_softc *sc)
                    696: {
                    697:        struct url_chain *c;
                    698:        usbd_status err;
                    699:        int i;
                    700:        int error = 0;
                    701:
                    702:        if (sc->sc_dying)
                    703:                return (EIO);
                    704:
                    705:        sc->sc_refcnt++;
                    706:
                    707:        /* Open RX pipe */
                    708:        err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkin_no,
                    709:                             USBD_EXCLUSIVE_USE, &sc->sc_pipe_rx);
                    710:        if (err) {
                    711:                printf("%s: open rx pipe failed: %s\n",
                    712:                       sc->sc_dev.dv_xname, usbd_errstr(err));
                    713:                error = EIO;
                    714:                goto done;
                    715:        }
                    716:
                    717:        /* Open TX pipe */
                    718:        err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkout_no,
                    719:                             USBD_EXCLUSIVE_USE, &sc->sc_pipe_tx);
                    720:        if (err) {
                    721:                printf("%s: open tx pipe failed: %s\n",
                    722:                       sc->sc_dev.dv_xname, usbd_errstr(err));
                    723:                error = EIO;
                    724:                goto done;
                    725:        }
                    726:
                    727: #if 0
                    728:        /* XXX: interrupt endpoint is not yet supported */
                    729:        /* Open Interrupt pipe */
                    730:        err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_intrin_no,
                    731:                                  USBD_EXCLUSIVE_USE, &sc->sc_pipe_intr, sc,
                    732:                                  &sc->sc_cdata.url_ibuf, URL_INTR_PKGLEN,
                    733:                                  url_intr, URL_INTR_INTERVAL);
                    734:        if (err) {
                    735:                printf("%s: open intr pipe failed: %s\n",
                    736:                       sc->sc_dev.dv_xname, usbd_errstr(err));
                    737:                error = EIO;
                    738:                goto done;
                    739:        }
                    740: #endif
                    741:
                    742:
                    743:        /* Start up the receive pipe. */
                    744:        for (i = 0; i < URL_RX_LIST_CNT; i++) {
                    745:                c = &sc->sc_cdata.url_rx_chain[i];
                    746:                usbd_setup_xfer(c->url_xfer, sc->sc_pipe_rx,
                    747:                                c, c->url_buf, URL_BUFSZ,
                    748:                                USBD_SHORT_XFER_OK | USBD_NO_COPY,
                    749:                                USBD_NO_TIMEOUT, url_rxeof);
                    750:                (void)usbd_transfer(c->url_xfer);
                    751:                DPRINTF(("%s: %s: start read\n", sc->sc_dev.dv_xname,
                    752:                         __func__));
                    753:        }
                    754:
                    755:  done:
                    756:        if (--sc->sc_refcnt < 0)
                    757:                usb_detach_wakeup(&sc->sc_dev);
                    758:
                    759:        return (error);
                    760: }
                    761:
                    762: int
                    763: url_newbuf(struct url_softc *sc, struct url_chain *c, struct mbuf *m)
                    764: {
                    765:        struct mbuf *m_new = NULL;
                    766:
                    767:        DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                    768:
                    769:        if (m == NULL) {
                    770:                MGETHDR(m_new, M_DONTWAIT, MT_DATA);
                    771:                if (m_new == NULL) {
                    772:                        printf("%s: no memory for rx list "
                    773:                               "-- packet dropped!\n", sc->sc_dev.dv_xname);
                    774:                        return (ENOBUFS);
                    775:                }
                    776:                MCLGET(m_new, M_DONTWAIT);
                    777:                if (!(m_new->m_flags & M_EXT)) {
                    778:                        printf("%s: no memory for rx list "
                    779:                               "-- packet dropped!\n", sc->sc_dev.dv_xname);
                    780:                        m_freem(m_new);
                    781:                        return (ENOBUFS);
                    782:                }
                    783:                m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
                    784:        } else {
                    785:                m_new = m;
                    786:                m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
                    787:                m_new->m_data = m_new->m_ext.ext_buf;
                    788:        }
                    789:
                    790:        m_adj(m_new, ETHER_ALIGN);
                    791:        c->url_mbuf = m_new;
                    792:
                    793:        return (0);
                    794: }
                    795:
                    796:
                    797: int
                    798: url_rx_list_init(struct url_softc *sc)
                    799: {
                    800:        struct url_cdata *cd;
                    801:        struct url_chain *c;
                    802:        int i;
                    803:
                    804:        DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                    805:
                    806:        cd = &sc->sc_cdata;
                    807:        for (i = 0; i < URL_RX_LIST_CNT; i++) {
                    808:                c = &cd->url_rx_chain[i];
                    809:                c->url_sc = sc;
                    810:                c->url_idx = i;
                    811:                if (url_newbuf(sc, c, NULL) == ENOBUFS)
                    812:                        return (ENOBUFS);
                    813:                if (c->url_xfer == NULL) {
                    814:                        c->url_xfer = usbd_alloc_xfer(sc->sc_udev);
                    815:                        if (c->url_xfer == NULL)
                    816:                                return (ENOBUFS);
                    817:                        c->url_buf = usbd_alloc_buffer(c->url_xfer, URL_BUFSZ);
                    818:                        if (c->url_buf == NULL) {
                    819:                                usbd_free_xfer(c->url_xfer);
                    820:                                return (ENOBUFS);
                    821:                        }
                    822:                }
                    823:        }
                    824:
                    825:        return (0);
                    826: }
                    827:
                    828: int
                    829: url_tx_list_init(struct url_softc *sc)
                    830: {
                    831:        struct url_cdata *cd;
                    832:        struct url_chain *c;
                    833:        int i;
                    834:
                    835:        DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                    836:
                    837:        cd = &sc->sc_cdata;
                    838:        for (i = 0; i < URL_TX_LIST_CNT; i++) {
                    839:                c = &cd->url_tx_chain[i];
                    840:                c->url_sc = sc;
                    841:                c->url_idx = i;
                    842:                c->url_mbuf = NULL;
                    843:                if (c->url_xfer == NULL) {
                    844:                        c->url_xfer = usbd_alloc_xfer(sc->sc_udev);
                    845:                        if (c->url_xfer == NULL)
                    846:                                return (ENOBUFS);
                    847:                        c->url_buf = usbd_alloc_buffer(c->url_xfer, URL_BUFSZ);
                    848:                        if (c->url_buf == NULL) {
                    849:                                usbd_free_xfer(c->url_xfer);
                    850:                                return (ENOBUFS);
                    851:                        }
                    852:                }
                    853:        }
                    854:
                    855:        return (0);
                    856: }
                    857:
                    858: void
                    859: url_start(struct ifnet *ifp)
                    860: {
                    861:        struct url_softc *sc = ifp->if_softc;
                    862:        struct mbuf *m_head = NULL;
                    863:
                    864:        DPRINTF(("%s: %s: enter, link=%d\n", sc->sc_dev.dv_xname,
                    865:                 __func__, sc->sc_link));
                    866:
                    867:        if (sc->sc_dying)
                    868:                return;
                    869:
                    870:        if (!sc->sc_link)
                    871:                return;
                    872:
                    873:        if (ifp->if_flags & IFF_OACTIVE)
                    874:                return;
                    875:
                    876:        IFQ_POLL(&ifp->if_snd, m_head);
                    877:        if (m_head == NULL)
                    878:                return;
                    879:
                    880:        if (url_send(sc, m_head, 0)) {
                    881:                ifp->if_flags |= IFF_OACTIVE;
                    882:                return;
                    883:        }
                    884:
                    885:        IFQ_DEQUEUE(&ifp->if_snd, m_head);
                    886:
                    887: #if NBPFILTER > 0
                    888:        if (ifp->if_bpf)
                    889:                bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
                    890: #endif
                    891:
                    892:        ifp->if_flags |= IFF_OACTIVE;
                    893:
                    894:        /* Set a timeout in case the chip goes out to lunch. */
                    895:        ifp->if_timer = 5;
                    896: }
                    897:
                    898: int
                    899: url_send(struct url_softc *sc, struct mbuf *m, int idx)
                    900: {
                    901:        int total_len;
                    902:        struct url_chain *c;
                    903:        usbd_status err;
                    904:
                    905:        DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__));
                    906:
                    907:        c = &sc->sc_cdata.url_tx_chain[idx];
                    908:
                    909:        /* Copy the mbuf data into a contiguous buffer */
                    910:        m_copydata(m, 0, m->m_pkthdr.len, c->url_buf);
                    911:        c->url_mbuf = m;
                    912:        total_len = m->m_pkthdr.len;
                    913:
                    914:        if (total_len < URL_MIN_FRAME_LEN) {
                    915:                bzero(c->url_buf + total_len, URL_MIN_FRAME_LEN - total_len);
                    916:                total_len = URL_MIN_FRAME_LEN;
                    917:        }
                    918:        usbd_setup_xfer(c->url_xfer, sc->sc_pipe_tx, c, c->url_buf, total_len,
                    919:                        USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
                    920:                        URL_TX_TIMEOUT, url_txeof);
                    921:
                    922:        /* Transmit */
                    923:        sc->sc_refcnt++;
                    924:        err = usbd_transfer(c->url_xfer);
                    925:        if (--sc->sc_refcnt < 0)
                    926:                usb_detach_wakeup(&sc->sc_dev);
                    927:        if (err != USBD_IN_PROGRESS) {
                    928:                printf("%s: url_send error=%s\n", sc->sc_dev.dv_xname,
                    929:                       usbd_errstr(err));
                    930:                /* Stop the interface */
                    931:                usb_add_task(sc->sc_udev, &sc->sc_stop_task);
                    932:                return (EIO);
                    933:        }
                    934:
                    935:        DPRINTF(("%s: %s: send %d bytes\n", sc->sc_dev.dv_xname,
                    936:                 __func__, total_len));
                    937:
                    938:        sc->sc_cdata.url_tx_cnt++;
                    939:
                    940:        return (0);
                    941: }
                    942:
                    943: void
                    944: url_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
                    945: {
                    946:        struct url_chain *c = priv;
                    947:        struct url_softc *sc = c->url_sc;
                    948:        struct ifnet *ifp = GET_IFP(sc);
                    949:        int s;
                    950:
                    951:        if (sc->sc_dying)
                    952:                return;
                    953:
                    954:        s = splnet();
                    955:
                    956:        DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                    957:
                    958:        ifp->if_timer = 0;
                    959:        ifp->if_flags &= ~IFF_OACTIVE;
                    960:
                    961:        if (status != USBD_NORMAL_COMPLETION) {
                    962:                if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
                    963:                        splx(s);
                    964:                        return;
                    965:                }
                    966:                ifp->if_oerrors++;
                    967:                printf("%s: usb error on tx: %s\n", sc->sc_dev.dv_xname,
                    968:                       usbd_errstr(status));
                    969:                if (status == USBD_STALLED) {
                    970:                        sc->sc_refcnt++;
                    971:                        usbd_clear_endpoint_stall_async(sc->sc_pipe_tx);
                    972:                        if (--sc->sc_refcnt < 0)
                    973:                                usb_detach_wakeup(&sc->sc_dev);
                    974:                }
                    975:                splx(s);
                    976:                return;
                    977:        }
                    978:
                    979:        ifp->if_opackets++;
                    980:
                    981:        m_freem(c->url_mbuf);
                    982:        c->url_mbuf = NULL;
                    983:
                    984:        if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
                    985:                url_start(ifp);
                    986:
                    987:        splx(s);
                    988: }
                    989:
                    990: void
                    991: url_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
                    992: {
                    993:        struct url_chain *c = priv;
                    994:        struct url_softc *sc = c->url_sc;
                    995:        struct ifnet *ifp = GET_IFP(sc);
                    996:        struct mbuf *m;
                    997:        u_int32_t total_len;
                    998:        url_rxhdr_t rxhdr;
                    999:        int s;
                   1000:
                   1001:        DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__));
                   1002:
                   1003:        if (sc->sc_dying)
                   1004:                return;
                   1005:
                   1006:        if (status != USBD_NORMAL_COMPLETION) {
                   1007:                if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
                   1008:                        return;
                   1009:                sc->sc_rx_errs++;
                   1010:                if (usbd_ratecheck(&sc->sc_rx_notice)) {
                   1011:                        printf("%s: %u usb errors on rx: %s\n",
                   1012:                               sc->sc_dev.dv_xname, sc->sc_rx_errs,
                   1013:                               usbd_errstr(status));
                   1014:                        sc->sc_rx_errs = 0;
                   1015:                }
                   1016:                if (status == USBD_STALLED) {
                   1017:                        sc->sc_refcnt++;
                   1018:                        usbd_clear_endpoint_stall_async(sc->sc_pipe_rx);
                   1019:                        if (--sc->sc_refcnt < 0)
                   1020:                                usb_detach_wakeup(&sc->sc_dev);
                   1021:                }
                   1022:                goto done;
                   1023:        }
                   1024:
                   1025:        usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
                   1026:
                   1027:        memcpy(mtod(c->url_mbuf, char *), c->url_buf, total_len);
                   1028:
                   1029:        if (total_len <= ETHER_CRC_LEN) {
                   1030:                ifp->if_ierrors++;
                   1031:                goto done;
                   1032:        }
                   1033:
                   1034:        memcpy(&rxhdr, c->url_buf + total_len - ETHER_CRC_LEN, sizeof(rxhdr));
                   1035:
                   1036:        DPRINTF(("%s: RX Status: %dbytes%s%s%s%s packets\n",
                   1037:                 sc->sc_dev.dv_xname,
                   1038:                 UGETW(rxhdr) & URL_RXHDR_BYTEC_MASK,
                   1039:                 UGETW(rxhdr) & URL_RXHDR_VALID_MASK ? ", Valid" : "",
                   1040:                 UGETW(rxhdr) & URL_RXHDR_RUNTPKT_MASK ? ", Runt" : "",
                   1041:                 UGETW(rxhdr) & URL_RXHDR_PHYPKT_MASK ? ", Physical match" : "",
                   1042:                 UGETW(rxhdr) & URL_RXHDR_MCASTPKT_MASK ? ", Multicast" : ""));
                   1043:
                   1044:        if ((UGETW(rxhdr) & URL_RXHDR_VALID_MASK) == 0) {
                   1045:                ifp->if_ierrors++;
                   1046:                goto done;
                   1047:        }
                   1048:
                   1049:        ifp->if_ipackets++;
                   1050:        total_len -= ETHER_CRC_LEN;
                   1051:
                   1052:        m = c->url_mbuf;
                   1053:        m->m_pkthdr.len = m->m_len = total_len;
                   1054:        m->m_pkthdr.rcvif = ifp;
                   1055:
                   1056:        s = splnet();
                   1057:
                   1058:        if (url_newbuf(sc, c, NULL) == ENOBUFS) {
                   1059:                ifp->if_ierrors++;
                   1060:                goto done1;
                   1061:        }
                   1062:
                   1063: #if NBPFILTER > 0
                   1064:        if (ifp->if_bpf)
                   1065:                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
                   1066: #endif
                   1067:
                   1068:        DPRINTF(("%s: %s: deliver %d\n", sc->sc_dev.dv_xname,
                   1069:                 __func__, m->m_len));
                   1070:        ether_input_mbuf(ifp, m);
                   1071:
                   1072:  done1:
                   1073:        splx(s);
                   1074:
                   1075:  done:
                   1076:        /* Setup new transfer */
                   1077:        usbd_setup_xfer(xfer, sc->sc_pipe_rx, c, c->url_buf, URL_BUFSZ,
                   1078:                        USBD_SHORT_XFER_OK | USBD_NO_COPY,
                   1079:                        USBD_NO_TIMEOUT, url_rxeof);
                   1080:        sc->sc_refcnt++;
                   1081:        usbd_transfer(xfer);
                   1082:        if (--sc->sc_refcnt < 0)
                   1083:                usb_detach_wakeup(&sc->sc_dev);
                   1084:
                   1085:        DPRINTF(("%s: %s: start rx\n", sc->sc_dev.dv_xname, __func__));
                   1086: }
                   1087:
                   1088: #if 0
                   1089: void url_intr()
                   1090: {
                   1091: }
                   1092: #endif
                   1093:
                   1094: int
                   1095: url_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
                   1096: {
                   1097:        struct url_softc *sc = ifp->if_softc;
                   1098:        struct ifaddr *ifa = (struct ifaddr *)data;
                   1099:        struct ifreq *ifr = (struct ifreq *)data;
                   1100:        struct mii_data *mii;
                   1101:        int s, error = 0;
                   1102:
                   1103:        DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                   1104:
                   1105:        if (sc->sc_dying)
                   1106:                return (EIO);
                   1107:
                   1108:        s = splnet();
                   1109:
                   1110:        switch (cmd) {
                   1111:        case SIOCSIFADDR:
                   1112:                ifp->if_flags |= IFF_UP;
                   1113:                url_init(ifp);
                   1114:
                   1115:                switch (ifa->ifa_addr->sa_family) {
                   1116: #ifdef INET
                   1117:                case AF_INET:
                   1118:                        arp_ifinit(&sc->sc_ac, ifa);
                   1119:                        break;
                   1120: #endif /* INET */
                   1121:                }
                   1122:                break;
                   1123:
                   1124:        case SIOCSIFMTU:
                   1125:                if (ifr->ifr_mtu > ETHERMTU)
                   1126:                        error = EINVAL;
                   1127:                else
                   1128:                        ifp->if_mtu = ifr->ifr_mtu;
                   1129:                break;
                   1130:
                   1131:        case SIOCSIFFLAGS:
                   1132:                if (ifp->if_flags & IFF_UP) {
                   1133:                        if (ifp->if_flags & IFF_RUNNING &&
                   1134:                            ifp->if_flags & IFF_PROMISC) {
                   1135:                                URL_SETBIT2(sc, URL_RCR,
                   1136:                                            URL_RCR_AAM|URL_RCR_AAP);
                   1137:                        } else if (ifp->if_flags & IFF_RUNNING &&
                   1138:                                   !(ifp->if_flags & IFF_PROMISC)) {
                   1139:                                URL_CLRBIT2(sc, URL_RCR,
                   1140:                                            URL_RCR_AAM|URL_RCR_AAP);
                   1141:                        } else if (!(ifp->if_flags & IFF_RUNNING))
                   1142:                                url_init(ifp);
                   1143:                } else {
                   1144:                        if (ifp->if_flags & IFF_RUNNING)
                   1145:                                url_stop(ifp, 1);
                   1146:                }
                   1147:                error = 0;
                   1148:                break;
                   1149:        case SIOCADDMULTI:
                   1150:        case SIOCDELMULTI:
                   1151:                error = (cmd == SIOCADDMULTI) ?
                   1152:                        ether_addmulti(ifr, &sc->sc_ac) :
                   1153:                        ether_delmulti(ifr, &sc->sc_ac);
                   1154:
                   1155:                if (error == ENETRESET) {
                   1156:                        if (ifp->if_flags & IFF_RUNNING)
                   1157:                                url_setmulti(sc);
                   1158:                        error = 0;
                   1159:                }
                   1160:                break;
                   1161:        case SIOCGIFMEDIA:
                   1162:        case SIOCSIFMEDIA:
                   1163:                mii = GET_MII(sc);
                   1164:                error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
                   1165:                break;
                   1166:        default:
                   1167:                error = EINVAL;
                   1168:                break;
                   1169:        }
                   1170:
                   1171:        splx(s);
                   1172:
                   1173:        return (error);
                   1174: }
                   1175:
                   1176: void
                   1177: url_watchdog(struct ifnet *ifp)
                   1178: {
                   1179:        struct url_softc *sc = ifp->if_softc;
                   1180:        struct url_chain *c;
                   1181:        usbd_status stat;
                   1182:        int s;
                   1183:
                   1184:        DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                   1185:
                   1186:        ifp->if_oerrors++;
                   1187:        printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname);
                   1188:
                   1189:        s = splusb();
                   1190:        c = &sc->sc_cdata.url_tx_chain[0];
                   1191:        usbd_get_xfer_status(c->url_xfer, NULL, NULL, NULL, &stat);
                   1192:        url_txeof(c->url_xfer, c, stat);
                   1193:
                   1194:        if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
                   1195:                url_start(ifp);
                   1196:        splx(s);
                   1197: }
                   1198:
                   1199: void
                   1200: url_stop_task(struct url_softc *sc)
                   1201: {
                   1202:        url_stop(GET_IFP(sc), 1);
                   1203: }
                   1204:
                   1205: /* Stop the adapter and free any mbufs allocated to the RX and TX lists. */
                   1206: void
                   1207: url_stop(struct ifnet *ifp, int disable)
                   1208: {
                   1209:        struct url_softc *sc = ifp->if_softc;
                   1210:        usbd_status err;
                   1211:        int i;
                   1212:
                   1213:        DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                   1214:
                   1215:        ifp->if_timer = 0;
                   1216:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
                   1217:
                   1218:        url_reset(sc);
                   1219:
                   1220:        timeout_del(&sc->sc_stat_ch);
                   1221:
                   1222:        /* Stop transfers */
                   1223:        /* RX endpoint */
                   1224:        if (sc->sc_pipe_rx != NULL) {
                   1225:                err = usbd_abort_pipe(sc->sc_pipe_rx);
                   1226:                if (err)
                   1227:                        printf("%s: abort rx pipe failed: %s\n",
                   1228:                               sc->sc_dev.dv_xname, usbd_errstr(err));
                   1229:                err = usbd_close_pipe(sc->sc_pipe_rx);
                   1230:                if (err)
                   1231:                        printf("%s: close rx pipe failed: %s\n",
                   1232:                               sc->sc_dev.dv_xname, usbd_errstr(err));
                   1233:                sc->sc_pipe_rx = NULL;
                   1234:        }
                   1235:
                   1236:        /* TX endpoint */
                   1237:        if (sc->sc_pipe_tx != NULL) {
                   1238:                err = usbd_abort_pipe(sc->sc_pipe_tx);
                   1239:                if (err)
                   1240:                        printf("%s: abort tx pipe failed: %s\n",
                   1241:                               sc->sc_dev.dv_xname, usbd_errstr(err));
                   1242:                err = usbd_close_pipe(sc->sc_pipe_tx);
                   1243:                if (err)
                   1244:                        printf("%s: close tx pipe failed: %s\n",
                   1245:                               sc->sc_dev.dv_xname, usbd_errstr(err));
                   1246:                sc->sc_pipe_tx = NULL;
                   1247:        }
                   1248:
                   1249: #if 0
                   1250:        /* XXX: Interrupt endpoint is not yet supported!! */
                   1251:        /* Interrupt endpoint */
                   1252:        if (sc->sc_pipe_intr != NULL) {
                   1253:                err = usbd_abort_pipe(sc->sc_pipe_intr);
                   1254:                if (err)
                   1255:                        printf("%s: abort intr pipe failed: %s\n",
                   1256:                               sc->sc_dev.dv_xname, usbd_errstr(err));
                   1257:                err = usbd_close_pipe(sc->sc_pipe_intr);
                   1258:                if (err)
                   1259:                        printf("%s: close intr pipe failed: %s\n",
                   1260:                               sc->sc_dev.dv_xname, usbd_errstr(err));
                   1261:                sc->sc_pipe_intr = NULL;
                   1262:        }
                   1263: #endif
                   1264:
                   1265:        /* Free RX resources. */
                   1266:        for (i = 0; i < URL_RX_LIST_CNT; i++) {
                   1267:                if (sc->sc_cdata.url_rx_chain[i].url_mbuf != NULL) {
                   1268:                        m_freem(sc->sc_cdata.url_rx_chain[i].url_mbuf);
                   1269:                        sc->sc_cdata.url_rx_chain[i].url_mbuf = NULL;
                   1270:                }
                   1271:                if (sc->sc_cdata.url_rx_chain[i].url_xfer != NULL) {
                   1272:                        usbd_free_xfer(sc->sc_cdata.url_rx_chain[i].url_xfer);
                   1273:                        sc->sc_cdata.url_rx_chain[i].url_xfer = NULL;
                   1274:                }
                   1275:        }
                   1276:
                   1277:        /* Free TX resources. */
                   1278:        for (i = 0; i < URL_TX_LIST_CNT; i++) {
                   1279:                if (sc->sc_cdata.url_tx_chain[i].url_mbuf != NULL) {
                   1280:                        m_freem(sc->sc_cdata.url_tx_chain[i].url_mbuf);
                   1281:                        sc->sc_cdata.url_tx_chain[i].url_mbuf = NULL;
                   1282:                }
                   1283:                if (sc->sc_cdata.url_tx_chain[i].url_xfer != NULL) {
                   1284:                        usbd_free_xfer(sc->sc_cdata.url_tx_chain[i].url_xfer);
                   1285:                        sc->sc_cdata.url_tx_chain[i].url_xfer = NULL;
                   1286:                }
                   1287:        }
                   1288:
                   1289:        sc->sc_link = 0;
                   1290: }
                   1291:
                   1292: /* Set media options */
                   1293: int
                   1294: url_ifmedia_change(struct ifnet *ifp)
                   1295: {
                   1296:        struct url_softc *sc = ifp->if_softc;
                   1297:        struct mii_data *mii = GET_MII(sc);
                   1298:
                   1299:        DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                   1300:
                   1301:        if (sc->sc_dying)
                   1302:                return (0);
                   1303:
                   1304:        sc->sc_link = 0;
                   1305:        if (mii->mii_instance) {
                   1306:                struct mii_softc *miisc;
                   1307:                for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL;
                   1308:                     miisc = LIST_NEXT(miisc, mii_list))
                   1309:                        mii_phy_reset(miisc);
                   1310:        }
                   1311:
                   1312:        return (mii_mediachg(mii));
                   1313: }
                   1314:
                   1315: /* Report current media status. */
                   1316: void
                   1317: url_ifmedia_status(struct ifnet *ifp, struct ifmediareq *ifmr)
                   1318: {
                   1319:        struct url_softc *sc = ifp->if_softc;
                   1320:        struct mii_data *mii = GET_MII(sc);
                   1321:
                   1322:        DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                   1323:
                   1324:        if (sc->sc_dying)
                   1325:                return;
                   1326:
                   1327:        if ((ifp->if_flags & IFF_RUNNING) == 0) {
                   1328:                ifmr->ifm_active = IFM_ETHER | IFM_NONE;
                   1329:                ifmr->ifm_status = 0;
                   1330:                return;
                   1331:        }
                   1332:
                   1333:        mii_pollstat(mii);
                   1334:        ifmr->ifm_active = mii->mii_media_active;
                   1335:        ifmr->ifm_status = mii->mii_media_status;
                   1336: }
                   1337:
                   1338: void
                   1339: url_tick(void *xsc)
                   1340: {
                   1341:        struct url_softc *sc = xsc;
                   1342:
                   1343:        if (sc == NULL)
                   1344:                return;
                   1345:
                   1346:        DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname,
                   1347:                        __func__));
                   1348:
                   1349:        if (sc->sc_dying)
                   1350:                return;
                   1351:
                   1352:        /* Perform periodic stuff in process context */
                   1353:        usb_add_task(sc->sc_udev, &sc->sc_tick_task);
                   1354: }
                   1355:
                   1356: void
                   1357: url_tick_task(void *xsc)
                   1358: {
                   1359:        struct url_softc *sc = xsc;
                   1360:        struct ifnet *ifp;
                   1361:        struct mii_data *mii;
                   1362:        int s;
                   1363:
                   1364:        if (sc == NULL)
                   1365:                return;
                   1366:
                   1367:        DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname,
                   1368:                        __func__));
                   1369:
                   1370:        if (sc->sc_dying)
                   1371:                return;
                   1372:
                   1373:        ifp = GET_IFP(sc);
                   1374:        mii = GET_MII(sc);
                   1375:
                   1376:        if (mii == NULL)
                   1377:                return;
                   1378:
                   1379:        s = splnet();
                   1380:
                   1381:        mii_tick(mii);
                   1382:        if (!sc->sc_link && mii->mii_media_status & IFM_ACTIVE &&
                   1383:            IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
                   1384:                DPRINTF(("%s: %s: got link\n",
                   1385:                         sc->sc_dev.dv_xname, __func__));
                   1386:                sc->sc_link++;
                   1387:                if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
                   1388:                           url_start(ifp);
                   1389:        }
                   1390:
                   1391:        timeout_del(&sc->sc_stat_ch);
                   1392:        timeout_set(&sc->sc_stat_ch, url_tick, sc);
                   1393:        timeout_add(&sc->sc_stat_ch, hz);
                   1394:
                   1395:        splx(s);
                   1396: }
                   1397:
                   1398: /* Get exclusive access to the MII registers */
                   1399: void
                   1400: url_lock_mii(struct url_softc *sc)
                   1401: {
                   1402:        DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname,
                   1403:                        __func__));
                   1404:
                   1405:        sc->sc_refcnt++;
                   1406:        rw_enter_write(&sc->sc_mii_lock);
                   1407: }
                   1408:
                   1409: void
                   1410: url_unlock_mii(struct url_softc *sc)
                   1411: {
                   1412:        DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname,
                   1413:                       __func__));
                   1414:
                   1415:        rw_exit_write(&sc->sc_mii_lock);
                   1416:        if (--sc->sc_refcnt < 0)
                   1417:                usb_detach_wakeup(&sc->sc_dev);
                   1418: }
                   1419:
                   1420: int
                   1421: url_int_miibus_readreg(struct device *dev, int phy, int reg)
                   1422: {
                   1423:        struct url_softc *sc;
                   1424:        u_int16_t val;
                   1425:
                   1426:        if (dev == NULL)
                   1427:                return (0);
                   1428:
                   1429:        sc = (void *)dev;
                   1430:
                   1431:        DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x\n",
                   1432:                 sc->sc_dev.dv_xname, __func__, phy, reg));
                   1433:
                   1434:        if (sc->sc_dying) {
                   1435: #ifdef DIAGNOSTIC
                   1436:                printf("%s: %s: dying\n", sc->sc_dev.dv_xname,
                   1437:                       __func__);
                   1438: #endif
                   1439:                return (0);
                   1440:        }
                   1441:
                   1442:        /* XXX: one PHY only for the RTL8150 internal PHY */
                   1443:        if (phy != 0) {
                   1444:                DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n",
                   1445:                         sc->sc_dev.dv_xname, __func__, phy));
                   1446:                return (0);
                   1447:        }
                   1448:
                   1449:        url_lock_mii(sc);
                   1450:
                   1451:        switch (reg) {
                   1452:        case MII_BMCR:          /* Control Register */
                   1453:                reg = URL_BMCR;
                   1454:                break;
                   1455:        case MII_BMSR:          /* Status Register */
                   1456:                reg = URL_BMSR;
                   1457:                break;
                   1458:        case MII_PHYIDR1:
                   1459:        case MII_PHYIDR2:
                   1460:                val = 0;
                   1461:                goto R_DONE;
                   1462:                break;
                   1463:        case MII_ANAR:          /* Autonegotiation advertisement */
                   1464:                reg = URL_ANAR;
                   1465:                break;
                   1466:        case MII_ANLPAR:        /* Autonegotiation link partner abilities */
                   1467:                reg = URL_ANLP;
                   1468:                break;
                   1469:        case URLPHY_MSR:        /* Media Status Register */
                   1470:                reg = URL_MSR;
                   1471:                break;
                   1472:        default:
                   1473:                printf("%s: %s: bad register %04x\n",
                   1474:                       sc->sc_dev.dv_xname, __func__, reg);
                   1475:                val = 0;
                   1476:                goto R_DONE;
                   1477:                break;
                   1478:        }
                   1479:
                   1480:        if (reg == URL_MSR)
                   1481:                val = url_csr_read_1(sc, reg);
                   1482:        else
                   1483:                val = url_csr_read_2(sc, reg);
                   1484:
                   1485:  R_DONE:
                   1486:        DPRINTFN(0xff, ("%s: %s: phy=%d reg=0x%04x => 0x%04x\n",
                   1487:                 sc->sc_dev.dv_xname, __func__, phy, reg, val));
                   1488:
                   1489:        url_unlock_mii(sc);
                   1490:        return (val);
                   1491: }
                   1492:
                   1493: void
                   1494: url_int_miibus_writereg(struct device *dev, int phy, int reg, int data)
                   1495: {
                   1496:        struct url_softc *sc;
                   1497:
                   1498:        if (dev == NULL)
                   1499:                return;
                   1500:
                   1501:        sc = (void *)dev;
                   1502:
                   1503:        DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x data=0x%04x\n",
                   1504:                 sc->sc_dev.dv_xname, __func__, phy, reg, data));
                   1505:
                   1506:        if (sc->sc_dying) {
                   1507: #ifdef DIAGNOSTIC
                   1508:                printf("%s: %s: dying\n", sc->sc_dev.dv_xname,
                   1509:                       __func__);
                   1510: #endif
                   1511:                return;
                   1512:        }
                   1513:
                   1514:        /* XXX: one PHY only for the RTL8150 internal PHY */
                   1515:        if (phy != 0) {
                   1516:                DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n",
                   1517:                         sc->sc_dev.dv_xname, __func__, phy));
                   1518:                return;
                   1519:        }
                   1520:
                   1521:        url_lock_mii(sc);
                   1522:
                   1523:        switch (reg) {
                   1524:        case MII_BMCR:          /* Control Register */
                   1525:                reg = URL_BMCR;
                   1526:                break;
                   1527:        case MII_BMSR:          /* Status Register */
                   1528:                reg = URL_BMSR;
                   1529:                break;
                   1530:        case MII_PHYIDR1:
                   1531:        case MII_PHYIDR2:
                   1532:                goto W_DONE;
                   1533:                break;
                   1534:        case MII_ANAR:          /* Autonegotiation advertisement */
                   1535:                reg = URL_ANAR;
                   1536:                break;
                   1537:        case MII_ANLPAR:        /* Autonegotiation link partner abilities */
                   1538:                reg = URL_ANLP;
                   1539:                break;
                   1540:        case URLPHY_MSR:        /* Media Status Register */
                   1541:                reg = URL_MSR;
                   1542:                break;
                   1543:        default:
                   1544:                printf("%s: %s: bad register %04x\n",
                   1545:                       sc->sc_dev.dv_xname, __func__, reg);
                   1546:                goto W_DONE;
                   1547:                break;
                   1548:        }
                   1549:
                   1550:        if (reg == URL_MSR)
                   1551:                url_csr_write_1(sc, reg, data);
                   1552:        else
                   1553:                url_csr_write_2(sc, reg, data);
                   1554:  W_DONE:
                   1555:
                   1556:        url_unlock_mii(sc);
                   1557:        return;
                   1558: }
                   1559:
                   1560: void
                   1561: url_miibus_statchg(struct device *dev)
                   1562: {
                   1563: #ifdef URL_DEBUG
                   1564:        struct url_softc *sc;
                   1565:
                   1566:        if (dev == NULL)
                   1567:                return;
                   1568:
                   1569:        sc = (void *)dev;
                   1570:        DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                   1571: #endif
                   1572:        /* Nothing to do */
                   1573: }
                   1574:
                   1575: #if 0
                   1576: /*
                   1577:  * external PHYs support, but not test.
                   1578:  */
                   1579: int
                   1580: url_ext_miibus_redreg(struct device *dev, int phy, int reg)
                   1581: {
                   1582:        struct url_softc *sc = (void *)dev;
                   1583:        u_int16_t val;
                   1584:
                   1585:        DPRINTF(("%s: %s: enter, phy=%d reg=0x%04x\n",
                   1586:                 sc->sc_dev.dv_xname, __func__, phy, reg));
                   1587:
                   1588:        if (sc->sc_dying) {
                   1589: #ifdef DIAGNOSTIC
                   1590:                printf("%s: %s: dying\n", sc->sc_dev.dv_xname,
                   1591:                       __func__);
                   1592: #endif
                   1593:                return (0);
                   1594:        }
                   1595:
                   1596:        url_lock_mii(sc);
                   1597:
                   1598:        url_csr_write_1(sc, URL_PHYADD, phy & URL_PHYADD_MASK);
                   1599:        /*
                   1600:         * RTL8150L will initiate a MII management data transaction
                   1601:         * if PHYCNT_OWN bit is set 1 by software. After transaction,
                   1602:         * this bit is auto cleared by TRL8150L.
                   1603:         */
                   1604:        url_csr_write_1(sc, URL_PHYCNT,
                   1605:                        (reg | URL_PHYCNT_PHYOWN) & ~URL_PHYCNT_RWCR);
                   1606:        for (i = 0; i < URL_TIMEOUT; i++) {
                   1607:                if ((url_csr_read_1(sc, URL_PHYCNT) & URL_PHYCNT_PHYOWN) == 0)
                   1608:                        break;
                   1609:        }
                   1610:        if (i == URL_TIMEOUT) {
                   1611:                printf("%s: MII read timed out\n", sc->sc_dev.dv_xname);
                   1612:        }
                   1613:
                   1614:        val = url_csr_read_2(sc, URL_PHYDAT);
                   1615:
                   1616:        DPRINTF(("%s: %s: phy=%d reg=0x%04x => 0x%04x\n",
                   1617:                 sc->sc_dev.dv_xname, __func__, phy, reg, val));
                   1618:
                   1619:        url_unlock_mii(sc);
                   1620:        return (val);
                   1621: }
                   1622:
                   1623: void
                   1624: url_ext_miibus_writereg(struct device *dev, int phy, int reg, int data)
                   1625: {
                   1626:        struct url_softc *sc = (void *)dev;
                   1627:
                   1628:        DPRINTF(("%s: %s: enter, phy=%d reg=0x%04x data=0x%04x\n",
                   1629:                 sc->sc_dev.dv_xname, __func__, phy, reg, data));
                   1630:
                   1631:        if (sc->sc_dying) {
                   1632: #ifdef DIAGNOSTIC
                   1633:                printf("%s: %s: dying\n", sc->sc_dev.dv_xname,
                   1634:                       __func__);
                   1635: #endif
                   1636:                return;
                   1637:        }
                   1638:
                   1639:        url_lock_mii(sc);
                   1640:
                   1641:        url_csr_write_2(sc, URL_PHYDAT, data);
                   1642:        url_csr_write_1(sc, URL_PHYADD, phy);
                   1643:        url_csr_write_1(sc, URL_PHYCNT, reg | URL_PHYCNT_RWCR); /* Write */
                   1644:
                   1645:        for (i=0; i < URL_TIMEOUT; i++) {
                   1646:                if (url_csr_read_1(sc, URL_PHYCNT) & URL_PHYCNT_PHYOWN)
                   1647:                        break;
                   1648:        }
                   1649:
                   1650:        if (i == URL_TIMEOUT) {
                   1651:                printf("%s: MII write timed out\n",
                   1652:                       sc->sc_dev.dv_xname);
                   1653:        }
                   1654:
                   1655:        url_unlock_mii(sc);
                   1656:        return;
                   1657: }
                   1658: #endif
                   1659:

CVSweb