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