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