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