[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     ! 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