]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/usb/if_cue.c
This commit was generated by cvs2svn to compensate for changes in r168988,
[FreeBSD/FreeBSD.git] / sys / dev / usb / if_cue.c
1 /*-
2  * Copyright (c) 1997, 1998, 1999, 2000
3  *      Bill Paul <wpaul@ee.columbia.edu>.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Bill Paul.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30  * THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 /*
37  * CATC USB-EL1210A USB to ethernet driver. Used in the CATC Netmate
38  * adapters and others.
39  *
40  * Written by Bill Paul <wpaul@ee.columbia.edu>
41  * Electrical Engineering Department
42  * Columbia University, New York City
43  */
44
45 /*
46  * The CATC USB-EL1210A provides USB ethernet support at 10Mbps. The
47  * RX filter uses a 512-bit multicast hash table, single perfect entry
48  * for the station address, and promiscuous mode. Unlike the ADMtek
49  * and KLSI chips, the CATC ASIC supports read and write combining
50  * mode where multiple packets can be transfered using a single bulk
51  * transaction, which helps performance a great deal.
52  */
53
54 #include <sys/param.h>
55 #include <sys/systm.h>
56 #include <sys/sockio.h>
57 #include <sys/mbuf.h>
58 #include <sys/malloc.h>
59 #include <sys/kernel.h>
60 #include <sys/module.h>
61 #include <sys/socket.h>
62
63 #include <net/if.h>
64 #include <net/if_arp.h>
65 #include <net/ethernet.h>
66 #include <net/if_dl.h>
67 #include <net/if_types.h>
68
69 #include <net/bpf.h>
70
71 #include <sys/bus.h>
72 #include <machine/bus.h>
73 #if __FreeBSD_version < 500000
74 #include <machine/clock.h>
75 #endif
76
77 #include <dev/usb/usb.h>
78 #include <dev/usb/usbdi.h>
79 #include <dev/usb/usbdi_util.h>
80 #include <dev/usb/usbdivar.h>
81 #include "usbdevs.h"
82 #include <dev/usb/usb_ethersubr.h>
83
84 #include <dev/usb/if_cuereg.h>
85
86 /*
87  * Various supported device vendors/products.
88  */
89 static struct cue_type cue_devs[] = {
90         { USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE },
91         { USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE2 },
92         { USB_VENDOR_SMARTBRIDGES, USB_PRODUCT_SMARTBRIDGES_SMARTLINK },
93         { 0, 0 }
94 };
95
96 static int cue_match(device_t);
97 static int cue_attach(device_t);
98 static int cue_detach(device_t);
99
100 static int cue_encap(struct cue_softc *, struct mbuf *, int);
101 static void cue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
102 static void cue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
103 static void cue_tick(void *);
104 static void cue_rxstart(struct ifnet *);
105 static void cue_start(struct ifnet *);
106 static int cue_ioctl(struct ifnet *, u_long, caddr_t);
107 static void cue_init(void *);
108 static void cue_stop(struct cue_softc *);
109 static void cue_watchdog(struct ifnet *);
110 static void cue_shutdown(device_t);
111
112 static void cue_setmulti(struct cue_softc *);
113 static uint32_t cue_mchash(const uint8_t *);
114 static void cue_reset(struct cue_softc *);
115
116 static int cue_csr_read_1(struct cue_softc *, int);
117 static int cue_csr_write_1(struct cue_softc *, int, int);
118 static int cue_csr_read_2(struct cue_softc *, int);
119 #ifdef notdef
120 static int cue_csr_write_2(struct cue_softc *, int, int);
121 #endif
122 static int cue_mem(struct cue_softc *, int, int, void *, int);
123 static int cue_getmac(struct cue_softc *, void *);
124
125 static device_method_t cue_methods[] = {
126         /* Device interface */
127         DEVMETHOD(device_probe,         cue_match),
128         DEVMETHOD(device_attach,        cue_attach),
129         DEVMETHOD(device_detach,        cue_detach),
130         DEVMETHOD(device_shutdown,      cue_shutdown),
131
132         { 0, 0 }
133 };
134
135 static driver_t cue_driver = {
136         "cue",
137         cue_methods,
138         sizeof(struct cue_softc)
139 };
140
141 static devclass_t cue_devclass;
142
143 DRIVER_MODULE(cue, uhub, cue_driver, cue_devclass, usbd_driver_load, 0);
144 MODULE_DEPEND(cue, usb, 1, 1, 1);
145 MODULE_DEPEND(cue, ether, 1, 1, 1);
146
147 #define CUE_SETBIT(sc, reg, x)                          \
148         cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) | (x))
149
150 #define CUE_CLRBIT(sc, reg, x)                          \
151         cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) & ~(x))
152
153 static int
154 cue_csr_read_1(struct cue_softc *sc, int reg)
155 {
156         usb_device_request_t    req;
157         usbd_status             err;
158         u_int8_t                val = 0;
159
160         if (sc->cue_dying)
161                 return(0);
162
163         CUE_LOCK(sc);
164
165         req.bmRequestType = UT_READ_VENDOR_DEVICE;
166         req.bRequest = CUE_CMD_READREG;
167         USETW(req.wValue, 0);
168         USETW(req.wIndex, reg);
169         USETW(req.wLength, 1);
170
171         err = usbd_do_request(sc->cue_udev, &req, &val);
172
173         CUE_UNLOCK(sc);
174
175         if (err)
176                 return(0);
177
178         return(val);
179 }
180
181 static int
182 cue_csr_read_2(struct cue_softc *sc, int reg)
183 {
184         usb_device_request_t    req;
185         usbd_status             err;
186         u_int16_t               val = 0;
187
188         if (sc->cue_dying)
189                 return(0);
190
191         CUE_LOCK(sc);
192
193         req.bmRequestType = UT_READ_VENDOR_DEVICE;
194         req.bRequest = CUE_CMD_READREG;
195         USETW(req.wValue, 0);
196         USETW(req.wIndex, reg);
197         USETW(req.wLength, 2);
198
199         err = usbd_do_request(sc->cue_udev, &req, &val);
200
201         CUE_UNLOCK(sc);
202
203         if (err)
204                 return(0);
205
206         return(val);
207 }
208
209 static int
210 cue_csr_write_1(struct cue_softc *sc, int reg, int val)
211 {
212         usb_device_request_t    req;
213         usbd_status             err;
214
215         if (sc->cue_dying)
216                 return(0);
217
218         CUE_LOCK(sc);
219
220         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
221         req.bRequest = CUE_CMD_WRITEREG;
222         USETW(req.wValue, val);
223         USETW(req.wIndex, reg);
224         USETW(req.wLength, 0);
225
226         err = usbd_do_request(sc->cue_udev, &req, NULL);
227
228         CUE_UNLOCK(sc);
229
230         if (err)
231                 return(-1);
232
233         return(0);
234 }
235
236 #ifdef notdef
237 static int
238 cue_csr_write_2(struct cue_softc *sc, int reg, int val)
239 {
240         usb_device_request_t    req;
241         usbd_status             err;
242
243         if (sc->cue_dying)
244                 return(0);
245
246         CUE_LOCK(sc);
247
248         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
249         req.bRequest = CUE_CMD_WRITEREG;
250         USETW(req.wValue, val);
251         USETW(req.wIndex, reg);
252         USETW(req.wLength, 0);
253
254         err = usbd_do_request(sc->cue_udev, &req, NULL);
255
256         CUE_UNLOCK(sc);
257
258         if (err)
259                 return(-1);
260
261         return(0);
262 }
263 #endif
264
265 static int
266 cue_mem(struct cue_softc *sc, int cmd, int addr, void *buf, int len)
267 {
268         usb_device_request_t    req;
269         usbd_status             err;
270
271         if (sc->cue_dying)
272                 return(0);
273
274         CUE_LOCK(sc);
275
276         if (cmd == CUE_CMD_READSRAM)
277                 req.bmRequestType = UT_READ_VENDOR_DEVICE;
278         else
279                 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
280         req.bRequest = cmd;
281         USETW(req.wValue, 0);
282         USETW(req.wIndex, addr);
283         USETW(req.wLength, len);
284
285         err = usbd_do_request(sc->cue_udev, &req, buf);
286
287         CUE_UNLOCK(sc);
288
289         if (err)
290                 return(-1);
291
292         return(0);
293 }
294
295 static int
296 cue_getmac(struct cue_softc *sc, void *buf)
297 {
298         usb_device_request_t    req;
299         usbd_status             err;
300
301         if (sc->cue_dying)
302                 return(0);
303
304         CUE_LOCK(sc);
305
306         req.bmRequestType = UT_READ_VENDOR_DEVICE;
307         req.bRequest = CUE_CMD_GET_MACADDR;
308         USETW(req.wValue, 0);
309         USETW(req.wIndex, 0);
310         USETW(req.wLength, ETHER_ADDR_LEN);
311
312         err = usbd_do_request(sc->cue_udev, &req, buf);
313
314         CUE_UNLOCK(sc);
315
316         if (err) {
317                 printf("cue%d: read MAC address failed\n", sc->cue_unit);
318                 return(-1);
319         }
320
321         return(0);
322 }
323
324 #define CUE_BITS        9
325
326 static uint32_t
327 cue_mchash(const uint8_t *addr)
328 {
329         uint32_t crc;
330
331         /* Compute CRC for the address value. */
332         crc = ether_crc32_le(addr, ETHER_ADDR_LEN);
333
334         return (crc & ((1 << CUE_BITS) - 1));
335 }
336
337 static void
338 cue_setmulti(struct cue_softc *sc)
339 {
340         struct ifnet            *ifp;
341         struct ifmultiaddr      *ifma;
342         u_int32_t               h = 0, i;
343
344         ifp = sc->cue_ifp;
345
346         if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
347                 for (i = 0; i < CUE_MCAST_TABLE_LEN; i++)
348                         sc->cue_mctab[i] = 0xFF;
349                 cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR,
350                     &sc->cue_mctab, CUE_MCAST_TABLE_LEN);
351                 return;
352         }
353
354         /* first, zot all the existing hash bits */
355         for (i = 0; i < CUE_MCAST_TABLE_LEN; i++)
356                 sc->cue_mctab[i] = 0;
357
358         /* now program new ones */
359         IF_ADDR_LOCK(ifp);
360 #if __FreeBSD_version >= 500000
361         TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
362 #else
363         LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
364 #endif
365         {
366                 if (ifma->ifma_addr->sa_family != AF_LINK)
367                         continue;
368                 h = cue_mchash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
369                 sc->cue_mctab[h >> 3] |= 1 << (h & 0x7);
370         }
371         IF_ADDR_UNLOCK(ifp);
372
373         /*
374          * Also include the broadcast address in the filter
375          * so we can receive broadcast frames.
376          */
377         if (ifp->if_flags & IFF_BROADCAST) {
378 #if __FreeBSD_version >= 500000
379                 h = cue_mchash(ifp->if_broadcastaddr);
380 #else
381                 h = cue_mchash(etherbroadcastaddr);
382 #endif
383                 sc->cue_mctab[h >> 3] |= 1 << (h & 0x7);
384         }
385
386         cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR,
387             &sc->cue_mctab, CUE_MCAST_TABLE_LEN);
388
389         return;
390 }
391
392 static void
393 cue_reset(struct cue_softc *sc)
394 {
395         usb_device_request_t    req;
396         usbd_status             err;
397
398         if (sc->cue_dying)
399                 return;
400
401         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
402         req.bRequest = CUE_CMD_RESET;
403         USETW(req.wValue, 0);
404         USETW(req.wIndex, 0);
405         USETW(req.wLength, 0);
406         err = usbd_do_request(sc->cue_udev, &req, NULL);
407         if (err)
408                 printf("cue%d: reset failed\n", sc->cue_unit);
409
410         /* Wait a little while for the chip to get its brains in order. */
411         DELAY(1000);
412         return;
413 }
414
415 /*
416  * Probe for a Pegasus chip.
417  */
418 USB_MATCH(cue)
419 {
420         USB_MATCH_START(cue, uaa);
421         struct cue_type                 *t;
422
423         if (!uaa->iface)
424                 return(UMATCH_NONE);
425
426         t = cue_devs;
427         while(t->cue_vid) {
428                 if (uaa->vendor == t->cue_vid &&
429                     uaa->product == t->cue_did) {
430                         return(UMATCH_VENDOR_PRODUCT);
431                 }
432                 t++;
433         }
434
435         return(UMATCH_NONE);
436 }
437
438 /*
439  * Attach the interface. Allocate softc structures, do ifmedia
440  * setup and ethernet/BPF attach.
441  */
442 USB_ATTACH(cue)
443 {
444         USB_ATTACH_START(cue, sc, uaa);
445         char                    devinfo[1024];
446         u_char                  eaddr[ETHER_ADDR_LEN];
447         struct ifnet            *ifp;
448         usb_interface_descriptor_t      *id;
449         usb_endpoint_descriptor_t       *ed;
450         int                     i;
451
452         bzero(sc, sizeof(struct cue_softc));
453         sc->cue_dev = self;
454         sc->cue_iface = uaa->iface;
455         sc->cue_udev = uaa->device;
456         sc->cue_unit = device_get_unit(self);
457
458         if (usbd_set_config_no(sc->cue_udev, CUE_CONFIG_NO, 0)) {
459                 printf("cue%d: getting interface handle failed\n",
460                     sc->cue_unit);
461                 USB_ATTACH_ERROR_RETURN;
462         }
463
464         id = usbd_get_interface_descriptor(uaa->iface);
465
466         usbd_devinfo(uaa->device, 0, devinfo);
467         device_set_desc_copy(self, devinfo);
468         printf("%s: %s\n", device_get_nameunit(self), devinfo);
469
470         /* Find endpoints. */
471         for (i = 0; i < id->bNumEndpoints; i++) {
472                 ed = usbd_interface2endpoint_descriptor(uaa->iface, i);
473                 if (!ed) {
474                         printf("cue%d: couldn't get ep %d\n",
475                             sc->cue_unit, i);
476                         USB_ATTACH_ERROR_RETURN;
477                 }
478                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
479                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
480                         sc->cue_ed[CUE_ENDPT_RX] = ed->bEndpointAddress;
481                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
482                            UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
483                         sc->cue_ed[CUE_ENDPT_TX] = ed->bEndpointAddress;
484                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
485                            UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
486                         sc->cue_ed[CUE_ENDPT_INTR] = ed->bEndpointAddress;
487                 }
488         }
489
490 #if __FreeBSD_version >= 500000
491         mtx_init(&sc->cue_mtx, device_get_nameunit(self), MTX_NETWORK_LOCK,
492             MTX_DEF | MTX_RECURSE);
493 #endif
494         CUE_LOCK(sc);
495
496 #ifdef notdef
497         /* Reset the adapter. */
498         cue_reset(sc);
499 #endif
500         /*
501          * Get station address.
502          */
503         cue_getmac(sc, &eaddr);
504
505         ifp = sc->cue_ifp = if_alloc(IFT_ETHER);
506         if (ifp == NULL) {
507                 printf("cue%d: can not if_alloc()\n", sc->cue_unit);
508                 CUE_UNLOCK(sc);
509 #if __FreeBSD_version >= 500000
510                 mtx_destroy(&sc->cue_mtx);
511 #endif
512                 USB_ATTACH_ERROR_RETURN;
513         }
514         ifp->if_softc = sc;
515         if_initname(ifp, "cue", sc->cue_unit);
516         ifp->if_mtu = ETHERMTU;
517         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST |
518             IFF_NEEDSGIANT;
519         ifp->if_ioctl = cue_ioctl;
520         ifp->if_start = cue_start;
521         ifp->if_watchdog = cue_watchdog;
522         ifp->if_init = cue_init;
523         ifp->if_baudrate = 10000000;
524         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
525
526         sc->cue_qdat.ifp = ifp;
527         sc->cue_qdat.if_rxstart = cue_rxstart;
528
529         /*
530          * Call MI attach routine.
531          */
532 #if __FreeBSD_version >= 500000
533         ether_ifattach(ifp, eaddr);
534 #else
535         ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
536 #endif
537         callout_handle_init(&sc->cue_stat_ch);
538         usb_register_netisr();
539         sc->cue_dying = 0;
540
541         CUE_UNLOCK(sc);
542         USB_ATTACH_SUCCESS_RETURN;
543 }
544
545 static int
546 cue_detach(device_t dev)
547 {
548         struct cue_softc        *sc;
549         struct ifnet            *ifp;
550
551         sc = device_get_softc(dev);
552         CUE_LOCK(sc);
553         ifp = sc->cue_ifp;
554
555         sc->cue_dying = 1;
556         untimeout(cue_tick, sc, sc->cue_stat_ch);
557 #if __FreeBSD_version >= 500000
558         ether_ifdetach(ifp);
559         if_free(ifp);
560 #else
561         ether_ifdetach(ifp, ETHER_BPF_SUPPORTED);
562 #endif
563
564         if (sc->cue_ep[CUE_ENDPT_TX] != NULL)
565                 usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_TX]);
566         if (sc->cue_ep[CUE_ENDPT_RX] != NULL)
567                 usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_RX]);
568         if (sc->cue_ep[CUE_ENDPT_INTR] != NULL)
569                 usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_INTR]);
570
571         CUE_UNLOCK(sc);
572 #if __FreeBSD_version >= 500000
573         mtx_destroy(&sc->cue_mtx);
574 #endif
575
576         return(0);
577 }
578
579 static void
580 cue_rxstart(struct ifnet *ifp)
581 {
582         struct cue_softc        *sc;
583         struct ue_chain *c;
584
585         sc = ifp->if_softc;
586         CUE_LOCK(sc);
587         c = &sc->cue_cdata.ue_rx_chain[sc->cue_cdata.ue_rx_prod];
588
589         c->ue_mbuf = usb_ether_newbuf();
590         if (c->ue_mbuf == NULL) {
591                 printf("%s: no memory for rx list "
592                     "-- packet dropped!\n", device_get_nameunit(sc->cue_dev));
593                 ifp->if_ierrors++;
594                 CUE_UNLOCK(sc);
595                 return;
596         }
597
598         /* Setup new transfer. */
599         usbd_setup_xfer(c->ue_xfer, sc->cue_ep[CUE_ENDPT_RX],
600             c, mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK,
601             USBD_NO_TIMEOUT, cue_rxeof);
602         usbd_transfer(c->ue_xfer);
603         CUE_UNLOCK(sc);
604
605         return;
606 }
607
608 /*
609  * A frame has been uploaded: pass the resulting mbuf chain up to
610  * the higher level protocols.
611  */
612 static void
613 cue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
614 {
615         struct cue_softc        *sc;
616         struct ue_chain *c;
617         struct mbuf             *m;
618         struct ifnet            *ifp;
619         int                     total_len = 0;
620         u_int16_t               len;
621
622         c = priv;
623         sc = c->ue_sc;
624         CUE_LOCK(sc);
625         ifp = sc->cue_ifp;
626
627         if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
628                 CUE_UNLOCK(sc);
629                 return;
630         }
631
632         if (status != USBD_NORMAL_COMPLETION) {
633                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
634                         CUE_UNLOCK(sc);
635                         return;
636                 }
637                 if (usbd_ratecheck(&sc->cue_rx_notice))
638                         printf("cue%d: usb error on rx: %s\n", sc->cue_unit,
639                             usbd_errstr(status));
640                 if (status == USBD_STALLED)
641                         usbd_clear_endpoint_stall(sc->cue_ep[CUE_ENDPT_RX]);
642                 goto done;
643         }
644
645         usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
646
647         m = c->ue_mbuf;
648         len = *mtod(m, u_int16_t *);
649
650         /* No errors; receive the packet. */
651         total_len = len;
652
653         if (len < sizeof(struct ether_header)) {
654                 ifp->if_ierrors++;
655                 goto done;
656         }
657
658         ifp->if_ipackets++;
659         m_adj(m, sizeof(u_int16_t));
660         m->m_pkthdr.rcvif = (void *)&sc->cue_qdat;
661         m->m_pkthdr.len = m->m_len = total_len;
662
663         /* Put the packet on the special USB input queue. */
664         usb_ether_input(m);
665         CUE_UNLOCK(sc);
666
667         return;
668 done:
669         /* Setup new transfer. */
670         usbd_setup_xfer(c->ue_xfer, sc->cue_ep[CUE_ENDPT_RX],
671             c, mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK,
672             USBD_NO_TIMEOUT, cue_rxeof);
673         usbd_transfer(c->ue_xfer);
674         CUE_UNLOCK(sc);
675
676         return;
677 }
678
679 /*
680  * A frame was downloaded to the chip. It's safe for us to clean up
681  * the list buffers.
682  */
683
684 static void
685 cue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
686 {
687         struct cue_softc        *sc;
688         struct ue_chain *c;
689         struct ifnet            *ifp;
690         usbd_status             err;
691
692         c = priv;
693         sc = c->ue_sc;
694         CUE_LOCK(sc);
695         ifp = sc->cue_ifp;
696
697         if (status != USBD_NORMAL_COMPLETION) {
698                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
699                         CUE_UNLOCK(sc);
700                         return;
701                 }
702                 printf("cue%d: usb error on tx: %s\n", sc->cue_unit,
703                     usbd_errstr(status));
704                 if (status == USBD_STALLED)
705                         usbd_clear_endpoint_stall(sc->cue_ep[CUE_ENDPT_TX]);
706                 CUE_UNLOCK(sc);
707                 return;
708         }
709
710         ifp->if_timer = 0;
711         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
712         usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &err);
713
714         if (c->ue_mbuf != NULL) {
715                 c->ue_mbuf->m_pkthdr.rcvif = ifp;
716                 usb_tx_done(c->ue_mbuf);
717                 c->ue_mbuf = NULL;
718         }
719
720         if (err)
721                 ifp->if_oerrors++;
722         else
723                 ifp->if_opackets++;
724
725         CUE_UNLOCK(sc);
726
727         return;
728 }
729
730 static void
731 cue_tick(void *xsc)
732 {
733         struct cue_softc        *sc;
734         struct ifnet            *ifp;
735
736         sc = xsc;
737
738         if (sc == NULL)
739                 return;
740
741         CUE_LOCK(sc);
742
743         ifp = sc->cue_ifp;
744
745         ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_SINGLECOLL);
746         ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_MULTICOLL);
747         ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_EXCESSCOLL);
748
749         if (cue_csr_read_2(sc, CUE_RX_FRAMEERR))
750                 ifp->if_ierrors++;
751
752         sc->cue_stat_ch = timeout(cue_tick, sc, hz);
753
754         CUE_UNLOCK(sc);
755
756         return;
757 }
758
759 static int
760 cue_encap(struct cue_softc *sc, struct mbuf *m, int idx)
761 {
762         int                     total_len;
763         struct ue_chain *c;
764         usbd_status             err;
765
766         c = &sc->cue_cdata.ue_tx_chain[idx];
767
768         /*
769          * Copy the mbuf data into a contiguous buffer, leaving two
770          * bytes at the beginning to hold the frame length.
771          */
772         m_copydata(m, 0, m->m_pkthdr.len, c->ue_buf + 2);
773         c->ue_mbuf = m;
774
775         total_len = m->m_pkthdr.len + 2;
776
777         /* The first two bytes are the frame length */
778         c->ue_buf[0] = (u_int8_t)m->m_pkthdr.len;
779         c->ue_buf[1] = (u_int8_t)(m->m_pkthdr.len >> 8);
780
781         usbd_setup_xfer(c->ue_xfer, sc->cue_ep[CUE_ENDPT_TX],
782             c, c->ue_buf, total_len, 0, 10000, cue_txeof);
783
784         /* Transmit */
785         err = usbd_transfer(c->ue_xfer);
786         if (err != USBD_IN_PROGRESS) {
787                 cue_stop(sc);
788                 return(EIO);
789         }
790
791         sc->cue_cdata.ue_tx_cnt++;
792
793         return(0);
794 }
795
796 static void
797 cue_start(struct ifnet *ifp)
798 {
799         struct cue_softc        *sc;
800         struct mbuf             *m_head = NULL;
801
802         sc = ifp->if_softc;
803         CUE_LOCK(sc);
804
805         if (ifp->if_drv_flags & IFF_DRV_OACTIVE) {
806                 CUE_UNLOCK(sc);
807                 return;
808         }
809
810         IF_DEQUEUE(&ifp->if_snd, m_head);
811         if (m_head == NULL) {
812                 CUE_UNLOCK(sc);
813                 return;
814         }
815
816         if (cue_encap(sc, m_head, 0)) {
817                 IF_PREPEND(&ifp->if_snd, m_head);
818                 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
819                 CUE_UNLOCK(sc);
820                 return;
821         }
822
823         /*
824          * If there's a BPF listener, bounce a copy of this frame
825          * to him.
826          */
827         BPF_MTAP(ifp, m_head);
828
829         ifp->if_drv_flags |= IFF_DRV_OACTIVE;
830
831         /*
832          * Set a timeout in case the chip goes out to lunch.
833          */
834         ifp->if_timer = 5;
835         CUE_UNLOCK(sc);
836
837         return;
838 }
839
840 static void
841 cue_init(void *xsc)
842 {
843         struct cue_softc        *sc = xsc;
844         struct ifnet            *ifp = sc->cue_ifp;
845         struct ue_chain *c;
846         usbd_status             err;
847         int                     i;
848
849         if (ifp->if_drv_flags & IFF_DRV_RUNNING)
850                 return;
851
852         CUE_LOCK(sc);
853
854         /*
855          * Cancel pending I/O and free all RX/TX buffers.
856          */
857 #ifdef foo
858         cue_reset(sc);
859 #endif
860
861         /* Set MAC address */
862         for (i = 0; i < ETHER_ADDR_LEN; i++)
863                 cue_csr_write_1(sc, CUE_PAR0 - i, IF_LLADDR(sc->cue_ifp)[i]);
864
865         /* Enable RX logic. */
866         cue_csr_write_1(sc, CUE_ETHCTL, CUE_ETHCTL_RX_ON|CUE_ETHCTL_MCAST_ON);
867
868          /* If we want promiscuous mode, set the allframes bit. */
869         if (ifp->if_flags & IFF_PROMISC) {
870                 CUE_SETBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
871         } else {
872                 CUE_CLRBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
873         }
874
875         /* Init TX ring. */
876         if (usb_ether_tx_list_init(sc, &sc->cue_cdata,
877             sc->cue_udev) == ENOBUFS) {
878                 printf("cue%d: tx list init failed\n", sc->cue_unit);
879                 CUE_UNLOCK(sc);
880                 return;
881         }
882
883         /* Init RX ring. */
884         if (usb_ether_rx_list_init(sc, &sc->cue_cdata,
885             sc->cue_udev) == ENOBUFS) {
886                 printf("cue%d: rx list init failed\n", sc->cue_unit);
887                 CUE_UNLOCK(sc);
888                 return;
889         }
890
891         /* Load the multicast filter. */
892         cue_setmulti(sc);
893
894         /*
895          * Set the number of RX and TX buffers that we want
896          * to reserve inside the ASIC.
897          */
898         cue_csr_write_1(sc, CUE_RX_BUFPKTS, CUE_RX_FRAMES);
899         cue_csr_write_1(sc, CUE_TX_BUFPKTS, CUE_TX_FRAMES);
900
901         /* Set advanced operation modes. */
902         cue_csr_write_1(sc, CUE_ADVANCED_OPMODES,
903             CUE_AOP_EMBED_RXLEN|0x01); /* 1 wait state */
904
905         /* Program the LED operation. */
906         cue_csr_write_1(sc, CUE_LEDCTL, CUE_LEDCTL_FOLLOW_LINK);
907
908         /* Open RX and TX pipes. */
909         err = usbd_open_pipe(sc->cue_iface, sc->cue_ed[CUE_ENDPT_RX],
910             USBD_EXCLUSIVE_USE, &sc->cue_ep[CUE_ENDPT_RX]);
911         if (err) {
912                 printf("cue%d: open rx pipe failed: %s\n",
913                     sc->cue_unit, usbd_errstr(err));
914                 CUE_UNLOCK(sc);
915                 return;
916         }
917         err = usbd_open_pipe(sc->cue_iface, sc->cue_ed[CUE_ENDPT_TX],
918             USBD_EXCLUSIVE_USE, &sc->cue_ep[CUE_ENDPT_TX]);
919         if (err) {
920                 printf("cue%d: open tx pipe failed: %s\n",
921                     sc->cue_unit, usbd_errstr(err));
922                 CUE_UNLOCK(sc);
923                 return;
924         }
925
926         /* Start up the receive pipe. */
927         for (i = 0; i < UE_RX_LIST_CNT; i++) {
928                 c = &sc->cue_cdata.ue_rx_chain[i];
929                 usbd_setup_xfer(c->ue_xfer, sc->cue_ep[CUE_ENDPT_RX],
930                     c, mtod(c->ue_mbuf, char *), UE_BUFSZ,
931                     USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, cue_rxeof);
932                 usbd_transfer(c->ue_xfer);
933         }
934
935         ifp->if_drv_flags |= IFF_DRV_RUNNING;
936         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
937
938         CUE_UNLOCK(sc);
939
940         sc->cue_stat_ch = timeout(cue_tick, sc, hz);
941
942         return;
943 }
944
945 static int
946 cue_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
947 {
948         struct cue_softc        *sc = ifp->if_softc;
949         int                     error = 0;
950
951         CUE_LOCK(sc);
952
953         switch(command) {
954         case SIOCSIFFLAGS:
955                 if (ifp->if_flags & IFF_UP) {
956                         if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
957                             ifp->if_flags & IFF_PROMISC &&
958                             !(sc->cue_if_flags & IFF_PROMISC)) {
959                                 CUE_SETBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
960                                 cue_setmulti(sc);
961                         } else if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
962                             !(ifp->if_flags & IFF_PROMISC) &&
963                             sc->cue_if_flags & IFF_PROMISC) {
964                                 CUE_CLRBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
965                                 cue_setmulti(sc);
966                         } else if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
967                                 cue_init(sc);
968                 } else {
969                         if (ifp->if_drv_flags & IFF_DRV_RUNNING)
970                                 cue_stop(sc);
971                 }
972                 sc->cue_if_flags = ifp->if_flags;
973                 error = 0;
974                 break;
975         case SIOCADDMULTI:
976         case SIOCDELMULTI:
977                 cue_setmulti(sc);
978                 error = 0;
979                 break;
980         default:
981                 error = ether_ioctl(ifp, command, data);
982                 break;
983         }
984
985         CUE_UNLOCK(sc);
986
987         return(error);
988 }
989
990 static void
991 cue_watchdog(struct ifnet *ifp)
992 {
993         struct cue_softc        *sc;
994         struct ue_chain *c;
995         usbd_status             stat;
996
997         sc = ifp->if_softc;
998         CUE_LOCK(sc);
999
1000         ifp->if_oerrors++;
1001         printf("cue%d: watchdog timeout\n", sc->cue_unit);
1002
1003         c = &sc->cue_cdata.ue_tx_chain[0];
1004         usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &stat);
1005         cue_txeof(c->ue_xfer, c, stat);
1006
1007         if (ifp->if_snd.ifq_head != NULL)
1008                 cue_start(ifp);
1009         CUE_UNLOCK(sc);
1010
1011         return;
1012 }
1013
1014 /*
1015  * Stop the adapter and free any mbufs allocated to the
1016  * RX and TX lists.
1017  */
1018 static void
1019 cue_stop(struct cue_softc *sc)
1020 {
1021         usbd_status             err;
1022         struct ifnet            *ifp;
1023
1024         CUE_LOCK(sc);
1025
1026         ifp = sc->cue_ifp;
1027         ifp->if_timer = 0;
1028
1029         cue_csr_write_1(sc, CUE_ETHCTL, 0);
1030         cue_reset(sc);
1031         untimeout(cue_tick, sc, sc->cue_stat_ch);
1032
1033         /* Stop transfers. */
1034         if (sc->cue_ep[CUE_ENDPT_RX] != NULL) {
1035                 err = usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_RX]);
1036                 if (err) {
1037                         printf("cue%d: abort rx pipe failed: %s\n",
1038                         sc->cue_unit, usbd_errstr(err));
1039                 }
1040                 err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_RX]);
1041                 if (err) {
1042                         printf("cue%d: close rx pipe failed: %s\n",
1043                         sc->cue_unit, usbd_errstr(err));
1044                 }
1045                 sc->cue_ep[CUE_ENDPT_RX] = NULL;
1046         }
1047
1048         if (sc->cue_ep[CUE_ENDPT_TX] != NULL) {
1049                 err = usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_TX]);
1050                 if (err) {
1051                         printf("cue%d: abort tx pipe failed: %s\n",
1052                         sc->cue_unit, usbd_errstr(err));
1053                 }
1054                 err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_TX]);
1055                 if (err) {
1056                         printf("cue%d: close tx pipe failed: %s\n",
1057                             sc->cue_unit, usbd_errstr(err));
1058                 }
1059                 sc->cue_ep[CUE_ENDPT_TX] = NULL;
1060         }
1061
1062         if (sc->cue_ep[CUE_ENDPT_INTR] != NULL) {
1063                 err = usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_INTR]);
1064                 if (err) {
1065                         printf("cue%d: abort intr pipe failed: %s\n",
1066                         sc->cue_unit, usbd_errstr(err));
1067                 }
1068                 err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_INTR]);
1069                 if (err) {
1070                         printf("cue%d: close intr pipe failed: %s\n",
1071                             sc->cue_unit, usbd_errstr(err));
1072                 }
1073                 sc->cue_ep[CUE_ENDPT_INTR] = NULL;
1074         }
1075
1076         /* Free RX resources. */
1077         usb_ether_rx_list_free(&sc->cue_cdata);
1078         /* Free TX resources. */
1079         usb_ether_tx_list_free(&sc->cue_cdata);
1080
1081         ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1082         CUE_UNLOCK(sc);
1083
1084         return;
1085 }
1086
1087 /*
1088  * Stop all chip I/O so that the kernel's probe routines don't
1089  * get confused by errant DMAs when rebooting.
1090  */
1091 static void
1092 cue_shutdown(device_t dev)
1093 {
1094         struct cue_softc        *sc;
1095
1096         sc = device_get_softc(dev);
1097
1098         CUE_LOCK(sc);
1099         cue_reset(sc);
1100         cue_stop(sc);
1101         CUE_UNLOCK(sc);
1102
1103         return;
1104 }