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