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