1: /*
2: * Copyright (c) 1998, Larry Lile
3: * All rights reserved.
4: *
5: * For latest sources and information on this driver, please
6: * go to http://anarchy.stdio.com.
7: *
8: * Questions, comments or suggestions should be directed to
9: * Larry Lile <lile@stdio.com>.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice unmodified, this list of conditions, and the following
16: * disclaimer.
17: * 2. Redistributions in binary form must reproduce the above copyright
18: * notice, this list of conditions and the following disclaimer in the
19: * documentation and/or other materials provided with the distribution.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * $FreeBSD: src/sys/contrib/dev/oltr/if_oltr.c,v 1.11.2.5 2001/10/20 04:15:21 mdodd Exp $
34: * $DragonFly: src/sys/contrib/dev/oltr/if_oltr.c,v 1.8 2004/01/06 01:40:45 dillon Exp $
35: */
36:
37: #include <sys/param.h>
38: #include <sys/systm.h>
39: #include <sys/sockio.h>
40: #include <sys/mbuf.h>
41: #include <sys/malloc.h>
42: #include <sys/kernel.h>
43: #include <sys/socket.h>
44: #include <sys/param.h>
45:
46: #include <net/if.h>
47: #include <net/if_arp.h>
48: #include <net/iso88025.h>
49: #include <net/ethernet.h>
50: #include <net/if_dl.h>
51: #include <net/if_media.h>
52: #include <net/iso88025.h>
53:
54: #if (__FreeBSD_version < 400000)
55: #include <bpfilter.h>
56: #endif
57:
58: #if (NBPFILTER > 0) || (__FreeBSD_version > 400000)
59: #include <net/bpf.h>
60: #endif
61:
62: #include <vm/vm.h> /* for vtophys */
63: #include <vm/pmap.h> /* for vtophys */
64: #include <machine/bus_memio.h>
65: #include <machine/bus_pio.h>
66: #include <machine/bus.h>
67: #include <machine/resource.h>
68: #include <machine/clock.h>
69: #include <sys/bus.h>
70: #include <sys/rman.h>
71:
72: #include <bus/pci/pcireg.h>
73: #include <bus/pci/pcivar.h>
74:
75: #include "contrib/dev/oltr/trlld.h"
76:
77: /*#define DEBUG_MASK DEBUG_POLL*/
78:
79: #ifndef DEBUG_MASK
80: #define DEBUG_MASK 0x0000
81: #endif
82:
83: #define DEBUG_POLL 0x0001
84: #define DEBUG_INT 0x0002
85: #define DEBUG_INIT 0x0004
86: #define DEBUG_FN_ENT 0x8000
87:
88: #define PCI_VENDOR_OLICOM 0x108D
89:
90: #define MIN3(A,B,C) (MIN(A, (MIN(B, C))))
91:
92: char *AdapterName[] = {
93: /* 0 */ "Olicom XT Adapter [unsupported]",
94: /* 1 */ "Olicom OC-3115",
95: /* 2 */ "Olicom ISA 16/4 Adapter (OC-3117)",
96: /* 3 */ "Olicom ISA 16/4 Adapter (OC-3118)",
97: /* 4 */ "Olicom MCA 16/4 Adapter (OC-3129) [unsupported]",
98: /* 5 */ "Olicom MCA 16/4 Adapter (OC-3129) [unsupported]",
99: /* 6 */ "Olicom MCA 16/4 Adapter (OC-3129) [unsupported]",
100: /* 7 */ "Olicom EISA 16/4 Adapter (OC-3133)",
101: /* 8 */ "Olicom EISA 16/4 Adapter (OC-3133)",
102: /* 9 */ "Olicom EISA 16/4 Server Adapter (OC-3135)",
103: /* 10 */ "Olicom PCI 16/4 Adapter (OC-3136)",
104: /* 11 */ "Olicom PCI 16/4 Adapter (OC-3136)",
105: /* 12 */ "Olicom PCI/II 16/4 Adapter (OC-3137)",
106: /* 13 */ "Olicom PCI 16/4 Adapter (OC-3139)",
107: /* 14 */ "Olicom RapidFire 3140 16/4 PCI Adapter (OC-3140)",
108: /* 15 */ "Olicom RapidFire 3141 Fiber Adapter (OC-3141)",
109: /* 16 */ "Olicom PCMCIA 16/4 Adapter (OC-3220) [unsupported]",
110: /* 17 */ "Olicom PCMCIA 16/4 Adapter (OC-3121, OC-3230, OC-3232) [unsupported]",
111: /* 18 */ "Olicom PCMCIA 16/4 Adapter (OC-3250)",
112: /* 19 */ "Olicom RapidFire 3540 100/16/4 Adapter (OC-3540)"
113: };
114:
115: /*
116: * Glue function prototypes for PMW kit IO
117: */
118:
119: #ifndef TRlldInlineIO
120: static void DriverOutByte (unsigned short, unsigned char);
121: static void DriverOutWord (unsigned short, unsigned short);
122: static void DriverOutDword (unsigned short, unsigned long);
123: static void DriverRepOutByte (unsigned short, unsigned char *, int);
124: static void DriverRepOutWord (unsigned short, unsigned short *, int);
125: static void DriverRepOutDword (unsigned short, unsigned long *, int);
126: static unsigned char DriverInByte (unsigned short);
127: static unsigned short DriverInWord (unsigned short);
128: static unsigned long DriverInDword (unsigned short);
129: static void DriverRepInByte (unsigned short, unsigned char *, int);
130: static void DriverRepInWord (unsigned short, unsigned short *, int);
131: static void DriverRepInDword (unsigned short, unsigned long *, int);
132: #endif /*TRlldInlineIO*/
133: static void DriverSuspend (unsigned short);
134: static void DriverStatus (void *, TRlldStatus_t *);
135: static void DriverCloseCompleted (void *);
136: static void DriverStatistics (void *, TRlldStatistics_t *);
137: static void DriverTransmitFrameCompleted (void *, void *, int);
138: static void DriverReceiveFrameCompleted (void *, int, int, void *, int);
139:
140: static TRlldDriver_t LldDriver = {
141: TRLLD_VERSION,
142: #ifndef TRlldInlineIO
143: DriverOutByte,
144: DriverOutWord,
145: DriverOutDword,
146: DriverRepOutByte,
147: DriverRepOutWord,
148: DriverRepOutDword,
149: DriverInByte,
150: DriverInWord,
151: DriverInDword,
152: DriverRepInByte,
153: DriverRepInWord,
154: DriverRepInDword,
155: #endif /*TRlldInlineIO*/
156: DriverSuspend,
157: DriverStatus,
158: DriverCloseCompleted,
159: DriverStatistics,
160: DriverTransmitFrameCompleted,
161: DriverReceiveFrameCompleted,
162: };
163:
164: struct oltr_rx_buf {
165: int index;
166: char *data;
167: u_long address;
168: };
169:
170: struct oltr_tx_buf {
171: int index;
172: char *data;
173: u_long address;
174: };
175:
176: #define RING_BUFFER_LEN 16
177: #define RING_BUFFER(x) ((RING_BUFFER_LEN - 1) & x)
178: #define RX_BUFFER_LEN 2048
179: #define TX_BUFFER_LEN 2048
180:
181: struct oltr_softc {
182: struct arpcom arpcom;
183: struct ifmedia ifmedia;
184: bus_space_handle_t oltr_bhandle;
185: bus_space_tag_t oltr_btag;
186: void *oltr_intrhand;
187: struct resource *oltr_irq;
188: struct resource *oltr_res;
189: int unit;
190: int state;
191: #define OL_UNKNOWN 0
192: #define OL_INIT 1
193: #define OL_READY 2
194: #define OL_CLOSING 3
195: #define OL_CLOSED 4
196: #define OL_OPENING 5
197: #define OL_OPEN 6
198: #define OL_PROMISC 7
199: #define OL_DEAD 8
200: struct oltr_rx_buf rx_ring[RING_BUFFER_LEN];
201: int tx_head, tx_avail, tx_frame;
202: struct oltr_tx_buf tx_ring[RING_BUFFER_LEN];
203: TRlldTransmit_t frame_ring[RING_BUFFER_LEN];
204: struct mbuf *restart;
205: TRlldAdapter_t TRlldAdapter;
206: TRlldStatistics_t statistics;
207: TRlldStatistics_t current;
208: TRlldAdapterConfig_t config;
209: u_short AdapterMode;
210: u_long GroupAddress;
211: u_long FunctionalAddress;
212: struct callout_handle oltr_poll_ch;
213: /*struct callout_handle oltr_stat_ch;*/
214: void *work_memory;
215: };
216:
217: #define SELF_TEST_POLLS 32
218:
219: void oltr_poll (void *);
220: /*void oltr_stat (void *);*/
221:
222: static void oltr_start (struct ifnet *);
223: static void oltr_stop (struct oltr_softc *);
224: static void oltr_close (struct oltr_softc *);
225: static void oltr_init (void *);
226: static int oltr_ioctl (struct ifnet *, u_long, caddr_t);
227: static void oltr_intr (void *);
228: static int oltr_ifmedia_upd (struct ifnet *);
229: static void oltr_ifmedia_sts (struct ifnet *, struct ifmediareq *);
230:
231: #if __FreeBSD_version > 400000
232:
233: static int oltr_pci_probe (device_t);
234: static int oltr_pci_attach (device_t);
235: static int oltr_pci_detach (device_t);
236: static void oltr_pci_shutdown (device_t);
237:
238: static device_method_t oltr_methods[] = {
239: DEVMETHOD(device_probe, oltr_pci_probe),
240: DEVMETHOD(device_attach, oltr_pci_attach),
241: DEVMETHOD(device_detach, oltr_pci_detach),
242: DEVMETHOD(device_shutdown, oltr_pci_shutdown),
243: { 0, 0 }
244: };
245:
246: static driver_t oltr_driver = {
247: "oltr",
248: oltr_methods,
249: sizeof(struct oltr_softc)
250: };
251:
252: static devclass_t oltr_devclass;
253:
254: DRIVER_MODULE(oltr, pci, oltr_driver, oltr_devclass, 0, 0);
255:
256: static int
257: oltr_pci_probe(device_t dev)
258: {
259: int i, rc;
260: char PCIConfigHeader[64];
261: TRlldAdapterConfig_t config;
262:
263: if ((pci_get_vendor(dev) == PCI_VENDOR_OLICOM) &&
264: ((pci_get_device(dev) == 0x0001) ||
265: (pci_get_device(dev) == 0x0004) ||
266: (pci_get_device(dev) == 0x0005) ||
267: (pci_get_device(dev) == 0x0007) ||
268: (pci_get_device(dev) == 0x0008))) {
269:
270: for (i = 0; i < sizeof(PCIConfigHeader); i++)
271: PCIConfigHeader[i] = pci_read_config(dev, i, 1);
272:
273: rc = TRlldPCIConfig(&LldDriver, &config, PCIConfigHeader);
274: if (rc == TRLLD_PCICONFIG_FAIL) {
275: device_printf(dev, "TRlldPciConfig failed!\n");
276: return(ENXIO);
277: }
278: if (rc == TRLLD_PCICONFIG_VERSION) {
279: device_printf(dev, "wrong LLD version\n");
280: return(ENXIO);
281: }
282: device_set_desc(dev, AdapterName[config.type]);
283: return(0);
284: }
285: return(ENXIO);
286: }
287:
288: static int
289: oltr_pci_attach(device_t dev)
290: {
291: int i, s, rc = 0, rid,
292: scratch_size;
293: int media = IFM_TOKEN|IFM_TOK_UTP16;
294: u_long command;
295: char PCIConfigHeader[64];
296: struct oltr_softc *sc = device_get_softc(dev);
297: struct ifnet *ifp = &sc->arpcom.ac_if;
298:
299: s = splimp();
300:
301: bzero(sc, sizeof(struct oltr_softc));
302: sc->unit = device_get_unit(dev);
303: sc->state = OL_UNKNOWN;
304:
305: for (i = 0; i < sizeof(PCIConfigHeader); i++)
306: PCIConfigHeader[i] = pci_read_config(dev, i, 1);
307:
308: switch(TRlldPCIConfig(&LldDriver, &sc->config, PCIConfigHeader)) {
309: case TRLLD_PCICONFIG_OK:
310: break;
311: case TRLLD_PCICONFIG_SET_COMMAND:
312: device_printf(dev, "enabling bus master mode\n");
313: command = pci_read_config(dev, PCIR_COMMAND, 4);
314: pci_write_config(dev, PCIR_COMMAND,
315: (command | PCIM_CMD_BUSMASTEREN), 4);
316: command = pci_read_config(dev, PCIR_COMMAND, 4);
317: if (!(command & PCIM_CMD_BUSMASTEREN)) {
318: device_printf(dev, "failed to enable bus master mode\n");
319: goto config_failed;
320: }
321: break;
322: case TRLLD_PCICONFIG_FAIL:
323: device_printf(dev, "TRlldPciConfig failed!\n");
324: goto config_failed;
325: break;
326: case TRLLD_PCICONFIG_VERSION:
327: device_printf(dev, "wrong LLD version\n");
328: goto config_failed;
329: break;
330: }
331: device_printf(dev, "MAC address %6D\n", sc->config.macaddress, ":");
332:
333: scratch_size = TRlldAdapterSize();
334: if (bootverbose)
335: device_printf(dev, "adapter memory block size %d bytes\n", scratch_size);
336: sc->TRlldAdapter = (TRlldAdapter_t)malloc(scratch_size, M_DEVBUF, M_NOWAIT);
337: if (sc->TRlldAdapter == NULL) {
338: device_printf(dev, "couldn't allocate scratch buffer (%d bytes)\n", scratch_size);
339: goto config_failed;
340: }
341:
342: /*
343: * Allocate RX/TX Pools
344: */
345: for (i = 0; i < RING_BUFFER_LEN; i++) {
346: sc->rx_ring[i].index = i;
347: sc->rx_ring[i].data = (char *)malloc(RX_BUFFER_LEN, M_DEVBUF, M_NOWAIT);
348: sc->rx_ring[i].address = vtophys(sc->rx_ring[i].data);
349: sc->tx_ring[i].index = i;
350: sc->tx_ring[i].data = (char *)malloc(TX_BUFFER_LEN, M_DEVBUF, M_NOWAIT);
351: sc->tx_ring[i].address = vtophys(sc->tx_ring[i].data);
352: if ((!sc->rx_ring[i].data) || (!sc->tx_ring[i].data)) {
353: device_printf(dev, "unable to allocate ring buffers\n");
354: while (i > 0) {
355: if (sc->rx_ring[i].data)
356: free(sc->rx_ring[i].data, M_DEVBUF);
357: if (sc->tx_ring[i].data)
358: free(sc->tx_ring[i].data, M_DEVBUF);
359: i--;
360: }
361: goto config_failed;
362: }
363: }
364:
365: /*
366: * Allocate interrupt and DMA channel
367: */
368: rid = 0;
369: sc->oltr_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
370: (sc->config.mode & TRLLD_MODE_SHARE_INTERRUPT ? RF_ACTIVE | RF_SHAREABLE : RF_ACTIVE));
371: if (sc->oltr_irq == NULL) {
372: device_printf(dev, "couldn't map interrupt\n");
373: goto config_failed;
374: }
375: if (bus_setup_intr(dev, sc->oltr_irq, INTR_TYPE_NET, oltr_intr, sc, &sc->oltr_intrhand)) {
376: device_printf(dev, "couldn't setup interrupt\n");
377: bus_release_resource(dev, SYS_RES_IRQ, 0, sc->oltr_irq);
378: goto config_failed;
379: }
380:
381: /*
382: * Do the ifnet initialization
383: */
384: ifp->if_softc = sc;
385: if_initname(ifp, "oltr", device_get_unit(dev));
386: ifp->if_output = iso88025_output;
387: ifp->if_init = oltr_init;
388: ifp->if_start = oltr_start;
389: ifp->if_ioctl = oltr_ioctl;
390: ifp->if_flags = IFF_BROADCAST;
391: bcopy(sc->config.macaddress, sc->arpcom.ac_enaddr, sizeof(sc->config.macaddress));
392:
393: /*
394: * Do ifmedia setup.
395: */
396: ifmedia_init(&sc->ifmedia, 0, oltr_ifmedia_upd, oltr_ifmedia_sts);
397: rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS);
398: switch(sc->config.type) {
399: case TRLLD_ADAPTER_PCI7: /* OC-3540 */
400: ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP100, 0, NULL);
401: /* FALL THROUGH */
402: case TRLLD_ADAPTER_PCI4: /* OC-3139 */
403: case TRLLD_ADAPTER_PCI5: /* OC-3140 */
404: case TRLLD_ADAPTER_PCI6: /* OC-3141 */
405: ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_AUTO, 0, NULL);
406: media = IFM_TOKEN|IFM_AUTO;
407: rc = TRlldSetSpeed(sc->TRlldAdapter, 0);
408: /* FALL THROUGH */
409: default:
410: ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP4, 0, NULL);
411: ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP16, 0, NULL);
412: break;
413: }
414: sc->ifmedia.ifm_media = media;
415: ifmedia_set(&sc->ifmedia, media);
416:
417: /*
418: * Attach the interface
419: */
420: if_attach(ifp);
421: ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
422: iso88025_ifattach(ifp);
423:
424: #if (NBPFILTER > 0) || (__FreeBSD_version > 400000)
425: bpfattach(ifp, DLT_IEEE802, sizeof(struct iso88025_header));
426: #endif
427:
428: splx(s);
429: return(0);
430:
431: config_failed:
432:
433: splx(s);
434: return(ENXIO);
435: }
436:
437: static int
438: oltr_pci_detach(device_t dev)
439: {
440: struct oltr_softc *sc = device_get_softc(dev);
441: struct ifnet *ifp = &sc->arpcom.ac_if;
442: int s, i;
443:
444: device_printf(dev, "driver unloading\n");
445:
446: s = splimp();
447:
448: if_detach(ifp);
449: if (sc->state > OL_CLOSED)
450: oltr_stop(sc);
451:
452: untimeout(oltr_poll, (void *)sc, sc->oltr_poll_ch);
453: /*untimeout(oltr_stat, (void *)sc, sc->oltr_stat_ch);*/
454:
455: bus_teardown_intr(dev, sc->oltr_irq, sc->oltr_intrhand);
456: bus_release_resource(dev, SYS_RES_IRQ, 0, sc->oltr_irq);
457:
458: /* Deallocate all dynamic memory regions */
459: for (i = 0; i < RING_BUFFER_LEN; i++) {
460: free(sc->rx_ring[i].data, M_DEVBUF);
461: free(sc->tx_ring[i].data, M_DEVBUF);
462: }
463: if (sc->work_memory)
464: free(sc->work_memory, M_DEVBUF);
465: free(sc->TRlldAdapter, M_DEVBUF);
466:
467: (void)splx(s);
468:
469: return(0);
470: }
471:
472: static void
473: oltr_pci_shutdown(device_t dev)
474: {
475: struct oltr_softc *sc = device_get_softc(dev);
476:
477: device_printf(dev, "oltr_pci_shutdown called\n");
478:
479: if (sc->state > OL_CLOSED)
480: oltr_stop(sc);
481:
482: return;
483: }
484:
485: #else
486:
487: static const char *oltr_pci_probe (pcici_t, pcidi_t);
488: static void oltr_pci_attach (pcici_t, int);
489:
490: static unsigned long oltr_count = 0;
491:
492: static struct pci_device oltr_device = {
493: "oltr",
494: oltr_pci_probe,
495: oltr_pci_attach,
496: &oltr_count,
497: NULL
498: };
499:
500: DATA_SET(pcidevice_set, oltr_device);
501:
502: static const char *
503: oltr_pci_probe(pcici_t config_id, pcidi_t device_id)
504: {
505: int i, rc;
506: char PCIConfigHeader[64];
507: TRlldAdapterConfig_t config;
508:
509: if (((device_id & 0xffff) == PCI_VENDOR_OLICOM) && (
510: (((device_id >> 16) & 0xffff) == 0x0001) ||
511: (((device_id >> 16) & 0xffff) == 0x0004) ||
512: (((device_id >> 16) & 0xffff) == 0x0005) ||
513: (((device_id >> 16) & 0xffff) == 0x0007) ||
514: (((device_id >> 16) & 0xffff) == 0x0008))) {
515:
516: for (i = 0; i < 64; i++)
517: PCIConfigHeader[i] = pci_cfgread(config_id, i, /* bytes */ 1);
518:
519: rc = TRlldPCIConfig(&LldDriver, &config, PCIConfigHeader);
520:
521: if (rc == TRLLD_PCICONFIG_FAIL) {
522: printf("oltr: TRlldPciConfig failed!\n");
523: return(NULL);
524: }
525: if (rc == TRLLD_PCICONFIG_VERSION) {
526: printf("oltr: wrong LLD version.\n");
527: return(NULL);
528: }
529: return(AdapterName[config.type]);
530: }
531:
532: return(NULL);
533: }
534:
535: static void
536: oltr_pci_attach(pcici_t config_id, int unit)
537: {
538: int i, s, rc = 0, scratch_size;
539: int media = IFM_TOKEN|IFM_TOK_UTP16;
540: u_long command;
541: char PCIConfigHeader[64];
542: struct oltr_softc *sc;
543: struct ifnet *ifp; /* = &sc->arpcom.ac_if; */
544:
545: s = splimp();
546:
547: sc = malloc(sizeof(struct oltr_softc), M_DEVBUF, M_NOWAIT | M_ZERO);
548: if (sc == NULL) {
549: printf("oltr%d: no memory for softc struct!\n", unit);
550: goto config_failed;
551: }
552: sc->unit = unit;
553: sc->state = OL_UNKNOWN;
554: ifp = &sc->arpcom.ac_if;
555:
556: for (i = 0; i < sizeof(PCIConfigHeader); i++)
557: PCIConfigHeader[i] = pci_cfgread(config_id, i, 1);
558:
559: switch(TRlldPCIConfig(&LldDriver, &sc->config, PCIConfigHeader)) {
560: case TRLLD_PCICONFIG_OK:
561: break;
562: case TRLLD_PCICONFIG_SET_COMMAND:
563: printf("oltr%d: enabling bus master mode\n", unit);
564: command = pci_conf_read(config_id, PCIR_COMMAND);
565: pci_conf_write(config_id, PCIR_COMMAND, (command | PCIM_CMD_BUSMASTEREN));
566: command = pci_conf_read(config_id, PCIR_COMMAND);
567: if (!(command & PCIM_CMD_BUSMASTEREN)) {
568: printf("oltr%d: failed to enable bus master mode\n", unit);
569: goto config_failed;
570: }
571: break;
572: case TRLLD_PCICONFIG_FAIL:
573: printf("oltr%d: TRlldPciConfig failed!\n", unit);
574: goto config_failed;
575: break;
576: case TRLLD_PCICONFIG_VERSION:
577: printf("oltr%d: wrong LLD version\n", unit);
578: goto config_failed;
579: break;
580: }
581: printf("oltr%d: MAC address %6D\n", unit, sc->config.macaddress, ":");
582:
583: scratch_size = TRlldAdapterSize();
584: if (bootverbose)
585: printf("oltr%d: adapter memory block size %d bytes\n", unit, scratch_size);
586: sc->TRlldAdapter = (TRlldAdapter_t)malloc(scratch_size, M_DEVBUF, M_NOWAIT);
587: if (sc->TRlldAdapter == NULL) {
588: printf("oltr%d: couldn't allocate scratch buffer (%d bytes)\n",unit, scratch_size);
589: goto config_failed;
590: }
591:
592: /*
593: * Allocate RX/TX Pools
594: */
595: for (i = 0; i < RING_BUFFER_LEN; i++) {
596: sc->rx_ring[i].index = i;
597: sc->rx_ring[i].data = (char *)malloc(RX_BUFFER_LEN, M_DEVBUF, M_NOWAIT);
598: sc->rx_ring[i].address = vtophys(sc->rx_ring[i].data);
599: sc->tx_ring[i].index = i;
600: sc->tx_ring[i].data = (char *)malloc(TX_BUFFER_LEN, M_DEVBUF, M_NOWAIT);
601: sc->tx_ring[i].address = vtophys(sc->tx_ring[i].data);
602: if ((!sc->rx_ring[i].data) || (!sc->tx_ring[i].data)) {
603: printf("oltr%d: unable to allocate ring buffers\n", unit);
604: while (i > 0) {
605: if (sc->rx_ring[i].data)
606: free(sc->rx_ring[i].data, M_DEVBUF);
607: if (sc->tx_ring[i].data)
608: free(sc->tx_ring[i].data, M_DEVBUF);
609: i--;
610: }
611: goto config_failed;
612: }
613: }
614:
615: /*
616: * Allocate interrupt and DMA channel
617: */
618: if (!pci_map_int(config_id, oltr_intr, sc, &net_imask)) {
619: printf("oltr%d: couldn't setup interrupt\n", unit);
620: goto config_failed;
621: }
622:
623: /*
624: * Do the ifnet initialization
625: */
626: ifp->if_softc = sc;
627: if_initname(ifp, "oltr", unit);
628: ifp->if_output = iso88025_output;
629: ifp->if_init = oltr_init;
630: ifp->if_start = oltr_start;
631: ifp->if_ioctl = oltr_ioctl;
632: ifp->if_flags = IFF_BROADCAST;
633: bcopy(sc->config.macaddress, sc->arpcom.ac_enaddr, sizeof(sc->config.macaddress));
634:
635: /*
636: * Do ifmedia setup.
637: */
638: ifmedia_init(&sc->ifmedia, 0, oltr_ifmedia_upd, oltr_ifmedia_sts);
639: rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS);
640: switch(sc->config.type) {
641: case TRLLD_ADAPTER_PCI7: /* OC-3540 */
642: ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP100, 0, NULL);
643: /* FALL THROUGH */
644: case TRLLD_ADAPTER_PCI4: /* OC-3139 */
645: case TRLLD_ADAPTER_PCI5: /* OC-3140 */
646: case TRLLD_ADAPTER_PCI6: /* OC-3141 */
647: ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_AUTO, 0, NULL);
648: media = IFM_TOKEN|IFM_AUTO;
649: rc = TRlldSetSpeed(sc->TRlldAdapter, 0);
650: /* FALL THROUGH */
651: default:
652: ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP4, 0, NULL);
653: ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP16, 0, NULL);
654: break;
655: }
656: sc->ifmedia.ifm_media = media;
657: ifmedia_set(&sc->ifmedia, media);
658:
659: /*
660: * Attach the interface
661: */
662: if_attach(ifp);
663: ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
664: iso88025_ifattach(ifp);
665:
666: #if (NBPFILTER > 0) || (__FreeBSD_version > 400000)
667: bpfattach(ifp, DLT_IEEE802, sizeof(struct iso88025_header));
668: #endif
669:
670: splx(s);
671: return;
672:
673: config_failed:
674: (void)splx(s);
675:
676: return;
677: }
678:
679: #endif
680:
681: static void
682: oltr_intr(void *xsc)
683: {
684: struct oltr_softc *sc = (struct oltr_softc *)xsc;
685:
686: if (DEBUG_MASK & DEBUG_INT)
687: printf("I");
688:
689: TRlldInterruptService(sc->TRlldAdapter);
690:
691: return;
692: }
693:
694: static void
695: oltr_start(struct ifnet *ifp)
696: {
697: struct oltr_softc *sc = ifp->if_softc;
698: struct mbuf *m0, *m;
699: int copy_len, buffer, frame, fragment, rc, s;
700:
701: /*
702: * Check to see if output is already active
703: */
704: if (ifp->if_flags & IFF_OACTIVE)
705: return;
706:
707: outloop:
708:
709: /*
710: * Make sure we have buffers to transmit with
711: */
712: if (sc->tx_avail <= 0) {
713: printf("oltr%d: tx queue full\n", sc->unit);
714: ifp->if_flags |= IFF_OACTIVE;
715: return;
716: }
717:
718: if (sc->restart == NULL) {
719: IF_DEQUEUE(&ifp->if_snd, m);
720: if (m == NULL)
721: return;
722: } else {
723: m = sc->restart;
724: sc->restart = NULL;
725: }
726:
727: m0 = m;
728: frame = RING_BUFFER(sc->tx_frame);
729: buffer = RING_BUFFER(sc->tx_head);
730: fragment = 0;
731: copy_len = 0;
732: sc->frame_ring[frame].FragmentCount = 0;
733:
734: while (copy_len < m0->m_pkthdr.len) {
735: sc->frame_ring[frame].FragmentCount++;
736: if (sc->frame_ring[frame].FragmentCount > sc->tx_avail)
737: goto nobuffers;
738: sc->frame_ring[frame].TransmitFragment[fragment].VirtualAddress = sc->tx_ring[buffer].data;
739: sc->frame_ring[frame].TransmitFragment[fragment].PhysicalAddress = sc->tx_ring[buffer].address;
740: sc->frame_ring[frame].TransmitFragment[fragment].count = MIN(m0->m_pkthdr.len - copy_len, TX_BUFFER_LEN);
741: m_copydata(m0, copy_len, MIN(m0->m_pkthdr.len - copy_len, TX_BUFFER_LEN), sc->tx_ring[buffer].data);
742: copy_len += MIN(m0->m_pkthdr.len - copy_len, TX_BUFFER_LEN);
743: fragment++;
744: buffer = RING_BUFFER((buffer + 1));
745: }
746:
747: s = splimp();
748: rc = TRlldTransmitFrame(sc->TRlldAdapter, &sc->frame_ring[frame], (void *)&sc->frame_ring[frame]);
749: (void)splx(s);
750:
751: if (rc != TRLLD_TRANSMIT_OK) {
752: printf("oltr%d: TRlldTransmitFrame returned %d\n", sc->unit, rc);
753: ifp->if_oerrors++;
754: goto bad;
755: }
756:
757: sc->tx_avail -= sc->frame_ring[frame].FragmentCount;
758: sc->tx_head = RING_BUFFER((sc->tx_head + sc->frame_ring[frame].FragmentCount));
759: sc->tx_frame++;
760:
761: #if (NBPFILTER > 0) || (__FreeBSD_version > 400000)
762: if (ifp->if_bpf)
763: bpf_mtap(ifp, m0);
764: #endif
765: /*ifp->if_opackets++;*/
766:
767: bad:
768: m_freem(m0);
769:
770: goto outloop;
771:
772: nobuffers:
773:
774: printf("oltr%d: queue full\n", sc->unit);
775: ifp->if_flags |= IFF_OACTIVE;
776: ifp->if_oerrors++;
777: /*m_freem(m0);*/
778: sc->restart = m0;
779:
780: return;
781: }
782:
783: static void
784: oltr_close(struct oltr_softc *sc)
785: {
786: /*printf("oltr%d: oltr_close\n", sc->unit);*/
787:
788: oltr_stop(sc);
789:
790: tsleep(sc, 0, "oltrclose", 30*hz);
791: }
792:
793: static void
794: oltr_stop(struct oltr_softc *sc)
795: {
796: struct ifnet *ifp = &sc->arpcom.ac_if;
797:
798: /*printf("oltr%d: oltr_stop\n", sc->unit);*/
799:
800: ifp->if_flags &= ~(IFF_UP | IFF_RUNNING | IFF_OACTIVE);
801: TRlldClose(sc->TRlldAdapter, 0);
802: sc->state = OL_CLOSING;
803: }
804:
805: static void
806: oltr_init(void * xsc)
807: {
808: struct oltr_softc *sc = (struct oltr_softc *)xsc;
809: struct ifnet *ifp = &sc->arpcom.ac_if;
810: struct ifmedia *ifm = &sc->ifmedia;
811: int poll = 0, i, rc = 0, s;
812: int work_size;
813:
814: /*
815: * Check adapter state, don't allow multiple inits
816: */
817: if (sc->state > OL_CLOSED) {
818: printf("oltr%d: adapter not ready\n", sc->unit);
819: return;
820: }
821:
822: s = splimp();
823:
824: /*
825: * Initialize Adapter
826: */
827: if ((rc = TRlldAdapterInit(&LldDriver, sc->TRlldAdapter, vtophys(sc->TRlldAdapter),
828: (void *)sc, &sc->config)) != TRLLD_INIT_OK) {
829: switch(rc) {
830: case TRLLD_INIT_NOT_FOUND:
831: printf("oltr%d: adapter not found\n", sc->unit);
832: break;
833: case TRLLD_INIT_UNSUPPORTED:
834: printf("oltr%d: adapter not supported by low level driver\n", sc->unit);
835: break;
836: case TRLLD_INIT_PHYS16:
837: printf("oltr%d: adapter memory block above 16M cannot DMA\n", sc->unit);
838: break;
839: case TRLLD_INIT_VERSION:
840: printf("oltr%d: low level driver version mismatch\n", sc->unit);
841: break;
842: default:
843: printf("oltr%d: unknown init error %d\n", sc->unit, rc);
844: break;
845: }
846: goto init_failed;
847: }
848: sc->state = OL_INIT;
849:
850: switch(sc->config.type) {
851: case TRLLD_ADAPTER_PCI4: /* OC-3139 */
852: work_size = 32 * 1024;
853: break;
854: case TRLLD_ADAPTER_PCI7: /* OC-3540 */
855: work_size = 256;
856: break;
857: default:
858: work_size = 0;
859: }
860:
861: if (work_size) {
862: if ((sc->work_memory = malloc(work_size, M_DEVBUF, M_NOWAIT)) == NULL) {
863: printf("oltr%d: failed to allocate work memory (%d octets).\n", sc->unit, work_size);
864: } else {
865: TRlldAddMemory(sc->TRlldAdapter, sc->work_memory,
866: vtophys(sc->work_memory), work_size);
867: }
868: }
869:
870: switch(IFM_SUBTYPE(ifm->ifm_media)) {
871: case IFM_AUTO:
872: rc = TRlldSetSpeed(sc->TRlldAdapter, 0); /* TRLLD_SPEED_AUTO */
873: break;
874: case IFM_TOK_UTP4:
875: rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_4MBPS);
876: break;
877: case IFM_TOK_UTP16:
878: rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS);
879: break;
880: case IFM_TOK_UTP100:
881: rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_100MBPS);
882: break;
883: }
884:
885: /*
886: * Download adapter micro-code
887: */
888: if (bootverbose)
889: printf("oltr%d: Downloading adapter microcode: ", sc->unit);
890:
891: switch(sc->config.mactype) {
892: case TRLLD_MAC_TMS:
893: rc = TRlldDownload(sc->TRlldAdapter, TRlldMacCode);
894: if (bootverbose)
895: printf("TMS-380");
896: break;
897: case TRLLD_MAC_HAWKEYE:
898: rc = TRlldDownload(sc->TRlldAdapter, TRlldHawkeyeMac);
899: if (bootverbose)
900: printf("Hawkeye");
901: break;
902: case TRLLD_MAC_BULLSEYE:
903: rc = TRlldDownload(sc->TRlldAdapter, TRlldBullseyeMac);
904: if (bootverbose)
905: printf("Bullseye");
906: break;
907: default:
908: if (bootverbose)
909: printf("unknown - failed!\n");
910: goto init_failed;
911: break;
912: }
913:
914: /*
915: * Check download status
916: */
917: switch(rc) {
918: case TRLLD_DOWNLOAD_OK:
919: if (bootverbose)
920: printf(" - ok\n");
921: break;
922: case TRLLD_DOWNLOAD_ERROR:
923: if (bootverbose)
924: printf(" - failed\n");
925: else
926: printf("oltr%d: adapter microcode download failed\n", sc->unit);
927: goto init_failed;
928: break;
929: case TRLLD_STATE:
930: if (bootverbose)
931: printf(" - not ready\n");
932: goto init_failed;
933: break;
934: }
935:
936: /*
937: * Wait for self-test to complete
938: */
939: i = 0;
940: while ((poll++ < SELF_TEST_POLLS) && (sc->state < OL_READY)) {
941: if (DEBUG_MASK & DEBUG_INIT)
942: printf("p");
943: DELAY(TRlldPoll(sc->TRlldAdapter) * 1000);
944: if (TRlldInterruptService(sc->TRlldAdapter) != 0)
945: if (DEBUG_MASK & DEBUG_INIT) printf("i");
946: }
947:
948: if (sc->state != OL_CLOSED) {
949: printf("oltr%d: self-test failed\n", sc->unit);
950: goto init_failed;
951: }
952:
953: /*
954: * Set up adapter poll
955: */
956: callout_handle_init(&sc->oltr_poll_ch);
957: sc->oltr_poll_ch = timeout(oltr_poll, (void *)sc, 1);
958:
959: sc->state = OL_OPENING;
960:
961: /*
962: * Open the adapter
963: */
964: rc = TRlldOpen(sc->TRlldAdapter, sc->arpcom.ac_enaddr, sc->GroupAddress,
965: sc->FunctionalAddress, 1552, sc->AdapterMode);
966: switch(rc) {
967: case TRLLD_OPEN_OK:
968: break;
969: case TRLLD_OPEN_STATE:
970: printf("oltr%d: adapter not ready for open\n", sc->unit);
971: (void)splx(s);
972: return;
973: case TRLLD_OPEN_ADDRESS_ERROR:
974: printf("oltr%d: illegal MAC address\n", sc->unit);
975: (void)splx(s);
976: return;
977: case TRLLD_OPEN_MODE_ERROR:
978: printf("oltr%d: illegal open mode\n", sc->unit);
979: (void)splx(s);
980: return;
981: default:
982: printf("oltr%d: unknown open error (%d)\n", sc->unit, rc);
983: (void)splx(s);
984: return;
985: }
986:
987: /*
988: * Set promiscious mode for now...
989: */
990: TRlldSetPromiscuousMode(sc->TRlldAdapter, TRLLD_PROM_LLC);
991: ifp->if_flags |= IFF_PROMISC;
992:
993: /*
994: * Block on the ring insert and set a timeout
995: */
996: tsleep(sc, 0, "oltropen", 30*hz);
997:
998: /*
999: * Set up receive buffer ring
1000: */
1001: for (i = 0; i < RING_BUFFER_LEN; i++) {
1002: rc = TRlldReceiveFragment(sc->TRlldAdapter, (void *)sc->rx_ring[i].data,
1003: sc->rx_ring[i].address, RX_BUFFER_LEN, (void *)sc->rx_ring[i].index);
1004: if (rc != TRLLD_RECEIVE_OK) {
1005: printf("oltr%d: adapter refused receive fragment %d (rc = %d)\n", sc->unit, i, rc);
1006: break;
1007: }
1008: }
1009:
1010: sc->tx_avail = RING_BUFFER_LEN;
1011: sc->tx_head = 0;
1012: sc->tx_frame = 0;
1013:
1014: sc->restart = NULL;
1015:
1016: ifp->if_flags |= IFF_RUNNING;
1017: ifp->if_flags &= ~IFF_OACTIVE;
1018:
1019: /*
1020: * Set up adapter statistics poll
1021: */
1022: /*callout_handle_init(&sc->oltr_stat_ch);*/
1023: /*sc->oltr_stat_ch = timeout(oltr_stat, (void *)sc, 1*hz);*/
1024:
1025: (void)splx(s);
1026: return;
1027:
1028: init_failed:
1029: sc->state = OL_DEAD;
1030: (void)splx(s);
1031: return;
1032: }
1033:
1034: static int
1035: oltr_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1036: {
1037: struct oltr_softc *sc = ifp->if_softc;
1038: struct ifreq *ifr = (struct ifreq *)data;
1039: int error = 0, s;
1040:
1041: s = splimp();
1042:
1043: switch(command) {
1044: case SIOCSIFADDR:
1045: case SIOCGIFADDR:
1046: case SIOCSIFMTU:
1047: error = iso88025_ioctl(ifp, command, data);
1048: break;
1049:
1050: case SIOCSIFFLAGS:
1051: if (ifp->if_flags & IFF_UP) {
1052: oltr_init(sc);
1053: } else {
1054: if (ifp->if_flags & IFF_RUNNING) {
1055: oltr_close(sc);
1056: }
1057: }
1058: break;
1059: case SIOCGIFMEDIA:
1060: case SIOCSIFMEDIA:
1061: error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
1062: break;
1063: default:
1064: error = EINVAL;
1065: break;
1066: }
1067:
1068: (void)splx(s);
1069:
1070: return(error);
1071: }
1072:
1073:
1074: void
1075: oltr_poll(void *arg)
1076: {
1077: struct oltr_softc *sc = (struct oltr_softc *)arg;
1078: int s;
1079:
1080: s = splimp();
1081:
1082: if (DEBUG_MASK & DEBUG_POLL) printf("P");
1083:
1084: /* Set up next adapter poll */
1085: sc->oltr_poll_ch = timeout(oltr_poll, (void *)sc, (TRlldPoll(sc->TRlldAdapter) * hz / 1000));
1086:
1087: (void)splx(s);
1088: }
1089:
1090: #ifdef NOTYET
1091: void
1092: oltr_stat(void *arg)
1093: {
1094: struct oltr_softc *sc = (struct oltr_softc *)arg;
1095: int s;
1096:
1097: s = splimp();
1098:
1099: /* Set up next adapter poll */
1100: sc->oltr_stat_ch = timeout(oltr_stat, (void *)sc, 1*hz);
1101: if (TRlldGetStatistics(sc->TRlldAdapter, &sc->current, 0) != 0) {
1102: /*printf("oltr%d: statistics available immediately...\n", sc->unit);*/
1103: DriverStatistics((void *)sc, &sc->current);
1104: }
1105:
1106: (void)splx(s);
1107: }
1108: #endif
1109: static int
1110: oltr_ifmedia_upd(struct ifnet *ifp)
1111: {
1112: struct oltr_softc *sc = ifp->if_softc;
1113: struct ifmedia *ifm = &sc->ifmedia;
1114: int rc;
1115:
1116: if (IFM_TYPE(ifm->ifm_media) != IFM_TOKEN)
1117: return(EINVAL);
1118:
1119: switch(IFM_SUBTYPE(ifm->ifm_media)) {
1120: case IFM_AUTO:
1121: rc = TRlldSetSpeed(sc->TRlldAdapter, 0); /* TRLLD_SPEED_AUTO */
1122: break;
1123: case IFM_TOK_UTP4:
1124: rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_4MBPS);
1125: break;
1126: case IFM_TOK_UTP16:
1127: rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS);
1128: break;
1129: case IFM_TOK_UTP100:
1130: rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_100MBPS);
1131: break;
1132: default:
1133: return(EINVAL);
1134: break;
1135: }
1136:
1137: return(0);
1138:
1139: }
1140:
1141: static void
1142: oltr_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
1143: {
1144: struct oltr_softc *sc = ifp->if_softc;
1145: struct ifmedia *ifm = &sc->ifmedia;
1146:
1147: /*printf("oltr%d: oltr_ifmedia_sts\n", sc->unit);*/
1148:
1149: ifmr->ifm_active = IFM_TYPE(ifm->ifm_media)|IFM_SUBTYPE(ifm->ifm_media);
1150:
1151: }
1152:
1153: /*
1154: * ---------------------- PMW Callback Functions -----------------------
1155: */
1156:
1157: void
1158: DriverStatistics(void *DriverHandle, TRlldStatistics_t *statistics)
1159: {
1160: #ifdef NOTYET
1161: struct oltr_softc *sc = (struct oltr_softc *)DriverHandle;
1162:
1163: if (sc->statistics.LineErrors != statistics->LineErrors)
1164: printf("oltr%d: Line Errors %lu\n", sc->unit,
1165: statistics->LineErrors);
1166: if (sc->statistics.InternalErrors != statistics->InternalErrors)
1167: printf("oltr%d: Internal Errors %lu\n", sc->unit,
1168: statistics->InternalErrors);
1169: if (sc->statistics.BurstErrors != statistics->BurstErrors)
1170: printf("oltr%d: Burst Errors %lu\n", sc->unit,
1171: statistics->BurstErrors);
1172: if (sc->statistics.AbortDelimiters != statistics->AbortDelimiters)
1173: printf("oltr%d: Abort Delimiters %lu\n", sc->unit,
1174: statistics->AbortDelimiters);
1175: if (sc->statistics.ARIFCIErrors != statistics->ARIFCIErrors)
1176: printf("oltr%d: ARIFCI Errors %lu\n", sc->unit,
1177: statistics->ARIFCIErrors);
1178: if (sc->statistics.LostFrames != statistics->LostFrames)
1179: printf("oltr%d: Lost Frames %lu\n", sc->unit,
1180: statistics->LostFrames);
1181: if (sc->statistics.CongestionErrors != statistics->CongestionErrors)
1182: printf("oltr%d: Congestion Errors %lu\n", sc->unit,
1183: statistics->CongestionErrors);
1184: if (sc->statistics.FrequencyErrors != statistics->FrequencyErrors)
1185: printf("oltr%d: Frequency Errors %lu\n", sc->unit,
1186: statistics->FrequencyErrors);
1187: if (sc->statistics.TokenErrors != statistics->TokenErrors)
1188: printf("oltr%d: Token Errors %lu\n", sc->unit,
1189: statistics->TokenErrors);
1190: if (sc->statistics.DMABusErrors != statistics->DMABusErrors)
1191: printf("oltr%d: DMA Bus Errors %lu\n", sc->unit,
1192: statistics->DMABusErrors);
1193: if (sc->statistics.DMAParityErrors != statistics->DMAParityErrors)
1194: printf("oltr%d: DMA Parity Errors %lu\n", sc->unit,
1195: statistics->DMAParityErrors);
1196: if (sc->statistics.ReceiveLongFrame != statistics->ReceiveLongFrame)
1197: printf("oltr%d: Long frames received %lu\n", sc->unit,
1198: statistics->ReceiveLongFrame);
1199: if (sc->statistics.ReceiveCRCErrors != statistics->ReceiveCRCErrors)
1200: printf("oltr%d: Receive CRC Errors %lu\n", sc->unit,
1201: statistics->ReceiveCRCErrors);
1202: if (sc->statistics.ReceiveOverflow != statistics->ReceiveOverflow)
1203: printf("oltr%d: Recieve overflows %lu\n", sc->unit,
1204: statistics->ReceiveOverflow);
1205: if (sc->statistics.TransmitUnderrun != statistics->TransmitUnderrun)
1206: printf("oltr%d: Frequency Errors %lu\n", sc->unit,
1207: statistics->TransmitUnderrun);
1208: bcopy(statistics, &sc->statistics, sizeof(TRlldStatistics_t));
1209: #endif
1210: }
1211:
1212: static void
1213: DriverSuspend(unsigned short MicroSeconds)
1214: {
1215: DELAY(MicroSeconds);
1216: }
1217:
1218:
1219: static void
1220: DriverStatus(void *DriverHandle, TRlldStatus_t *Status)
1221: {
1222: struct oltr_softc *sc = (struct oltr_softc *)DriverHandle;
1223: struct ifnet *ifp = &sc->arpcom.ac_if;
1224:
1225: char *Protocol[] = { /* 0 */ "Unknown",
1226: /* 1 */ "TKP",
1227: /* 2 */ "TXI" };
1228: char *Timeout[] = { /* 0 */ "command",
1229: /* 1 */ "transmit",
1230: /* 2 */ "interrupt" };
1231:
1232: switch (Status->Type) {
1233:
1234: case TRLLD_STS_ON_WIRE:
1235: printf("oltr%d: ring insert (%d Mbps - %s)\n", sc->unit,
1236: Status->Specification.OnWireInformation.Speed,
1237: Protocol[Status->Specification.OnWireInformation.AccessProtocol]);
1238: sc->state = OL_OPEN;
1239: wakeup(sc);
1240: break;
1241: case TRLLD_STS_SELFTEST_STATUS:
1242: if (Status->Specification.SelftestStatus == TRLLD_ST_OK) {
1243: sc->state = OL_CLOSED;
1244: if (bootverbose)
1245: printf("oltr%d: self test complete\n", sc->unit);
1246: }
1247: if (Status->Specification.SelftestStatus & TRLLD_ST_ERROR) {
1248: printf("oltr%d: Adapter self test error %d", sc->unit,
1249: Status->Specification.SelftestStatus & ~TRLLD_ST_ERROR);
1250: sc->state = OL_DEAD;
1251: }
1252: if (Status->Specification.SelftestStatus & TRLLD_ST_TIMEOUT) {
1253: printf("oltr%d: Adapter self test timed out.\n", sc->unit);
1254: sc->state = OL_DEAD;
1255: }
1256: break;
1257: case TRLLD_STS_INIT_STATUS:
1258: if (Status->Specification.InitStatus == 0x800) {
1259: oltr_stop(sc);
1260: ifmedia_set(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP16);
1261: TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS);
1262: oltr_init(sc);
1263: break;
1264: }
1265: printf("oltr%d: adapter init failure 0x%03x\n", sc->unit,
1266: Status->Specification.InitStatus);
1267: oltr_stop(sc);
1268: break;
1269: case TRLLD_STS_RING_STATUS:
1270: if (Status->Specification.RingStatus) {
1271: printf("oltr%d: Ring status change: ", sc->unit);
1272: if (Status->Specification.RingStatus &
1273: TRLLD_RS_SIGNAL_LOSS)
1274: printf(" [Signal Loss]");
1275: if (Status->Specification.RingStatus &
1276: TRLLD_RS_HARD_ERROR)
1277: printf(" [Hard Error]");
1278: if (Status->Specification.RingStatus &
1279: TRLLD_RS_SOFT_ERROR)
1280: printf(" [Soft Error]");
1281: if (Status->Specification.RingStatus &
1282: TRLLD_RS_TRANSMIT_BEACON)
1283: printf(" [Beacon]");
1284: if (Status->Specification.RingStatus &
1285: TRLLD_RS_LOBE_WIRE_FAULT)
1286: printf(" [Wire Fault]");
1287: if (Status->Specification.RingStatus &
1288: TRLLD_RS_AUTO_REMOVAL_ERROR)
1289: printf(" [Auto Removal]");
1290: if (Status->Specification.RingStatus &
1291: TRLLD_RS_REMOVE_RECEIVED)
1292: printf(" [Remove Received]");
1293: if (Status->Specification.RingStatus &
1294: TRLLD_RS_COUNTER_OVERFLOW)
1295: printf(" [Counter Overflow]");
1296: if (Status->Specification.RingStatus &
1297: TRLLD_RS_SINGLE_STATION)
1298: printf(" [Single Station]");
1299: if (Status->Specification.RingStatus &
1300: TRLLD_RS_RING_RECOVERY)
1301: printf(" [Ring Recovery]");
1302: printf("\n");
1303: }
1304: break;
1305: case TRLLD_STS_ADAPTER_CHECK:
1306: printf("oltr%d: adapter check (%04x %04x %04x %04x)\n", sc->unit,
1307: Status->Specification.AdapterCheck[0],
1308: Status->Specification.AdapterCheck[1],
1309: Status->Specification.AdapterCheck[2],
1310: Status->Specification.AdapterCheck[3]);
1311: sc->state = OL_DEAD;
1312: oltr_stop(sc);
1313: break;
1314: case TRLLD_STS_PROMISCUOUS_STOPPED:
1315: printf("oltr%d: promiscuous mode ", sc->unit);
1316: if (Status->Specification.PromRemovedCause == 1)
1317: printf("remove received.");
1318: if (Status->Specification.PromRemovedCause == 2)
1319: printf("poll failure.");
1320: if (Status->Specification.PromRemovedCause == 2)
1321: printf("buffer size failure.");
1322: printf("\n");
1323: ifp->if_flags &= ~IFF_PROMISC;
1324: break;
1325: case TRLLD_STS_LLD_ERROR:
1326: printf("oltr%d: low level driver internal error ", sc->unit);
1327: printf("(%04x %04x %04x %04x).\n",
1328: Status->Specification.InternalError[0],
1329: Status->Specification.InternalError[1],
1330: Status->Specification.InternalError[2],
1331: Status->Specification.InternalError[3]);
1332: sc->state = OL_DEAD;
1333: oltr_stop(sc);
1334: break;
1335: case TRLLD_STS_ADAPTER_TIMEOUT:
1336: printf("oltr%d: adapter %s timeout.\n", sc->unit,
1337: Timeout[Status->Specification.AdapterTimeout]);
1338: break;
1339: default:
1340: printf("oltr%d: driver status Type = %d\n", sc->unit, Status->Type);
1341: break;
1342:
1343: }
1344: if (Status->Closed) {
1345: sc->state = OL_CLOSING;
1346: oltr_stop(sc);
1347: }
1348:
1349: }
1350:
1351: static void
1352: DriverCloseCompleted(void *DriverHandle)
1353: {
1354: struct oltr_softc *sc = (struct oltr_softc *)DriverHandle;
1355:
1356: printf("oltr%d: adapter closed\n", sc->unit);
1357: wakeup(sc);
1358: sc->state = OL_CLOSED;
1359: }
1360:
1361: static void
1362: DriverTransmitFrameCompleted(void *DriverHandle, void *FrameHandle, int TransmitStatus)
1363: {
1364: struct oltr_softc *sc = (struct oltr_softc *)DriverHandle;
1365: struct ifnet *ifp = &sc->arpcom.ac_if;
1366: TRlldTransmit_t *frame = (TRlldTransmit_t *)FrameHandle;
1367:
1368: /*printf("oltr%d: DriverTransmitFrameCompleted\n", sc->unit);*/
1369:
1370: if (TransmitStatus != TRLLD_TRANSMIT_OK) {
1371: ifp->if_oerrors++;
1372: printf("oltr%d: transmit error %d\n", sc->unit, TransmitStatus);
1373: } else {
1374: ifp->if_opackets++;
1375: }
1376:
1377: sc->tx_avail += frame->FragmentCount;
1378:
1379: if (ifp->if_flags & IFF_OACTIVE) {
1380: printf("oltr%d: queue restart\n", sc->unit);
1381: ifp->if_flags &= ~IFF_OACTIVE;
1382: oltr_start(ifp);
1383: }
1384:
1385:
1386: }
1387:
1388: static void
1389: DriverReceiveFrameCompleted(void *DriverHandle, int ByteCount, int FragmentCount, void *FragmentHandle, int ReceiveStatus)
1390: {
1391: struct oltr_softc *sc = (struct oltr_softc *)DriverHandle;
1392: struct ifnet *ifp = (struct ifnet *)&sc->arpcom.ac_if;
1393: struct mbuf *m0, *m1, *m;
1394: struct iso88025_header *th;
1395: int frame_len = ByteCount, hdr_len, i = (int)FragmentHandle, rc, s;
1396: int mbuf_offset, mbuf_size, frag_offset, copy_length;
1397: char *fragment = sc->rx_ring[RING_BUFFER(i)].data;
1398:
1399: if (sc->state > OL_CLOSED) {
1400: if (ReceiveStatus == TRLLD_RCV_OK) {
1401: MGETHDR(m0, M_DONTWAIT, MT_DATA);
1402: mbuf_size = MHLEN - 2;
1403: if (!m0) {
1404: ifp->if_ierrors++;
1405: goto dropped;
1406: }
1407: if (ByteCount + 2 > MHLEN) {
1408: MCLGET(m0, M_DONTWAIT);
1409: mbuf_size = MCLBYTES - 2;
1410: if (!(m0->m_flags & M_EXT)) {
1411: m_freem(m0);
1412: ifp->if_ierrors++;
1413: goto dropped;
1414: }
1415: }
1416: m0->m_pkthdr.rcvif = ifp;
1417: m0->m_pkthdr.len = ByteCount;
1418: m0->m_len = 0;
1419: m0->m_data += 2;
1420: th = mtod(m0, struct iso88025_header *);
1421: m0->m_pkthdr.header = (void *)th;
1422:
1423: m = m0;
1424: mbuf_offset = 0;
1425: frag_offset = 0;
1426: while (frame_len) {
1427: copy_length = MIN3(frame_len,
1428: (RX_BUFFER_LEN - frag_offset),
1429: (mbuf_size - mbuf_offset));
1430: bcopy(fragment + frag_offset, mtod(m, char *) +
1431: mbuf_offset, copy_length);
1432: m->m_len += copy_length;
1433: mbuf_offset += copy_length;
1434: frag_offset += copy_length;
1435: frame_len -= copy_length;
1436:
1437: if (frag_offset == RX_BUFFER_LEN) {
1438: fragment =
1439: sc->rx_ring[RING_BUFFER(++i)].data;
1440: frag_offset = 0;
1441: }
1442: if ((mbuf_offset == mbuf_size) && (frame_len > 0)) {
1443: MGET(m1, M_DONTWAIT, MT_DATA);
1444: mbuf_size = MHLEN;
1445: if (!m1) {
1446: ifp->if_ierrors++;
1447: m_freem(m0);
1448: goto dropped;
1449: }
1450: if (frame_len > MHLEN) {
1451: MCLGET(m1, M_DONTWAIT);
1452: mbuf_size = MCLBYTES;
1453: if (!(m1->m_flags & M_EXT)) {
1454: m_freem(m0);
1455: m_freem(m1);
1456: ifp->if_ierrors++;
1457: goto dropped;
1458: }
1459: }
1460: m->m_next = m1;
1461: m = m1;
1462: mbuf_offset = 0;
1463: m->m_len = 0;
1464: }
1465: }
1466: #if (NBPFILTER > 0) || (__FreeBSD_version > 400000)
1467: if (ifp->if_bpf)
1468: bpf_mtap(ifp, m0);
1469: #endif
1470:
1471: /*if (ifp->if_flags & IFF_PROMISC) {*/
1472: if (bcmp(th->iso88025_dhost, etherbroadcastaddr
1473: , sizeof(th->iso88025_dhost))) {
1474: if ((bcmp(th->iso88025_dhost + 1, sc->arpcom.ac_enaddr + 1, ISO88025_ADDR_LEN - 1)) ||
1475: ((th->iso88025_dhost[0] & 0x7f) != sc->arpcom.ac_enaddr[0])) {
1476: m_freem(m0);
1477: goto dropped;
1478: }
1479: }
1480: /*}*/
1481: ifp->if_ipackets++;
1482:
1483: hdr_len = ISO88025_HDR_LEN;
1484: if (th->iso88025_shost[0] & 0x80)
1485: hdr_len += (ntohs(th->rcf) & 0x1f00) >> 8;
1486:
1487: m0->m_pkthdr.len -= hdr_len;
1488: m0->m_len -= hdr_len;
1489: m0->m_data += hdr_len;
1490:
1491: iso88025_input(ifp, th, m0);
1492:
1493: } else { /* Receiver error */
1494: if (ReceiveStatus != TRLLD_RCV_NO_DATA) {
1495: printf("oltr%d: receive error %d\n", sc->unit,
1496: ReceiveStatus);
1497: ifp->if_ierrors++;
1498: }
1499: }
1500:
1501: dropped:
1502: s = splimp();
1503: i = (int)FragmentHandle;
1504: while (FragmentCount--) {
1505: rc = TRlldReceiveFragment(sc->TRlldAdapter,
1506: (void *)sc->rx_ring[RING_BUFFER(i)].data,
1507: sc->rx_ring[RING_BUFFER(i)].address,
1508: RX_BUFFER_LEN, (void *)sc->rx_ring[RING_BUFFER(i)].index);
1509: if (rc != TRLLD_RECEIVE_OK) {
1510: printf("oltr%d: adapter refused receive fragment %d (rc = %d)\n", sc->unit, i, rc);
1511: break;
1512: }
1513: i++;
1514: }
1515: (void)splx(s);
1516: }
1517: }
1518:
1519:
1520: /*
1521: * ---------------------------- PMW Glue -------------------------------
1522: */
1523:
1524: #ifndef TRlldInlineIO
1525:
1526: static void
1527: DriverOutByte(unsigned short IOAddress, unsigned char value)
1528: {
1529: outb(IOAddress, value);
1530: }
1531:
1532: static void
1533: DriverOutWord(unsigned short IOAddress, unsigned short value)
1534: {
1535: outw(IOAddress, value);
1536: }
1537:
1538: static void
1539: DriverOutDword(unsigned short IOAddress, unsigned long value)
1540: {
1541: outl(IOAddress, value);
1542: }
1543:
1544: static void
1545: DriverRepOutByte(unsigned short IOAddress, unsigned char *DataPointer, int ByteCount)
1546: {
1547: outsb(IOAddress, (void *)DataPointer, ByteCount);
1548: }
1549:
1550: static void
1551: DriverRepOutWord(unsigned short IOAddress, unsigned short *DataPointer, int WordCount)
1552: {
1553: outsw(IOAddress, (void *)DataPointer, WordCount);
1554: }
1555:
1556: static void
1557: DriverRepOutDword(unsigned short IOAddress, unsigned long *DataPointer, int DWordCount)
1558: {
1559: outsl(IOAddress, (void *)DataPointer, DWordCount);
1560: }
1561:
1562: static unsigned char
1563: DriverInByte(unsigned short IOAddress)
1564: {
1565: return(inb(IOAddress));
1566: }
1567:
1568: static unsigned short
1569: DriverInWord(unsigned short IOAddress)
1570: {
1571: return(inw(IOAddress));
1572: }
1573:
1574: static unsigned long
1575: DriverInDword(unsigned short IOAddress)
1576: {
1577: return(inl(IOAddress));
1578: }
1579:
1580: static void
1581: DriverRepInByte(unsigned short IOAddress, unsigned char *DataPointer, int ByteCount)
1582: {
1583: insb(IOAddress, (void *)DataPointer, ByteCount);
1584: }
1585:
1586: static void
1587: DriverRepInWord(unsigned short IOAddress, unsigned short *DataPointer, int WordCount)
1588: {
1589: insw(IOAddress, (void *)DataPointer, WordCount);
1590: }
1591: static void
1592: DriverRepInDword( unsigned short IOAddress, unsigned long *DataPointer, int DWordCount)
1593: {
1594: insl(IOAddress, (void *)DataPointer, DWordCount);
1595: }
1596: #endif /* TRlldInlineIO */