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