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