Do a major clean-up of the BUSDMA architecture. A large number of
[dfdiff.git] / sys / contrib / dev / oltr / if_oltr.c
blobf43b9d4658a3df02a18811371a88f917811fb9f0
1 /*
2 * Copyright (c) 1998, Larry Lile
3 * All rights reserved.
5 * For latest sources and information on this driver, please
6 * go to http://anarchy.stdio.com.
8 * Questions, comments or suggestions should be directed to
9 * Larry Lile <lile@stdio.com>.
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.
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.
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/Attic/if_oltr.c,v 1.24 2006/10/25 20:55:52 dillon Exp $
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 #include <sys/bus.h>
47 #include <net/if.h>
48 #include <net/if_arp.h>
49 #include <net/iso88025.h>
50 #include <net/ethernet.h>
51 #include <net/if_dl.h>
52 #include <net/if_media.h>
53 #include <net/iso88025.h>
55 #if defined(__DragonFly__) || (NBPFILTER > 0)
56 #include <net/bpf.h>
57 #endif
59 #include <vm/vm.h> /* for vtophys */
60 #include <vm/pmap.h> /* for vtophys */
61 #include <machine/clock.h>
62 #include <sys/bus.h>
63 #include <sys/rman.h>
64 #include <sys/thread2.h>
66 #include <bus/pci/pcireg.h>
67 #include <bus/pci/pcivar.h>
69 #include "contrib/dev/oltr/trlld.h"
71 /*#define DEBUG_MASK DEBUG_POLL*/
73 #ifndef DEBUG_MASK
74 #define DEBUG_MASK 0x0000
75 #endif
77 #define DEBUG_POLL 0x0001
78 #define DEBUG_INT 0x0002
79 #define DEBUG_INIT 0x0004
80 #define DEBUG_FN_ENT 0x8000
82 #define PCI_VENDOR_OLICOM 0x108D
84 #define MIN3(A,B,C) (MIN(A, (MIN(B, C))))
86 char *AdapterName[] = {
87 /* 0 */ "Olicom XT Adapter [unsupported]",
88 /* 1 */ "Olicom OC-3115",
89 /* 2 */ "Olicom ISA 16/4 Adapter (OC-3117)",
90 /* 3 */ "Olicom ISA 16/4 Adapter (OC-3118)",
91 /* 4 */ "Olicom MCA 16/4 Adapter (OC-3129) [unsupported]",
92 /* 5 */ "Olicom MCA 16/4 Adapter (OC-3129) [unsupported]",
93 /* 6 */ "Olicom MCA 16/4 Adapter (OC-3129) [unsupported]",
94 /* 7 */ "Olicom EISA 16/4 Adapter (OC-3133)",
95 /* 8 */ "Olicom EISA 16/4 Adapter (OC-3133)",
96 /* 9 */ "Olicom EISA 16/4 Server Adapter (OC-3135)",
97 /* 10 */ "Olicom PCI 16/4 Adapter (OC-3136)",
98 /* 11 */ "Olicom PCI 16/4 Adapter (OC-3136)",
99 /* 12 */ "Olicom PCI/II 16/4 Adapter (OC-3137)",
100 /* 13 */ "Olicom PCI 16/4 Adapter (OC-3139)",
101 /* 14 */ "Olicom RapidFire 3140 16/4 PCI Adapter (OC-3140)",
102 /* 15 */ "Olicom RapidFire 3141 Fiber Adapter (OC-3141)",
103 /* 16 */ "Olicom PCMCIA 16/4 Adapter (OC-3220) [unsupported]",
104 /* 17 */ "Olicom PCMCIA 16/4 Adapter (OC-3121, OC-3230, OC-3232) [unsupported]",
105 /* 18 */ "Olicom PCMCIA 16/4 Adapter (OC-3250)",
106 /* 19 */ "Olicom RapidFire 3540 100/16/4 Adapter (OC-3540)"
110 * Glue function prototypes for PMW kit IO
113 #ifndef TRlldInlineIO
114 static void DriverOutByte (unsigned short, unsigned char);
115 static void DriverOutWord (unsigned short, unsigned short);
116 static void DriverOutDword (unsigned short, unsigned long);
117 static void DriverRepOutByte (unsigned short, unsigned char *, int);
118 static void DriverRepOutWord (unsigned short, unsigned short *, int);
119 static void DriverRepOutDword (unsigned short, unsigned long *, int);
120 static unsigned char DriverInByte (unsigned short);
121 static unsigned short DriverInWord (unsigned short);
122 static unsigned long DriverInDword (unsigned short);
123 static void DriverRepInByte (unsigned short, unsigned char *, int);
124 static void DriverRepInWord (unsigned short, unsigned short *, int);
125 static void DriverRepInDword (unsigned short, unsigned long *, int);
126 #endif /*TRlldInlineIO*/
127 static void DriverSuspend (unsigned short);
128 static void DriverStatus (void *, TRlldStatus_t *);
129 static void DriverCloseCompleted (void *);
130 static void DriverStatistics (void *, TRlldStatistics_t *);
131 static void DriverTransmitFrameCompleted (void *, void *, int);
132 static void DriverReceiveFrameCompleted (void *, int, int, void *, int);
134 static TRlldDriver_t LldDriver = {
135 TRLLD_VERSION,
136 #ifndef TRlldInlineIO
137 DriverOutByte,
138 DriverOutWord,
139 DriverOutDword,
140 DriverRepOutByte,
141 DriverRepOutWord,
142 DriverRepOutDword,
143 DriverInByte,
144 DriverInWord,
145 DriverInDword,
146 DriverRepInByte,
147 DriverRepInWord,
148 DriverRepInDword,
149 #endif /*TRlldInlineIO*/
150 DriverSuspend,
151 DriverStatus,
152 DriverCloseCompleted,
153 DriverStatistics,
154 DriverTransmitFrameCompleted,
155 DriverReceiveFrameCompleted,
158 struct oltr_rx_buf {
159 int index;
160 char *data;
161 u_long address;
164 struct oltr_tx_buf {
165 int index;
166 char *data;
167 u_long address;
170 #define RING_BUFFER_LEN 16
171 #define RING_BUFFER(x) ((RING_BUFFER_LEN - 1) & x)
172 #define RX_BUFFER_LEN 2048
173 #define TX_BUFFER_LEN 2048
175 struct oltr_softc {
176 struct arpcom arpcom;
177 struct ifmedia ifmedia;
178 bus_space_handle_t oltr_bhandle;
179 bus_space_tag_t oltr_btag;
180 void *oltr_intrhand;
181 struct resource *oltr_irq;
182 struct resource *oltr_res;
183 int unit;
184 int state;
185 #define OL_UNKNOWN 0
186 #define OL_INIT 1
187 #define OL_READY 2
188 #define OL_CLOSING 3
189 #define OL_CLOSED 4
190 #define OL_OPENING 5
191 #define OL_OPEN 6
192 #define OL_PROMISC 7
193 #define OL_DEAD 8
194 struct oltr_rx_buf rx_ring[RING_BUFFER_LEN];
195 int tx_head, tx_avail, tx_frame;
196 struct oltr_tx_buf tx_ring[RING_BUFFER_LEN];
197 TRlldTransmit_t frame_ring[RING_BUFFER_LEN];
198 struct mbuf *restart;
199 TRlldAdapter_t TRlldAdapter;
200 TRlldStatistics_t statistics;
201 TRlldStatistics_t current;
202 TRlldAdapterConfig_t config;
203 u_short AdapterMode;
204 u_long GroupAddress;
205 u_long FunctionalAddress;
206 struct callout oltr_poll_ch;
207 /*struct callout_handle oltr_stat_ch;*/
208 void *work_memory;
211 #define SELF_TEST_POLLS 32
213 void oltr_poll (void *);
214 /*void oltr_stat (void *);*/
216 static void oltr_start (struct ifnet *);
217 static void oltr_stop (struct oltr_softc *);
218 static void oltr_close (struct oltr_softc *);
219 static void oltr_init (void *);
220 static int oltr_ioctl (struct ifnet *, u_long, caddr_t,
221 struct ucred *);
222 static void oltr_intr (void *);
223 static int oltr_ifmedia_upd (struct ifnet *);
224 static void oltr_ifmedia_sts (struct ifnet *, struct ifmediareq *);
226 #if defined(__DragonFly__) || __FreeBSD_version > 400000
228 static int oltr_pci_probe (device_t);
229 static int oltr_pci_attach (device_t);
230 static int oltr_pci_detach (device_t);
231 static void oltr_pci_shutdown (device_t);
233 static device_method_t oltr_methods[] = {
234 DEVMETHOD(device_probe, oltr_pci_probe),
235 DEVMETHOD(device_attach, oltr_pci_attach),
236 DEVMETHOD(device_detach, oltr_pci_detach),
237 DEVMETHOD(device_shutdown, oltr_pci_shutdown),
238 { 0, 0 }
241 static driver_t oltr_driver = {
242 "oltr",
243 oltr_methods,
244 sizeof(struct oltr_softc)
247 static devclass_t oltr_devclass;
249 DRIVER_MODULE(oltr, pci, oltr_driver, oltr_devclass, 0, 0);
251 static int
252 oltr_pci_probe(device_t dev)
254 int i, rc;
255 char PCIConfigHeader[64];
256 TRlldAdapterConfig_t config;
258 if ((pci_get_vendor(dev) == PCI_VENDOR_OLICOM) &&
259 ((pci_get_device(dev) == 0x0001) ||
260 (pci_get_device(dev) == 0x0004) ||
261 (pci_get_device(dev) == 0x0005) ||
262 (pci_get_device(dev) == 0x0007) ||
263 (pci_get_device(dev) == 0x0008))) {
265 for (i = 0; i < sizeof(PCIConfigHeader); i++)
266 PCIConfigHeader[i] = pci_read_config(dev, i, 1);
268 rc = TRlldPCIConfig(&LldDriver, &config, PCIConfigHeader);
269 if (rc == TRLLD_PCICONFIG_FAIL) {
270 device_printf(dev, "TRlldPciConfig failed!\n");
271 return(ENXIO);
273 if (rc == TRLLD_PCICONFIG_VERSION) {
274 device_printf(dev, "wrong LLD version\n");
275 return(ENXIO);
277 device_set_desc(dev, AdapterName[config.type]);
278 return(0);
280 return(ENXIO);
283 static int
284 oltr_pci_attach(device_t dev)
286 int i, rc = 0, rid,
287 scratch_size;
288 int media = IFM_TOKEN|IFM_TOK_UTP16;
289 u_long command;
290 char PCIConfigHeader[64];
291 struct oltr_softc *sc = device_get_softc(dev);
292 struct ifnet *ifp = &sc->arpcom.ac_if;
294 crit_enter();
296 bzero(sc, sizeof(struct oltr_softc));
297 sc->unit = device_get_unit(dev);
298 sc->state = OL_UNKNOWN;
300 for (i = 0; i < sizeof(PCIConfigHeader); i++)
301 PCIConfigHeader[i] = pci_read_config(dev, i, 1);
303 switch(TRlldPCIConfig(&LldDriver, &sc->config, PCIConfigHeader)) {
304 case TRLLD_PCICONFIG_OK:
305 break;
306 case TRLLD_PCICONFIG_SET_COMMAND:
307 device_printf(dev, "enabling bus master mode\n");
308 command = pci_read_config(dev, PCIR_COMMAND, 4);
309 pci_write_config(dev, PCIR_COMMAND,
310 (command | PCIM_CMD_BUSMASTEREN), 4);
311 command = pci_read_config(dev, PCIR_COMMAND, 4);
312 if (!(command & PCIM_CMD_BUSMASTEREN)) {
313 device_printf(dev, "failed to enable bus master mode\n");
314 goto config_failed;
316 break;
317 case TRLLD_PCICONFIG_FAIL:
318 device_printf(dev, "TRlldPciConfig failed!\n");
319 goto config_failed;
320 break;
321 case TRLLD_PCICONFIG_VERSION:
322 device_printf(dev, "wrong LLD version\n");
323 goto config_failed;
324 break;
326 device_printf(dev, "MAC address %6D\n", sc->config.macaddress, ":");
328 scratch_size = TRlldAdapterSize();
329 if (bootverbose)
330 device_printf(dev, "adapter memory block size %d bytes\n", scratch_size);
331 sc->TRlldAdapter = (TRlldAdapter_t)kmalloc(scratch_size, M_DEVBUF, M_NOWAIT);
332 if (sc->TRlldAdapter == NULL) {
333 device_printf(dev, "couldn't allocate scratch buffer (%d bytes)\n", scratch_size);
334 goto config_failed;
338 * Allocate RX/TX Pools
340 for (i = 0; i < RING_BUFFER_LEN; i++) {
341 sc->rx_ring[i].index = i;
342 sc->rx_ring[i].data = (char *)kmalloc(RX_BUFFER_LEN, M_DEVBUF, M_NOWAIT);
343 sc->rx_ring[i].address = vtophys(sc->rx_ring[i].data);
344 sc->tx_ring[i].index = i;
345 sc->tx_ring[i].data = (char *)kmalloc(TX_BUFFER_LEN, M_DEVBUF, M_NOWAIT);
346 sc->tx_ring[i].address = vtophys(sc->tx_ring[i].data);
347 if ((!sc->rx_ring[i].data) || (!sc->tx_ring[i].data)) {
348 device_printf(dev, "unable to allocate ring buffers\n");
349 while (i > 0) {
350 if (sc->rx_ring[i].data)
351 kfree(sc->rx_ring[i].data, M_DEVBUF);
352 if (sc->tx_ring[i].data)
353 kfree(sc->tx_ring[i].data, M_DEVBUF);
354 i--;
356 goto config_failed;
361 * Allocate interrupt and DMA channel
363 rid = 0;
364 sc->oltr_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
365 (sc->config.mode & TRLLD_MODE_SHARE_INTERRUPT ? RF_ACTIVE | RF_SHAREABLE : RF_ACTIVE));
366 if (sc->oltr_irq == NULL) {
367 device_printf(dev, "couldn't map interrupt\n");
368 goto config_failed;
370 if (bus_setup_intr(dev, sc->oltr_irq, 0, oltr_intr, sc,
371 &sc->oltr_intrhand, NULL)) {
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;
378 * Do the ifnet initialization
380 ifp->if_softc = sc;
381 if_initname(ifp, "oltr", device_get_unit(dev));
382 ifp->if_init = oltr_init;
383 ifp->if_start = oltr_start;
384 ifp->if_ioctl = oltr_ioctl;
385 ifp->if_flags = IFF_BROADCAST;
386 bcopy(sc->config.macaddress, sc->arpcom.ac_enaddr, sizeof(sc->config.macaddress));
389 * Do ifmedia setup.
391 ifmedia_init(&sc->ifmedia, 0, oltr_ifmedia_upd, oltr_ifmedia_sts);
392 rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS);
393 switch(sc->config.type) {
394 case TRLLD_ADAPTER_PCI7: /* OC-3540 */
395 ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP100, 0, NULL);
396 /* FALL THROUGH */
397 case TRLLD_ADAPTER_PCI4: /* OC-3139 */
398 case TRLLD_ADAPTER_PCI5: /* OC-3140 */
399 case TRLLD_ADAPTER_PCI6: /* OC-3141 */
400 ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_AUTO, 0, NULL);
401 media = IFM_TOKEN|IFM_AUTO;
402 rc = TRlldSetSpeed(sc->TRlldAdapter, 0);
403 /* FALL THROUGH */
404 default:
405 ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP4, 0, NULL);
406 ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP16, 0, NULL);
407 break;
409 sc->ifmedia.ifm_media = media;
410 ifmedia_set(&sc->ifmedia, media);
413 * Attach the interface
415 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
416 iso88025_ifattach(ifp, NULL);
418 crit_exit();
419 return(0);
421 config_failed:
423 crit_exit();
424 return(ENXIO);
427 static int
428 oltr_pci_detach(device_t dev)
430 struct oltr_softc *sc = device_get_softc(dev);
431 struct ifnet *ifp = &sc->arpcom.ac_if;
432 int i;
434 device_printf(dev, "driver unloading\n");
436 crit_enter();
438 if_detach(ifp);
439 if (sc->state > OL_CLOSED)
440 oltr_stop(sc);
442 callout_stop(&sc->oltr_poll_ch);
443 /*untimeout(oltr_stat, (void *)sc, sc->oltr_stat_ch);*/
445 bus_teardown_intr(dev, sc->oltr_irq, sc->oltr_intrhand);
446 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->oltr_irq);
448 /* Deallocate all dynamic memory regions */
449 for (i = 0; i < RING_BUFFER_LEN; i++) {
450 kfree(sc->rx_ring[i].data, M_DEVBUF);
451 kfree(sc->tx_ring[i].data, M_DEVBUF);
453 if (sc->work_memory)
454 kfree(sc->work_memory, M_DEVBUF);
455 kfree(sc->TRlldAdapter, M_DEVBUF);
457 crit_exit();
459 return(0);
462 static void
463 oltr_pci_shutdown(device_t dev)
465 struct oltr_softc *sc = device_get_softc(dev);
467 device_printf(dev, "oltr_pci_shutdown called\n");
469 if (sc->state > OL_CLOSED)
470 oltr_stop(sc);
472 return;
475 #else
477 static const char *oltr_pci_probe (pcici_t, pcidi_t);
478 static void oltr_pci_attach (pcici_t, int);
480 static unsigned long oltr_count = 0;
482 static struct pci_device oltr_device = {
483 "oltr",
484 oltr_pci_probe,
485 oltr_pci_attach,
486 &oltr_count,
487 NULL
490 DATA_SET(pcidevice_set, oltr_device);
492 static const char *
493 oltr_pci_probe(pcici_t config_id, pcidi_t device_id)
495 int i, rc;
496 char PCIConfigHeader[64];
497 TRlldAdapterConfig_t config;
499 if (((device_id & 0xffff) == PCI_VENDOR_OLICOM) && (
500 (((device_id >> 16) & 0xffff) == 0x0001) ||
501 (((device_id >> 16) & 0xffff) == 0x0004) ||
502 (((device_id >> 16) & 0xffff) == 0x0005) ||
503 (((device_id >> 16) & 0xffff) == 0x0007) ||
504 (((device_id >> 16) & 0xffff) == 0x0008))) {
506 for (i = 0; i < 64; i++)
507 PCIConfigHeader[i] = pci_cfgread(config_id, i, /* bytes */ 1);
509 rc = TRlldPCIConfig(&LldDriver, &config, PCIConfigHeader);
511 if (rc == TRLLD_PCICONFIG_FAIL) {
512 printf("oltr: TRlldPciConfig failed!\n");
513 return(NULL);
515 if (rc == TRLLD_PCICONFIG_VERSION) {
516 printf("oltr: wrong LLD version.\n");
517 return(NULL);
519 return(AdapterName[config.type]);
522 return(NULL);
525 static void
526 oltr_pci_attach(pcici_t config_id, int unit)
528 int i, rc = 0, scratch_size;
529 int media = IFM_TOKEN|IFM_TOK_UTP16;
530 u_long command;
531 char PCIConfigHeader[64];
532 struct oltr_softc *sc;
533 struct ifnet *ifp; /* = &sc->arpcom.ac_if; */
535 crit_enter();
537 sc = kmalloc(sizeof(struct oltr_softc), M_DEVBUF, M_NOWAIT | M_ZERO);
538 if (sc == NULL) {
539 printf("oltr%d: no memory for softc struct!\n", unit);
540 goto config_failed;
542 sc->unit = unit;
543 sc->state = OL_UNKNOWN;
544 ifp = &sc->arpcom.ac_if;
546 for (i = 0; i < sizeof(PCIConfigHeader); i++)
547 PCIConfigHeader[i] = pci_cfgread(config_id, i, 1);
549 switch(TRlldPCIConfig(&LldDriver, &sc->config, PCIConfigHeader)) {
550 case TRLLD_PCICONFIG_OK:
551 break;
552 case TRLLD_PCICONFIG_SET_COMMAND:
553 printf("oltr%d: enabling bus master mode\n", unit);
554 command = pci_conf_read(config_id, PCIR_COMMAND);
555 pci_conf_write(config_id, PCIR_COMMAND, (command | PCIM_CMD_BUSMASTEREN));
556 command = pci_conf_read(config_id, PCIR_COMMAND);
557 if (!(command & PCIM_CMD_BUSMASTEREN)) {
558 printf("oltr%d: failed to enable bus master mode\n", unit);
559 goto config_failed;
561 break;
562 case TRLLD_PCICONFIG_FAIL:
563 printf("oltr%d: TRlldPciConfig failed!\n", unit);
564 goto config_failed;
565 break;
566 case TRLLD_PCICONFIG_VERSION:
567 printf("oltr%d: wrong LLD version\n", unit);
568 goto config_failed;
569 break;
571 printf("oltr%d: MAC address %6D\n", unit, sc->config.macaddress, ":");
573 scratch_size = TRlldAdapterSize();
574 if (bootverbose)
575 printf("oltr%d: adapter memory block size %d bytes\n", unit, scratch_size);
576 sc->TRlldAdapter = (TRlldAdapter_t)kmalloc(scratch_size, M_DEVBUF, M_NOWAIT);
577 if (sc->TRlldAdapter == NULL) {
578 printf("oltr%d: couldn't allocate scratch buffer (%d bytes)\n",unit, scratch_size);
579 goto config_failed;
583 * Allocate RX/TX Pools
585 for (i = 0; i < RING_BUFFER_LEN; i++) {
586 sc->rx_ring[i].index = i;
587 sc->rx_ring[i].data = (char *)kmalloc(RX_BUFFER_LEN, M_DEVBUF, M_NOWAIT);
588 sc->rx_ring[i].address = vtophys(sc->rx_ring[i].data);
589 sc->tx_ring[i].index = i;
590 sc->tx_ring[i].data = (char *)kmalloc(TX_BUFFER_LEN, M_DEVBUF, M_NOWAIT);
591 sc->tx_ring[i].address = vtophys(sc->tx_ring[i].data);
592 if ((!sc->rx_ring[i].data) || (!sc->tx_ring[i].data)) {
593 printf("oltr%d: unable to allocate ring buffers\n", unit);
594 while (i > 0) {
595 if (sc->rx_ring[i].data)
596 kfree(sc->rx_ring[i].data, M_DEVBUF);
597 if (sc->tx_ring[i].data)
598 kfree(sc->tx_ring[i].data, M_DEVBUF);
599 i--;
601 goto config_failed;
606 * Allocate interrupt and DMA channel
608 if (!pci_map_int(config_id, oltr_intr, sc)) {
609 printf("oltr%d: couldn't setup interrupt\n", unit);
610 goto config_failed;
614 * Do the ifnet initialization
616 ifp->if_softc = sc;
617 if_initname(ifp, "oltr", unit);
618 ifp->if_output = iso88025_output;
619 ifp->if_init = oltr_init;
620 ifp->if_start = oltr_start;
621 ifp->if_ioctl = oltr_ioctl;
622 ifp->if_flags = IFF_BROADCAST;
623 bcopy(sc->config.macaddress, sc->arpcom.ac_enaddr, sizeof(sc->config.macaddress));
626 * Do ifmedia setup.
628 ifmedia_init(&sc->ifmedia, 0, oltr_ifmedia_upd, oltr_ifmedia_sts);
629 rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS);
630 switch(sc->config.type) {
631 case TRLLD_ADAPTER_PCI7: /* OC-3540 */
632 ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP100, 0, NULL);
633 /* FALL THROUGH */
634 case TRLLD_ADAPTER_PCI4: /* OC-3139 */
635 case TRLLD_ADAPTER_PCI5: /* OC-3140 */
636 case TRLLD_ADAPTER_PCI6: /* OC-3141 */
637 ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_AUTO, 0, NULL);
638 media = IFM_TOKEN|IFM_AUTO;
639 rc = TRlldSetSpeed(sc->TRlldAdapter, 0);
640 /* FALL THROUGH */
641 default:
642 ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP4, 0, NULL);
643 ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP16, 0, NULL);
644 break;
646 sc->ifmedia.ifm_media = media;
647 ifmedia_set(&sc->ifmedia, media);
650 * Attach the interface
652 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
653 iso88025_ifattach(ifp);
655 crit_exit();
656 return;
658 config_failed:
659 crit_exit();
661 return;
664 #endif
666 static void
667 oltr_intr(void *xsc)
669 struct oltr_softc *sc = (struct oltr_softc *)xsc;
671 if (DEBUG_MASK & DEBUG_INT)
672 printf("I");
674 TRlldInterruptService(sc->TRlldAdapter);
676 return;
679 static void
680 oltr_start(struct ifnet *ifp)
682 struct oltr_softc *sc = ifp->if_softc;
683 struct mbuf *m0, *m;
684 int copy_len, buffer, frame, fragment, rc;
687 * Check to see if output is already active
689 if (ifp->if_flags & IFF_OACTIVE)
690 return;
692 outloop:
695 * Make sure we have buffers to transmit with
697 if (sc->tx_avail <= 0) {
698 printf("oltr%d: tx queue full\n", sc->unit);
699 ifp->if_flags |= IFF_OACTIVE;
700 return;
703 if (sc->restart == NULL) {
704 IF_DEQUEUE(&ifp->if_snd, m);
705 if (m == NULL)
706 return;
707 } else {
708 m = sc->restart;
709 sc->restart = NULL;
712 m0 = m;
713 frame = RING_BUFFER(sc->tx_frame);
714 buffer = RING_BUFFER(sc->tx_head);
715 fragment = 0;
716 copy_len = 0;
717 sc->frame_ring[frame].FragmentCount = 0;
719 while (copy_len < m0->m_pkthdr.len) {
720 sc->frame_ring[frame].FragmentCount++;
721 if (sc->frame_ring[frame].FragmentCount > sc->tx_avail)
722 goto nobuffers;
723 sc->frame_ring[frame].TransmitFragment[fragment].VirtualAddress = sc->tx_ring[buffer].data;
724 sc->frame_ring[frame].TransmitFragment[fragment].PhysicalAddress = sc->tx_ring[buffer].address;
725 sc->frame_ring[frame].TransmitFragment[fragment].count = MIN(m0->m_pkthdr.len - copy_len, TX_BUFFER_LEN);
726 m_copydata(m0, copy_len, MIN(m0->m_pkthdr.len - copy_len, TX_BUFFER_LEN), sc->tx_ring[buffer].data);
727 copy_len += MIN(m0->m_pkthdr.len - copy_len, TX_BUFFER_LEN);
728 fragment++;
729 buffer = RING_BUFFER((buffer + 1));
732 crit_enter();
733 rc = TRlldTransmitFrame(sc->TRlldAdapter, &sc->frame_ring[frame],
734 (void *)&sc->frame_ring[frame]);
735 crit_exit();
737 if (rc != TRLLD_TRANSMIT_OK) {
738 printf("oltr%d: TRlldTransmitFrame returned %d\n", sc->unit, rc);
739 ifp->if_oerrors++;
740 goto bad;
743 sc->tx_avail -= sc->frame_ring[frame].FragmentCount;
744 sc->tx_head = RING_BUFFER((sc->tx_head + sc->frame_ring[frame].FragmentCount));
745 sc->tx_frame++;
747 BPF_MTAP(ifp, m0);
748 /*ifp->if_opackets++;*/
750 bad:
751 m_freem(m0);
753 goto outloop;
755 nobuffers:
757 printf("oltr%d: queue full\n", sc->unit);
758 ifp->if_flags |= IFF_OACTIVE;
759 ifp->if_oerrors++;
760 /*m_freem(m0);*/
761 sc->restart = m0;
763 return;
766 static void
767 oltr_close(struct oltr_softc *sc)
769 /*printf("oltr%d: oltr_close\n", sc->unit);*/
771 oltr_stop(sc);
773 tsleep(sc, 0, "oltrclose", 30*hz);
776 static void
777 oltr_stop(struct oltr_softc *sc)
779 struct ifnet *ifp = &sc->arpcom.ac_if;
781 /*printf("oltr%d: oltr_stop\n", sc->unit);*/
783 ifp->if_flags &= ~(IFF_UP | IFF_RUNNING | IFF_OACTIVE);
784 TRlldClose(sc->TRlldAdapter, 0);
785 sc->state = OL_CLOSING;
788 static void
789 oltr_init(void * xsc)
791 struct oltr_softc *sc = (struct oltr_softc *)xsc;
792 struct ifnet *ifp = &sc->arpcom.ac_if;
793 struct ifmedia *ifm = &sc->ifmedia;
794 int poll = 0, i, rc = 0;
795 int work_size;
798 * Check adapter state, don't allow multiple inits
800 if (sc->state > OL_CLOSED) {
801 printf("oltr%d: adapter not ready\n", sc->unit);
802 return;
805 crit_enter();
808 * Initialize Adapter
810 if ((rc = TRlldAdapterInit(&LldDriver, sc->TRlldAdapter, vtophys(sc->TRlldAdapter),
811 (void *)sc, &sc->config)) != TRLLD_INIT_OK) {
812 switch(rc) {
813 case TRLLD_INIT_NOT_FOUND:
814 printf("oltr%d: adapter not found\n", sc->unit);
815 break;
816 case TRLLD_INIT_UNSUPPORTED:
817 printf("oltr%d: adapter not supported by low level driver\n", sc->unit);
818 break;
819 case TRLLD_INIT_PHYS16:
820 printf("oltr%d: adapter memory block above 16M cannot DMA\n", sc->unit);
821 break;
822 case TRLLD_INIT_VERSION:
823 printf("oltr%d: low level driver version mismatch\n", sc->unit);
824 break;
825 default:
826 printf("oltr%d: unknown init error %d\n", sc->unit, rc);
827 break;
829 goto init_failed;
831 sc->state = OL_INIT;
833 switch(sc->config.type) {
834 case TRLLD_ADAPTER_PCI4: /* OC-3139 */
835 work_size = 32 * 1024;
836 break;
837 case TRLLD_ADAPTER_PCI7: /* OC-3540 */
838 work_size = 256;
839 break;
840 default:
841 work_size = 0;
844 if (work_size) {
845 if ((sc->work_memory = kmalloc(work_size, M_DEVBUF, M_NOWAIT)) == NULL) {
846 printf("oltr%d: failed to allocate work memory (%d octets).\n", sc->unit, work_size);
847 } else {
848 TRlldAddMemory(sc->TRlldAdapter, sc->work_memory,
849 vtophys(sc->work_memory), work_size);
853 switch(IFM_SUBTYPE(ifm->ifm_media)) {
854 case IFM_AUTO:
855 rc = TRlldSetSpeed(sc->TRlldAdapter, 0); /* TRLLD_SPEED_AUTO */
856 break;
857 case IFM_TOK_UTP4:
858 rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_4MBPS);
859 break;
860 case IFM_TOK_UTP16:
861 rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS);
862 break;
863 case IFM_TOK_UTP100:
864 rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_100MBPS);
865 break;
869 * Download adapter micro-code
871 if (bootverbose)
872 printf("oltr%d: Downloading adapter microcode: ", sc->unit);
874 switch(sc->config.mactype) {
875 case TRLLD_MAC_TMS:
876 rc = TRlldDownload(sc->TRlldAdapter, TRlldMacCode);
877 if (bootverbose)
878 printf("TMS-380");
879 break;
880 case TRLLD_MAC_HAWKEYE:
881 rc = TRlldDownload(sc->TRlldAdapter, TRlldHawkeyeMac);
882 if (bootverbose)
883 printf("Hawkeye");
884 break;
885 case TRLLD_MAC_BULLSEYE:
886 rc = TRlldDownload(sc->TRlldAdapter, TRlldBullseyeMac);
887 if (bootverbose)
888 printf("Bullseye");
889 break;
890 default:
891 if (bootverbose)
892 printf("unknown - failed!\n");
893 goto init_failed;
894 break;
898 * Check download status
900 switch(rc) {
901 case TRLLD_DOWNLOAD_OK:
902 if (bootverbose)
903 printf(" - ok\n");
904 break;
905 case TRLLD_DOWNLOAD_ERROR:
906 if (bootverbose)
907 printf(" - failed\n");
908 else
909 printf("oltr%d: adapter microcode download failed\n", sc->unit);
910 goto init_failed;
911 break;
912 case TRLLD_STATE:
913 if (bootverbose)
914 printf(" - not ready\n");
915 goto init_failed;
916 break;
920 * Wait for self-test to complete
922 i = 0;
923 while ((poll++ < SELF_TEST_POLLS) && (sc->state < OL_READY)) {
924 if (DEBUG_MASK & DEBUG_INIT)
925 printf("p");
926 DELAY(TRlldPoll(sc->TRlldAdapter) * 1000);
927 if (TRlldInterruptService(sc->TRlldAdapter) != 0)
928 if (DEBUG_MASK & DEBUG_INIT) printf("i");
931 if (sc->state != OL_CLOSED) {
932 printf("oltr%d: self-test failed\n", sc->unit);
933 goto init_failed;
937 * Set up adapter poll
939 callout_init(&sc->oltr_poll_ch);
940 callout_reset(&sc->oltr_poll_ch, 1, oltr_poll, sc);
942 sc->state = OL_OPENING;
945 * Open the adapter
947 rc = TRlldOpen(sc->TRlldAdapter, sc->arpcom.ac_enaddr, sc->GroupAddress,
948 sc->FunctionalAddress, 1552, sc->AdapterMode);
949 switch(rc) {
950 case TRLLD_OPEN_OK:
951 break;
952 case TRLLD_OPEN_STATE:
953 printf("oltr%d: adapter not ready for open\n", sc->unit);
954 crit_exit();
955 return;
956 case TRLLD_OPEN_ADDRESS_ERROR:
957 printf("oltr%d: illegal MAC address\n", sc->unit);
958 crit_exit();
959 return;
960 case TRLLD_OPEN_MODE_ERROR:
961 printf("oltr%d: illegal open mode\n", sc->unit);
962 crit_exit();
963 return;
964 default:
965 printf("oltr%d: unknown open error (%d)\n", sc->unit, rc);
966 crit_exit();
967 return;
971 * Set promiscious mode for now...
973 TRlldSetPromiscuousMode(sc->TRlldAdapter, TRLLD_PROM_LLC);
974 ifp->if_flags |= IFF_PROMISC;
977 * Block on the ring insert and set a timeout
979 tsleep(sc, 0, "oltropen", 30*hz);
982 * Set up receive buffer ring
984 for (i = 0; i < RING_BUFFER_LEN; i++) {
985 rc = TRlldReceiveFragment(sc->TRlldAdapter, (void *)sc->rx_ring[i].data,
986 sc->rx_ring[i].address, RX_BUFFER_LEN, (void *)sc->rx_ring[i].index);
987 if (rc != TRLLD_RECEIVE_OK) {
988 printf("oltr%d: adapter refused receive fragment %d (rc = %d)\n", sc->unit, i, rc);
989 break;
993 sc->tx_avail = RING_BUFFER_LEN;
994 sc->tx_head = 0;
995 sc->tx_frame = 0;
997 sc->restart = NULL;
999 ifp->if_flags |= IFF_RUNNING;
1000 ifp->if_flags &= ~IFF_OACTIVE;
1003 * Set up adapter statistics poll
1005 /*callout_handle_init(&sc->oltr_stat_ch);*/
1006 /*sc->oltr_stat_ch = timeout(oltr_stat, (void *)sc, 1*hz);*/
1008 crit_exit();
1009 return;
1011 init_failed:
1012 sc->state = OL_DEAD;
1013 crit_exit();
1014 return;
1017 static int
1018 oltr_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
1020 struct oltr_softc *sc = ifp->if_softc;
1021 struct ifreq *ifr = (struct ifreq *)data;
1022 int error = 0;
1024 crit_enter();
1026 switch(command) {
1027 case SIOCSIFADDR:
1028 case SIOCGIFADDR:
1029 case SIOCSIFMTU:
1030 error = iso88025_ioctl(ifp, command, data);
1031 break;
1033 case SIOCSIFFLAGS:
1034 if (ifp->if_flags & IFF_UP) {
1035 oltr_init(sc);
1036 } else {
1037 if (ifp->if_flags & IFF_RUNNING) {
1038 oltr_close(sc);
1041 break;
1042 case SIOCGIFMEDIA:
1043 case SIOCSIFMEDIA:
1044 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
1045 break;
1046 default:
1047 error = EINVAL;
1048 break;
1051 crit_exit();
1053 return(error);
1057 void
1058 oltr_poll(void *arg)
1060 struct oltr_softc *sc = (struct oltr_softc *)arg;
1062 crit_enter();
1064 if (DEBUG_MASK & DEBUG_POLL) printf("P");
1066 /* Set up next adapter poll */
1067 callout_reset(&sc->oltr_poll_ch,
1068 (TRlldPoll(sc->TRlldAdapter) * hz / 1000), oltr_poll, sc);
1070 crit_exit();
1073 #ifdef NOTYET
1074 void
1075 oltr_stat(void *arg)
1077 struct oltr_softc *sc = (struct oltr_softc *)arg;
1079 crit_enter();
1081 /* Set up next adapter poll */
1082 sc->oltr_stat_ch = timeout(oltr_stat, (void *)sc, 1*hz);
1083 if (TRlldGetStatistics(sc->TRlldAdapter, &sc->current, 0) != 0) {
1084 /*printf("oltr%d: statistics available immediately...\n", sc->unit);*/
1085 DriverStatistics((void *)sc, &sc->current);
1088 crit_exit();
1090 #endif
1091 static int
1092 oltr_ifmedia_upd(struct ifnet *ifp)
1094 struct oltr_softc *sc = ifp->if_softc;
1095 struct ifmedia *ifm = &sc->ifmedia;
1096 int rc;
1098 if (IFM_TYPE(ifm->ifm_media) != IFM_TOKEN)
1099 return(EINVAL);
1101 switch(IFM_SUBTYPE(ifm->ifm_media)) {
1102 case IFM_AUTO:
1103 rc = TRlldSetSpeed(sc->TRlldAdapter, 0); /* TRLLD_SPEED_AUTO */
1104 break;
1105 case IFM_TOK_UTP4:
1106 rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_4MBPS);
1107 break;
1108 case IFM_TOK_UTP16:
1109 rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS);
1110 break;
1111 case IFM_TOK_UTP100:
1112 rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_100MBPS);
1113 break;
1114 default:
1115 return(EINVAL);
1116 break;
1119 return(0);
1123 static void
1124 oltr_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
1126 struct oltr_softc *sc = ifp->if_softc;
1127 struct ifmedia *ifm = &sc->ifmedia;
1129 /*printf("oltr%d: oltr_ifmedia_sts\n", sc->unit);*/
1131 ifmr->ifm_active = IFM_TYPE(ifm->ifm_media)|IFM_SUBTYPE(ifm->ifm_media);
1136 * ---------------------- PMW Callback Functions -----------------------
1139 void
1140 DriverStatistics(void *DriverHandle, TRlldStatistics_t *statistics)
1142 #ifdef NOTYET
1143 struct oltr_softc *sc = (struct oltr_softc *)DriverHandle;
1145 if (sc->statistics.LineErrors != statistics->LineErrors)
1146 printf("oltr%d: Line Errors %lu\n", sc->unit,
1147 statistics->LineErrors);
1148 if (sc->statistics.InternalErrors != statistics->InternalErrors)
1149 printf("oltr%d: Internal Errors %lu\n", sc->unit,
1150 statistics->InternalErrors);
1151 if (sc->statistics.BurstErrors != statistics->BurstErrors)
1152 printf("oltr%d: Burst Errors %lu\n", sc->unit,
1153 statistics->BurstErrors);
1154 if (sc->statistics.AbortDelimiters != statistics->AbortDelimiters)
1155 printf("oltr%d: Abort Delimiters %lu\n", sc->unit,
1156 statistics->AbortDelimiters);
1157 if (sc->statistics.ARIFCIErrors != statistics->ARIFCIErrors)
1158 printf("oltr%d: ARIFCI Errors %lu\n", sc->unit,
1159 statistics->ARIFCIErrors);
1160 if (sc->statistics.LostFrames != statistics->LostFrames)
1161 printf("oltr%d: Lost Frames %lu\n", sc->unit,
1162 statistics->LostFrames);
1163 if (sc->statistics.CongestionErrors != statistics->CongestionErrors)
1164 printf("oltr%d: Congestion Errors %lu\n", sc->unit,
1165 statistics->CongestionErrors);
1166 if (sc->statistics.FrequencyErrors != statistics->FrequencyErrors)
1167 printf("oltr%d: Frequency Errors %lu\n", sc->unit,
1168 statistics->FrequencyErrors);
1169 if (sc->statistics.TokenErrors != statistics->TokenErrors)
1170 printf("oltr%d: Token Errors %lu\n", sc->unit,
1171 statistics->TokenErrors);
1172 if (sc->statistics.DMABusErrors != statistics->DMABusErrors)
1173 printf("oltr%d: DMA Bus Errors %lu\n", sc->unit,
1174 statistics->DMABusErrors);
1175 if (sc->statistics.DMAParityErrors != statistics->DMAParityErrors)
1176 printf("oltr%d: DMA Parity Errors %lu\n", sc->unit,
1177 statistics->DMAParityErrors);
1178 if (sc->statistics.ReceiveLongFrame != statistics->ReceiveLongFrame)
1179 printf("oltr%d: Long frames received %lu\n", sc->unit,
1180 statistics->ReceiveLongFrame);
1181 if (sc->statistics.ReceiveCRCErrors != statistics->ReceiveCRCErrors)
1182 printf("oltr%d: Receive CRC Errors %lu\n", sc->unit,
1183 statistics->ReceiveCRCErrors);
1184 if (sc->statistics.ReceiveOverflow != statistics->ReceiveOverflow)
1185 printf("oltr%d: Recieve overflows %lu\n", sc->unit,
1186 statistics->ReceiveOverflow);
1187 if (sc->statistics.TransmitUnderrun != statistics->TransmitUnderrun)
1188 printf("oltr%d: Frequency Errors %lu\n", sc->unit,
1189 statistics->TransmitUnderrun);
1190 bcopy(statistics, &sc->statistics, sizeof(TRlldStatistics_t));
1191 #endif
1194 static void
1195 DriverSuspend(unsigned short MicroSeconds)
1197 DELAY(MicroSeconds);
1201 static void
1202 DriverStatus(void *DriverHandle, TRlldStatus_t *Status)
1204 struct oltr_softc *sc = (struct oltr_softc *)DriverHandle;
1205 struct ifnet *ifp = &sc->arpcom.ac_if;
1207 char *Protocol[] = { /* 0 */ "Unknown",
1208 /* 1 */ "TKP",
1209 /* 2 */ "TXI" };
1210 char *Timeout[] = { /* 0 */ "command",
1211 /* 1 */ "transmit",
1212 /* 2 */ "interrupt" };
1214 switch (Status->Type) {
1216 case TRLLD_STS_ON_WIRE:
1217 printf("oltr%d: ring insert (%d Mbps - %s)\n", sc->unit,
1218 Status->Specification.OnWireInformation.Speed,
1219 Protocol[Status->Specification.OnWireInformation.AccessProtocol]);
1220 sc->state = OL_OPEN;
1221 wakeup(sc);
1222 break;
1223 case TRLLD_STS_SELFTEST_STATUS:
1224 if (Status->Specification.SelftestStatus == TRLLD_ST_OK) {
1225 sc->state = OL_CLOSED;
1226 if (bootverbose)
1227 printf("oltr%d: self test complete\n", sc->unit);
1229 if (Status->Specification.SelftestStatus & TRLLD_ST_ERROR) {
1230 printf("oltr%d: Adapter self test error %d", sc->unit,
1231 Status->Specification.SelftestStatus & ~TRLLD_ST_ERROR);
1232 sc->state = OL_DEAD;
1234 if (Status->Specification.SelftestStatus & TRLLD_ST_TIMEOUT) {
1235 printf("oltr%d: Adapter self test timed out.\n", sc->unit);
1236 sc->state = OL_DEAD;
1238 break;
1239 case TRLLD_STS_INIT_STATUS:
1240 if (Status->Specification.InitStatus == 0x800) {
1241 oltr_stop(sc);
1242 ifmedia_set(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP16);
1243 TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS);
1244 oltr_init(sc);
1245 break;
1247 printf("oltr%d: adapter init failure 0x%03x\n", sc->unit,
1248 Status->Specification.InitStatus);
1249 oltr_stop(sc);
1250 break;
1251 case TRLLD_STS_RING_STATUS:
1252 if (Status->Specification.RingStatus) {
1253 printf("oltr%d: Ring status change: ", sc->unit);
1254 if (Status->Specification.RingStatus &
1255 TRLLD_RS_SIGNAL_LOSS)
1256 printf(" [Signal Loss]");
1257 if (Status->Specification.RingStatus &
1258 TRLLD_RS_HARD_ERROR)
1259 printf(" [Hard Error]");
1260 if (Status->Specification.RingStatus &
1261 TRLLD_RS_SOFT_ERROR)
1262 printf(" [Soft Error]");
1263 if (Status->Specification.RingStatus &
1264 TRLLD_RS_TRANSMIT_BEACON)
1265 printf(" [Beacon]");
1266 if (Status->Specification.RingStatus &
1267 TRLLD_RS_LOBE_WIRE_FAULT)
1268 printf(" [Wire Fault]");
1269 if (Status->Specification.RingStatus &
1270 TRLLD_RS_AUTO_REMOVAL_ERROR)
1271 printf(" [Auto Removal]");
1272 if (Status->Specification.RingStatus &
1273 TRLLD_RS_REMOVE_RECEIVED)
1274 printf(" [Remove Received]");
1275 if (Status->Specification.RingStatus &
1276 TRLLD_RS_COUNTER_OVERFLOW)
1277 printf(" [Counter Overflow]");
1278 if (Status->Specification.RingStatus &
1279 TRLLD_RS_SINGLE_STATION)
1280 printf(" [Single Station]");
1281 if (Status->Specification.RingStatus &
1282 TRLLD_RS_RING_RECOVERY)
1283 printf(" [Ring Recovery]");
1284 printf("\n");
1286 break;
1287 case TRLLD_STS_ADAPTER_CHECK:
1288 printf("oltr%d: adapter check (%04x %04x %04x %04x)\n", sc->unit,
1289 Status->Specification.AdapterCheck[0],
1290 Status->Specification.AdapterCheck[1],
1291 Status->Specification.AdapterCheck[2],
1292 Status->Specification.AdapterCheck[3]);
1293 sc->state = OL_DEAD;
1294 oltr_stop(sc);
1295 break;
1296 case TRLLD_STS_PROMISCUOUS_STOPPED:
1297 printf("oltr%d: promiscuous mode ", sc->unit);
1298 if (Status->Specification.PromRemovedCause == 1)
1299 printf("remove received.");
1300 if (Status->Specification.PromRemovedCause == 2)
1301 printf("poll failure.");
1302 if (Status->Specification.PromRemovedCause == 2)
1303 printf("buffer size failure.");
1304 printf("\n");
1305 ifp->if_flags &= ~IFF_PROMISC;
1306 break;
1307 case TRLLD_STS_LLD_ERROR:
1308 printf("oltr%d: low level driver internal error ", sc->unit);
1309 printf("(%04x %04x %04x %04x).\n",
1310 Status->Specification.InternalError[0],
1311 Status->Specification.InternalError[1],
1312 Status->Specification.InternalError[2],
1313 Status->Specification.InternalError[3]);
1314 sc->state = OL_DEAD;
1315 oltr_stop(sc);
1316 break;
1317 case TRLLD_STS_ADAPTER_TIMEOUT:
1318 printf("oltr%d: adapter %s timeout.\n", sc->unit,
1319 Timeout[Status->Specification.AdapterTimeout]);
1320 break;
1321 default:
1322 printf("oltr%d: driver status Type = %d\n", sc->unit, Status->Type);
1323 break;
1326 if (Status->Closed) {
1327 sc->state = OL_CLOSING;
1328 oltr_stop(sc);
1333 static void
1334 DriverCloseCompleted(void *DriverHandle)
1336 struct oltr_softc *sc = (struct oltr_softc *)DriverHandle;
1338 printf("oltr%d: adapter closed\n", sc->unit);
1339 wakeup(sc);
1340 sc->state = OL_CLOSED;
1343 static void
1344 DriverTransmitFrameCompleted(void *DriverHandle, void *FrameHandle, int TransmitStatus)
1346 struct oltr_softc *sc = (struct oltr_softc *)DriverHandle;
1347 struct ifnet *ifp = &sc->arpcom.ac_if;
1348 TRlldTransmit_t *frame = (TRlldTransmit_t *)FrameHandle;
1350 /*printf("oltr%d: DriverTransmitFrameCompleted\n", sc->unit);*/
1352 if (TransmitStatus != TRLLD_TRANSMIT_OK) {
1353 ifp->if_oerrors++;
1354 printf("oltr%d: transmit error %d\n", sc->unit, TransmitStatus);
1355 } else {
1356 ifp->if_opackets++;
1359 sc->tx_avail += frame->FragmentCount;
1361 if (ifp->if_flags & IFF_OACTIVE) {
1362 printf("oltr%d: queue restart\n", sc->unit);
1363 ifp->if_flags &= ~IFF_OACTIVE;
1364 oltr_start(ifp);
1370 static void
1371 DriverReceiveFrameCompleted(void *DriverHandle, int ByteCount, int FragmentCount, void *FragmentHandle, int ReceiveStatus)
1373 struct oltr_softc *sc = (struct oltr_softc *)DriverHandle;
1374 struct ifnet *ifp = (struct ifnet *)&sc->arpcom.ac_if;
1375 struct mbuf *m0, *m1, *m;
1376 struct iso88025_header *th;
1377 int frame_len = ByteCount, i = (int)FragmentHandle, rc;
1378 int mbuf_offset, mbuf_size, frag_offset, copy_length;
1379 char *fragment = sc->rx_ring[RING_BUFFER(i)].data;
1381 if (sc->state > OL_CLOSED) {
1382 if (ReceiveStatus == TRLLD_RCV_OK) {
1383 MGETHDR(m0, MB_DONTWAIT, MT_DATA);
1384 mbuf_size = MHLEN - 2;
1385 if (!m0) {
1386 ifp->if_ierrors++;
1387 goto dropped;
1389 if (ByteCount + 2 > MHLEN) {
1390 MCLGET(m0, MB_DONTWAIT);
1391 mbuf_size = MCLBYTES - 2;
1392 if (!(m0->m_flags & M_EXT)) {
1393 m_freem(m0);
1394 ifp->if_ierrors++;
1395 goto dropped;
1398 m0->m_pkthdr.rcvif = ifp;
1399 m0->m_pkthdr.len = ByteCount;
1400 m0->m_len = 0;
1401 m0->m_data += 2;
1402 th = mtod(m0, struct iso88025_header *);
1403 m0->m_pkthdr.header = (void *)th;
1405 m = m0;
1406 mbuf_offset = 0;
1407 frag_offset = 0;
1408 while (frame_len) {
1409 copy_length = MIN3(frame_len,
1410 (RX_BUFFER_LEN - frag_offset),
1411 (mbuf_size - mbuf_offset));
1412 bcopy(fragment + frag_offset, mtod(m, char *) +
1413 mbuf_offset, copy_length);
1414 m->m_len += copy_length;
1415 mbuf_offset += copy_length;
1416 frag_offset += copy_length;
1417 frame_len -= copy_length;
1419 if (frag_offset == RX_BUFFER_LEN) {
1420 fragment =
1421 sc->rx_ring[RING_BUFFER(++i)].data;
1422 frag_offset = 0;
1424 if ((mbuf_offset == mbuf_size) && (frame_len > 0)) {
1425 MGET(m1, MB_DONTWAIT, MT_DATA);
1426 mbuf_size = MHLEN;
1427 if (!m1) {
1428 ifp->if_ierrors++;
1429 m_freem(m0);
1430 goto dropped;
1432 if (frame_len > MHLEN) {
1433 MCLGET(m1, MB_DONTWAIT);
1434 mbuf_size = MCLBYTES;
1435 if (!(m1->m_flags & M_EXT)) {
1436 m_freem(m0);
1437 m_freem(m1);
1438 ifp->if_ierrors++;
1439 goto dropped;
1442 m->m_next = m1;
1443 m = m1;
1444 mbuf_offset = 0;
1445 m->m_len = 0;
1448 BPF_MTAP(ifp, m0);
1450 /*if (ifp->if_flags & IFF_PROMISC) {*/
1451 if (bcmp(th->iso88025_dhost, ifp->if_broadcastaddr,
1452 ifp->if_addrlen)) {
1453 if ((bcmp(th->iso88025_dhost + 1, sc->arpcom.ac_enaddr + 1, ISO88025_ADDR_LEN - 1)) ||
1454 ((th->iso88025_dhost[0] & 0x7f) != sc->arpcom.ac_enaddr[0])) {
1455 m_freem(m0);
1456 goto dropped;
1459 /*}*/
1460 ifp->if_ipackets++;
1462 (*ifp->if_input)(ifp, m0);
1464 } else { /* Receiver error */
1465 if (ReceiveStatus != TRLLD_RCV_NO_DATA) {
1466 printf("oltr%d: receive error %d\n", sc->unit,
1467 ReceiveStatus);
1468 ifp->if_ierrors++;
1472 dropped:
1473 crit_enter();
1474 i = (int)FragmentHandle;
1475 while (FragmentCount--) {
1476 rc = TRlldReceiveFragment(sc->TRlldAdapter,
1477 (void *)sc->rx_ring[RING_BUFFER(i)].data,
1478 sc->rx_ring[RING_BUFFER(i)].address,
1479 RX_BUFFER_LEN, (void *)sc->rx_ring[RING_BUFFER(i)].index);
1480 if (rc != TRLLD_RECEIVE_OK) {
1481 printf("oltr%d: adapter refused receive fragment %d (rc = %d)\n", sc->unit, i, rc);
1482 break;
1484 i++;
1486 crit_exit();
1492 * ---------------------------- PMW Glue -------------------------------
1495 #ifndef TRlldInlineIO
1497 static void
1498 DriverOutByte(unsigned short IOAddress, unsigned char value)
1500 outb(IOAddress, value);
1503 static void
1504 DriverOutWord(unsigned short IOAddress, unsigned short value)
1506 outw(IOAddress, value);
1509 static void
1510 DriverOutDword(unsigned short IOAddress, unsigned long value)
1512 outl(IOAddress, value);
1515 static void
1516 DriverRepOutByte(unsigned short IOAddress, unsigned char *DataPointer, int ByteCount)
1518 outsb(IOAddress, (void *)DataPointer, ByteCount);
1521 static void
1522 DriverRepOutWord(unsigned short IOAddress, unsigned short *DataPointer, int WordCount)
1524 outsw(IOAddress, (void *)DataPointer, WordCount);
1527 static void
1528 DriverRepOutDword(unsigned short IOAddress, unsigned long *DataPointer, int DWordCount)
1530 outsl(IOAddress, (void *)DataPointer, DWordCount);
1533 static unsigned char
1534 DriverInByte(unsigned short IOAddress)
1536 return(inb(IOAddress));
1539 static unsigned short
1540 DriverInWord(unsigned short IOAddress)
1542 return(inw(IOAddress));
1545 static unsigned long
1546 DriverInDword(unsigned short IOAddress)
1548 return(inl(IOAddress));
1551 static void
1552 DriverRepInByte(unsigned short IOAddress, unsigned char *DataPointer, int ByteCount)
1554 insb(IOAddress, (void *)DataPointer, ByteCount);
1557 static void
1558 DriverRepInWord(unsigned short IOAddress, unsigned short *DataPointer, int WordCount)
1560 insw(IOAddress, (void *)DataPointer, WordCount);
1562 static void
1563 DriverRepInDword( unsigned short IOAddress, unsigned long *DataPointer, int DWordCount)
1565 insl(IOAddress, (void *)DataPointer, DWordCount);
1567 #endif /* TRlldInlineIO */