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