summaryrefslogtreecommitdiffstats
path: root/sys/contrib/dev/oltr/if_oltr.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/dev/oltr/if_oltr.c')
-rw-r--r--sys/contrib/dev/oltr/if_oltr.c1517
1 files changed, 1517 insertions, 0 deletions
diff --git a/sys/contrib/dev/oltr/if_oltr.c b/sys/contrib/dev/oltr/if_oltr.c
new file mode 100644
index 0000000..e394714
--- /dev/null
+++ b/sys/contrib/dev/oltr/if_oltr.c
@@ -0,0 +1,1517 @@
+/*
+ * Copyright (c) 1998, Larry Lile
+ * All rights reserved.
+ *
+ * For latest sources and information on this driver, please
+ * go to http://anarchy.stdio.com.
+ *
+ * Questions, comments or suggestions should be directed to
+ * Larry Lile <lile@stdio.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: if_oltr.c,v 1.17 1999/02/12 19:05:35 lile Exp lile $
+ */
+
+
+#include "pci.h"
+#include "oltr.h"
+#include "opt_inet.h"
+#include "bpfilter.h"
+
+#if (NOLTR + NPCI) > 0
+
+/*#define TRlldInlineIO*/
+
+#define ISA_ADAPTERS (OC_3115 | OC_3117 | OC_3118)
+#define PCI_ADAPTERS (OC_3133 | OC_3136 | OC_3137 | \
+ OC_3139 | OC_3140 | OC_3141 | \
+ OC_3250 | OC_3540 )
+
+#define PCI_VENDOR_OLICOM 0x108D
+
+char *AdapterName[] = {
+ /* 0 */ "Olicom XT Adapter [unsupported]",
+ /* 1 */ "Olicom OC-3115",
+ /* 2 */ "Olicom ISA 16/4 Adapter (OC-3117)",
+ /* 3 */ "Olicom ISA 16/4 Adapter (OC-3118)",
+ /* 4 */ "Olicom MCA 16/4 Adapter (OC-3129) [unsupported]",
+ /* 5 */ "Olicom MCA 16/4 Adapter (OC-3129) [unsupported]",
+ /* 6 */ "Olicom MCA 16/4 Adapter (OC-3129) [unsupported]",
+ /* 7 */ "Olicom EISA 16/4 Adapter (OC-3133)",
+ /* 8 */ "Olicom EISA 16/4 Adapter (OC-3133)",
+ /* 9 */ "Olicom EISA 16/4 Server Adapter (OC-3135)",
+ /* 10 */ "Olicom PCI 16/4 Adapter (OC-3136)",
+ /* 11 */ "Olicom PCI 16/4 Adapter (OC-3136)",
+ /* 12 */ "Olicom PCI/II 16/4 Adapter (OC-3137)",
+ /* 13 */ "Olicom PCI 16/4 Adapter (OC-3139)",
+ /* 14 */ "Olicom RapidFire 3140 16/4 PCI Adapter (OC-3140)",
+ /* 15 */ "Olicom RapidFire 3141 Fiber Adapter (OC-3141)",
+ /* 16 */ "Olicom PCMCIA 16/4 Adapter (OC-3220) [unsupported]",
+ /* 17 */ "Olicom PCMCIA 16/4 Adapter (OC-3121, OC-3230, OC-3232) [unsupported]",
+ /* 18 */ "Olicom PCMCIA 16/4 Adapter (OC-3250)",
+ /* 19 */ "Olicom RapidFire 3540 4/16/100 Adapter (OC-3540)"
+};
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/sockio.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+#include <sys/kernel.h>
+#include <sys/interrupt.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/iso88025.h>
+#include <net/if_media.h>
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+
+#if NPNP > 0
+#include <i386/isa/pnp.h>
+#endif
+
+#include <machine/clock.h>
+#include <machine/md_var.h>
+#include <i386/isa/isa_device.h>
+
+#if NPCI > 0
+#include <pci/pcivar.h>
+#include <pci/pcireg.h>
+#endif
+
+#include "dev/oltr/trlld.h"
+
+#ifndef TRLLD_SPEED_AUTO
+#define TRLLD_SPEED_AUTO 0
+#endif
+
+#define MIN(A,B) (((A) < (B)) ? (A) : (B))
+#define MIN3(A,B,C) (MIN(A, (MIN(B, C))))
+
+void *oltr_malloc(ssize_t, TRlldAdapterConfig_t *);
+
+/*
+ * Glue functions prototypes for PMW kit IO
+ */
+
+#ifndef TRlldInlineIO
+static void DriverOutByte __P((unsigned short, unsigned char));
+static void DriverOutWord __P((unsigned short, unsigned short));
+static void DriverOutDword __P((unsigned short, unsigned long));
+static void DriverRepOutByte __P((unsigned short, unsigned char *, int));
+static void DriverRepOutWord __P((unsigned short, unsigned short *, int));
+static void DriverRepOutDword __P((unsigned short, unsigned long *, int));
+static unsigned char DriverInByte __P((unsigned short));
+static unsigned short DriverInWord __P((unsigned short));
+static unsigned long DriverInDword __P((unsigned short));
+static void DriverRepInByte __P((unsigned short, unsigned char *, int));
+static void DriverRepInWord __P((unsigned short, unsigned short *, int));
+static void DriverRepInDword __P((unsigned short, unsigned long *, int));
+#endif /*TRlldInlineIO*/
+static void DriverSuspend __P((unsigned short));
+static void DriverStatus __P((void *, TRlldStatus_t *));
+static void DriverCloseCompleted __P((void *));
+static void DriverStatistics __P((void *, TRlldStatistics_t *));
+static void DriverTransmitFrameCompleted __P((void *, void *, int));
+static void DriverReceiveFrameCompleted __P((void *, int, int, void *, int));
+
+typedef struct tx_buf {
+ int index;
+ int count;
+ char *buf;
+ struct mbuf *m;
+} tx_buf_t;
+
+typedef struct rx_buf {
+ int index;
+ char *buf;
+} rx_buf_t;
+
+#ifndef EXTRA_OLTR
+#if NPCI > 0
+#define EXTRA_OLTR 8
+#else
+#define EXTRA_OLTR 0
+#endif /* NPCI */
+#endif /* EXTRA_OLTR */
+
+#ifndef OLTR_PROMISC_MODE
+#define OLTR_PROMISC_MODE (TRLLD_PROM_LLC)
+#endif
+
+#define ALL_OPTIONS (IFM_TOK_ETR | IFM_TOK_SRCRT | IFM_TOK_ALLR | IFM_TOK_DTR | IFM_TOK_CLASSIC | IFM_TOK_AUTO)
+
+/* List sizes MUST be a power of 2 */
+#define TX_LIST_SIZE 16
+#define RX_LIST_SIZE 16
+#define TX_LIST_MASK (TX_LIST_SIZE - 1)
+#define RX_LIST_MASK (RX_LIST_SIZE - 1)
+#define RX_BUFFER_LEN (8*1024)
+#define TX_BUFFER_LEN (8*1024)
+
+struct oltr_softc {
+ struct arpcom arpcom;
+ struct ifmedia ifmedia;
+ TRlldAdapterConfig_t *config;
+ TRlldAdapter_t *TRlldAdapter;
+ int unit;
+ u_short PromiscMode;
+ u_short AdapterMode;
+ int hw_state;
+#define HW_UNKNOWN 0 /* initial/absent state */
+#define HW_FOUND 1 /* found, not initialized */
+#define HW_BAD 2 /* fatal error */
+#define HW_FAILED 3 /* closed eg. by remove, allow manual reopen */
+#define HW_LOADING 4
+#define HW_CLOSING 5
+#define HW_CLOSING2 6
+#define HW_CLOSED 7
+#define HW_OPENING 8
+#define HW_OPEN 9
+#define HW_ERROR 10 /* temporary error */
+
+ u_long GroupAddress;
+ u_long FunctionalAddress;
+ int poll_adapter;
+
+ int tx_next;
+ int tx_avail;
+ tx_buf_t tx_buffer[TX_LIST_SIZE];
+ TRlldTransmit_t tx_frame;
+
+ int rx_next;
+ int rx_avail;
+ rx_buf_t rx_buffer[RX_LIST_SIZE];
+
+ struct callout_handle oltr_ch;
+ struct callout_handle poll_ch;
+
+};
+
+static struct oltr_softc oltr_softc[NOLTR + EXTRA_OLTR];
+
+/*
+ * Driver function prototypes
+ */
+
+static int oltr_probe __P((struct isa_device *));
+static int oltr_attach __P((struct isa_device *));
+static void oltr_init __P((struct oltr_softc *));
+static void oltr_intr __P((int));
+static void oltr_start __P((struct ifnet *));
+static void oltr_stop __P((struct oltr_softc *));
+static int oltr_ioctl __P((struct ifnet *, u_long, caddr_t));
+
+static int oltr_attach_common __P((struct oltr_softc *));
+
+void oltr_timeout __P((void *));
+void adapter_poll __P((void *));
+
+struct isa_driver oltrdriver = {
+ oltr_probe,
+ oltr_attach,
+ "oltr",
+ 0
+};
+
+int isa_cards = 0;
+
+#if NPCI > 0
+static u_long oltr_count = NOLTR;
+static const char *oltr_pci_probe __P((pcici_t, pcidi_t));
+static void oltr_pci_attach __P((pcici_t, int));
+static void oltr_pci_intr __P((void *));
+static void oltr_pci_shutdown __P((int, void *));
+
+static struct pci_device oltr_device = {
+ "oltr",
+ oltr_pci_probe,
+ oltr_pci_attach,
+ &oltr_count,
+ NULL
+};
+
+DATA_SET(pcidevice_set, oltr_device);
+int pci_cards = 0;
+#endif /* NPCI */
+
+static int oltr_ifmedia_upd __P((struct ifnet *));
+static void oltr_ifmedia_sts __P((struct ifnet *, struct ifmediareq *));
+
+static TRlldDriver_t oltrLldDriver = {
+ TRLLD_VERSION,
+#ifndef TRlldInlineIO
+ DriverOutByte,
+ DriverOutWord,
+ DriverOutDword,
+ DriverRepOutByte,
+ DriverRepOutWord,
+ DriverRepOutDword,
+ DriverInByte,
+ DriverInWord,
+ DriverInDword,
+ DriverRepInByte,
+ DriverRepInWord,
+ DriverRepInDword,
+#endif /*TRlldInlineIO*/
+ DriverSuspend,
+ DriverStatus,
+ DriverCloseCompleted,
+ DriverStatistics,
+ DriverTransmitFrameCompleted,
+ DriverReceiveFrameCompleted,
+};
+
+TRlldAdapterConfig_t oltr_config[NOLTR + EXTRA_OLTR];
+
+void *
+oltr_malloc(Size, Adapter)
+ ssize_t Size;
+ TRlldAdapterConfig_t *Adapter;
+{
+
+ /* If the adapter needs memory below 16M for DMA then use contigmalloc */
+ if (Adapter->mode & TRLLD_MODE_16M) /* Adapter using ISA DMA buffer below 16M */
+ return(contigmalloc(Size, M_DEVBUF, M_NOWAIT, 0ul, 0xfffffful, 1ul, 0x10000ul));
+ else
+ return(malloc(Size, M_DEVBUF, M_NOWAIT));
+}
+
+/*
+ * Driver Functions
+ */
+
+static int
+oltr_probe(is)
+ struct isa_device *is;
+{
+ static int find_completed = 0, assigned[NOLTR];
+ struct oltr_softc *sc = &oltr_softc[is->id_unit];
+ int i;
+
+ printf("oltr%d: oltr_probe\n", is->id_unit);
+
+ /* Make life easy, use the Olicom supplied find function on the first probe
+ * to probe all of the ISA adapters. Then give them to each unit as requested.
+ * Try to match the adapters to units based on the iobase, but if iobase? then
+ * just give out the next available adapter.
+ */
+ if (!find_completed) {
+ isa_cards = TRlldFind(&oltrLldDriver, &oltr_config[0], ISA_ADAPTERS, NOLTR);
+ /*for (i = 0; i < isa_cards; i++) {
+ printf("TRlldFind: card %d - %s MAC %6D\n", i + 1, AdapterName[oltr_config[i].type], oltr_config[i].macaddress, ":");
+ }*/
+ for (i = 0; i < NOLTR; i++)
+ assigned[i] = 0;
+ find_completed = 1;
+ }
+
+ sc->unit = is->id_unit;
+ sc->hw_state = HW_UNKNOWN;
+
+ if (find_completed && ((isa_cards == 0) || (is->id_unit > isa_cards)))
+ return(0);
+
+ if (((is->id_iobase < 0xa00) || (is->id_iobase > 0xbe0)) && (is->id_iobase != 0xffffffff)) {
+ printf("oltr%d: port address impossible (0x%X)\n", is->id_unit, is->id_iobase);
+ return(0);
+ }
+
+ /* Auto assign lowest available card not already in use */
+ if (is->id_iobase == 0xffffffff) {
+ printf("oltr%d: auto assigning card.\n", is->id_unit);
+ for (i = 0; assigned[i]; i++);
+ assigned[i] = 1;
+ sc->config = &oltr_config[i];
+ is->id_iobase = sc->config->iobase0; /* Claim our port space */
+ if (!is->id_irq)
+ is->id_irq = (1 << sc->config->interruptlevel); /* Claim our interrupt */
+ is->id_intr = (inthand2_t *)oltr_intr;
+ register_intr(ffs(is->id_irq) - 1, is->id_id, is->id_ri_flags, is->id_intr, &net_imask, is->id_unit);
+ if ((is->id_drq == 0xffffffff) && (sc->config->dmalevel != TRLLD_DMA_PIO))
+ is->id_drq = sc->config->dmalevel; /* Claim our dma channel */
+ printf("oltr%d: <%s> [%6D]\n", is->id_unit, AdapterName[sc->config->type], sc->config->macaddress, ":");
+ sc->hw_state = HW_FOUND;
+ return(1);
+ } else {
+ /* Assign based on iobase address provided in kernel config */
+ for (i = 0; i < NOLTR; i++) {
+ if (is->id_iobase == oltr_config[i].iobase0) {
+ if (assigned[i]) {
+ printf("oltr%d: adapter (0x%X) already assigned.\n", is->id_unit, is->id_iobase);
+ return(0);
+ }
+ assigned[i] = 1;
+ sc->config = &oltr_config[i];
+ if (is->id_irq == 0)
+ is->id_irq = (1 << sc->config->interruptlevel); /* Claim our interrupt */
+ is->id_intr = (inthand2_t *)oltr_intr;
+ register_intr(ffs(is->id_irq) - 1, is->id_id, is->id_ri_flags, is->id_intr, &net_imask, is->id_unit);
+ if ((is->id_drq == 0xffffffff) && (sc->config->dmalevel != TRLLD_DMA_PIO))
+ is->id_drq = sc->config->dmalevel; /* Claim our dma channel */
+ printf("oltr%d: <%s> [%6D]\n", is->id_unit, AdapterName[sc->config->type], sc->config->macaddress, ":");
+ sc->hw_state = HW_FOUND;
+ return(1);
+ }
+ }
+ }
+ return(0); /* Card was not found */
+}
+
+#if NPCI > 0
+static const char *
+oltr_pci_probe(config_id, device_id)
+ pcici_t config_id;
+ pcidi_t device_id;
+{
+ u_char PCIConfigurationSpace[64];
+ u_long command;
+ int i, j, rc;
+
+ printf("oltr: oltr_pci_probe\n");
+
+ j = NOLTR + pci_cards;
+
+ if (pci_cards == EXTRA_OLTR)
+ return(NULL);
+
+ if (((device_id & 0xffff) == PCI_VENDOR_OLICOM) &&
+ ((((device_id >> 16) & 0xffff) == 0x0001) ||
+ (((device_id >> 16) & 0xffff) == 0x0004) ||
+ (((device_id >> 16) & 0xffff) == 0x0005) ||
+ (((device_id >> 16) & 0xffff) == 0x0007) ||
+ (((device_id >> 16) & 0xffff) == 0x0008))) {
+
+ for (i = 0; i < 64; i++)
+ PCIConfigurationSpace[i] = pci_cfgread(config_id, i, /*bytes*/1);
+
+ rc = TRlldPCIConfig(&oltrLldDriver, &oltr_config[j], PCIConfigurationSpace);
+
+ if ((rc == TRLLD_PCICONFIG_OK) || (rc == TRLLD_PCICONFIG_SET_COMMAND)) {
+ if (rc == TRLLD_PCICONFIG_SET_COMMAND) {
+ printf("oltr: setting bus-master mode\n");
+ command = pci_conf_read(config_id, PCIR_COMMAND);
+ pci_conf_write(config_id, PCIR_COMMAND, (command | PCIM_CMD_BUSMASTEREN));
+ }
+ pci_cards++;
+ return (AdapterName[oltr_config[j].type]);
+ } else {
+ if (rc == TRLLD_PCICONFIG_FAIL)
+ printf("oltr: TRlldPCIConfig failed!\n");
+ if (rc == TRLLD_PCICONFIG_VERSION)
+ printf("oltr: wrong LLD version\n");
+ }
+ }
+ return(NULL);
+}
+#endif /* NPCI */
+
+static int
+oltr_attach(is)
+ struct isa_device *is;
+{
+ struct oltr_softc *sc = &oltr_softc[is->id_unit];
+ int rc;
+
+ sc->unit = is->id_unit;
+
+ if (!oltr_attach_common(sc))
+ return(0);
+
+ /* If the kernel config does not match the current card configuration then
+ * adjust the card settings to match the kernel.
+ */
+ if ((ffs(is->id_irq) - 1) != sc->config->interruptlevel) {
+ rc = TRlldSetInterrupt(sc->TRlldAdapter, is->id_irq);
+ if (rc != TRLLD_CONFIG_OK) {
+ printf("oltr%d: Unable to change adapter interrupt level (%x)\n", sc->unit, rc);
+ return(0);
+ }
+ }
+
+ /* Set dma level, fall back to pio if possible. (following SCO driver example) */
+ if (is->id_drq != sc->config->dmalevel) {
+ rc = TRlldSetDMA(sc->TRlldAdapter, is->id_drq, &sc->config->mode);
+ if (rc != TRLLD_CONFIG_OK) {
+ if ((sc->config->dmalevel != TRLLD_DMA_PIO) &&
+ (TRlldSetDMA(sc->TRlldAdapter, TRLLD_DMA_PIO, &sc->config->mode) != TRLLD_CONFIG_OK)) {
+ printf("oltr%d: unable to change dma level from %d to %d (%x)\n", sc->unit,
+ sc->config->dmalevel, is->id_drq, rc);
+ }
+ printf("oltr%d: Unable to change adapter dma level, using PIO mode (%x)\n", sc->unit, rc);
+ sc->config->dmalevel = TRLLD_DMA_PIO;
+ rc = TRlldSetDMA(sc->TRlldAdapter, is->id_drq, &sc->config->mode);
+ }
+ is->id_irq = sc->config->dmalevel;
+ }
+ return(1);
+}
+
+#if NPCI > 0
+static void
+oltr_pci_attach(config_id, unit)
+ pcici_t config_id;
+ int unit;
+{
+ struct oltr_softc *sc = &oltr_softc[unit];
+
+ sc->unit = unit;
+ sc->config = &oltr_config[unit];
+ sc->hw_state = HW_FOUND;
+
+ printf("oltr%d: mac address [%6D]\n", sc->unit, sc->config->macaddress, ":");
+
+ if (!oltr_attach_common(sc))
+ return;
+
+ /* Map our interrupt */
+ if (!pci_map_int(config_id, oltr_pci_intr, sc, &net_imask)) {
+ printf("oltr%d: couldn't map interrupt\n", unit);
+ return;
+ }
+}
+#endif /* NPCI */
+
+static int
+oltr_attach_common(sc)
+ struct oltr_softc *sc;
+{
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ u_int bufsize;
+ int rc, i, j;
+
+ /*printf("oltr%d: attach_common called\n", sc->unit);*/
+
+ /* Allocate adapter memory buffer */
+ bufsize = TRlldAdapterSize();
+ sc->TRlldAdapter = (TRlldAdapter_t *)oltr_malloc(bufsize, sc->config);
+ if (sc->TRlldAdapter == NULL) {
+ printf("oltr%d: Unable to allocate adapter memory block (%d bytes)\n", sc->unit, bufsize);
+ }
+ /*printf("oltr%d: Adapter memory block (%p %d bytes)\n", sc->unit, sc->TRlldAdapter, bufsize);*/
+
+ /* Setup transmit pool */
+ for (i = 0; i < TX_LIST_SIZE; i++) {
+ sc->tx_buffer[i].index = i;
+ sc->tx_buffer[i].buf = (char *)oltr_malloc(TX_BUFFER_LEN, sc->config);
+ /* If we have a failure then free everything and get out */
+ if (!sc->tx_buffer[i].buf) {
+ printf("oltr%d: Unable to allocate transmit buffers.\n", sc->unit);
+ for (j = 0; j < i; j++)
+ free(sc->tx_buffer[j].buf, M_DEVBUF);
+ return(0);
+ }
+ }
+ sc->tx_next = 0;
+ sc->tx_avail = TX_LIST_SIZE;
+ sc->tx_frame.FragmentCount = 0;
+
+ /* Setup receive pool */
+ for (i = 0; i < RX_LIST_SIZE; i++) {
+ sc->rx_buffer[i].index = i;
+ sc->rx_buffer[i].buf = (char *)oltr_malloc(RX_BUFFER_LEN, sc->config);
+ /* If we have a failure then free everything and get out */
+ if (!sc->rx_buffer[i].buf) {
+ printf("oltr%d: Unable to allocate receive buffers.\n", sc->unit);
+ for (j = 0; j < i; j++)
+ free(sc->rx_buffer[j].buf, M_DEVBUF);
+ return(0);
+ }
+ }
+ sc->rx_next = 0;
+ sc->rx_avail = RX_LIST_SIZE;
+ /*printf("oltr%d: Allocated receive buffers\n", sc->unit); */
+
+ /* Set up adapter polling mechanism */
+ sc->poll_adapter = 1;
+ callout_handle_init(&sc->poll_ch);
+ sc->poll_ch = timeout(adapter_poll, (void *)sc->unit, (1*hz)/1000);
+ callout_handle_init(&sc->oltr_ch);
+
+ /* Initialize adapter */
+ rc = TRlldAdapterInit(&oltrLldDriver, sc->TRlldAdapter, kvtop(sc->TRlldAdapter),
+ (void *)sc->unit, sc->config);
+ if (rc != TRLLD_INIT_OK) {
+ switch (rc) {
+ case TRLLD_INIT_NOT_FOUND:
+ printf("oltr%d: Adapter not found or malfunctioning.\n", sc->unit);
+ sc->hw_state = HW_BAD;
+ return(0);
+ case TRLLD_INIT_UNSUPPORTED:
+ printf("oltr%d: Adapter not supported by low level driver.\n", sc->unit);
+ sc->hw_state = HW_UNKNOWN;
+ return(0);
+ case TRLLD_INIT_PHYS16:
+ printf("oltr%d: Adapter memory block above 16M, must be below 16M.\n", sc->unit);
+ return(0);
+ case TRLLD_INIT_VERSION:
+ printf("oltr%d: Low level driver version mismatch.\n", sc->unit);
+ return(0);
+ default:
+ printf("oltr%d: Unknown initilization error occoured (%x).\n", sc->unit, rc);
+ return(0);
+ }
+ }
+
+ /* Download Adapter Microcode */
+ /*printf("oltr%d: Downloading adapter microcode...", sc->unit);*/
+ sc->hw_state = HW_LOADING;
+ switch(sc->config->mactype) {
+ case TRLLD_MAC_TMS: /* TMS microcode */
+ rc = TRlldDownload(sc->TRlldAdapter, TRlldMacCode);
+ break;
+ case TRLLD_MAC_HAWKEYE: /* Hawkeye microcode */
+ rc = TRlldDownload(sc->TRlldAdapter, TRlldHawkeyeMac);
+ break;
+ case TRLLD_MAC_BULLSEYE: /* Bullseye microcode */
+ rc = TRlldDownload(sc->TRlldAdapter, TRlldBullseyeMac);
+ break;
+ default:
+ printf("oltr%d: unknown mactype %d\n", sc->unit, sc->config->mactype);
+ return(0);
+ }
+ /*if (rc == TRLLD_DOWNLOAD_OK)
+ printf("done\n");*/
+ if ((rc == TRLLD_DOWNLOAD_ERROR) || (rc == TRLLD_STATE)) {
+ printf("oltr%d: Adapter microcode download failed! (rc = %x)\n", sc->unit, rc);
+ sc->hw_state = HW_BAD;
+ return(0);
+ }
+
+ TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_AUTO);
+
+ sc->PromiscMode = 0;
+ sc->AdapterMode = 0;
+
+ /* Do the ifnet initialization */
+ ifp->if_softc = sc;
+ ifp->if_unit = sc->unit;
+ ifp->if_name = "oltr";
+ ifp->if_output = iso88025_output;
+ ifp->if_init = (if_init_f_t *)oltr_init;
+ ifp->if_start = oltr_start;
+ ifp->if_ioctl = oltr_ioctl;
+ ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX;
+ bcopy(sc->config->macaddress, sc->arpcom.ac_enaddr, sizeof(sc->config->macaddress));
+
+ /* Set up common ifmedia options */
+ ifmedia_init(&sc->ifmedia, 0, oltr_ifmedia_upd, oltr_ifmedia_sts);
+
+ ifmedia_add(&sc->ifmedia, IFM_TOKEN | IFM_AUTO, 0 , NULL);
+ ifmedia_add(&sc->ifmedia, IFM_TOKEN | IFM_TOK_UTP4, 0 , NULL);
+ ifmedia_add(&sc->ifmedia, IFM_TOKEN | IFM_TOK_UTP16, 0 , NULL);
+
+ ifmedia_set(&sc->ifmedia, IFM_TOKEN | IFM_AUTO);
+
+ if_attach(ifp);
+ iso88025_ifattach(ifp);
+
+#if NBPFILTER > 0
+ bpfattach(ifp, DLT_IEEE802, sizeof(struct iso88025_header));
+#endif
+
+ printf("oltr%d: Adapter modes - ", sc->unit);
+ if (sc->config->mode & TRLLD_MODE_16M) printf("TRLLD_MODE_16M ");
+ if (sc->config->mode & TRLLD_MODE_PHYSICAL) printf("TRLLD_MODE_PHYSICAL ");
+ if (sc->config->mode & TRLLD_MODE_FIXED_CFG) printf("TRLLD_MODE_FIXED_CFG ");
+ if (sc->config->mode & TRLLD_MODE_SHORT_SLOT) printf("TRLLD_MODE_SHORT_SLOT ");
+ if (sc->config->mode & TRLLD_MODE_CANNOT_DISABLE) printf("TRLLD_MODE_CANNOT_DISABLE ");
+ if (sc->config->mode & TRLLD_MODE_SHARE_INTERRUPT) printf("TRLLD_MODE_SHARE_INTERRUPT ");
+ if (sc->config->mode & TRLLD_MODE_MEMORY) printf("TRLLD_MODE_MEMORY ");
+ printf("\n");
+
+ return(1);
+}
+
+#if NPCI > 0
+static void
+oltr_pci_shutdown(howto, sc)
+ int howto;
+ void *sc;
+{
+ printf("oltr: oltr_pci_shutdown called\n");
+}
+#endif /* NPCI */
+
+static int
+oltr_ifmedia_upd(ifp)
+ struct ifnet *ifp;
+{
+ struct oltr_softc *sc = ifp->if_softc;
+ struct ifmedia *ifm = &sc->ifmedia;
+
+ if (IFM_TYPE(ifm->ifm_media) != IFM_TOKEN)
+ return(EINVAL);
+
+ switch(IFM_SUBTYPE(ifm->ifm_media)) {
+ case IFM_AUTO:
+ TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_AUTO);
+ break;
+ case IFM_TOK_UTP4:
+ TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_4MBPS);
+ break;
+ case IFM_TOK_UTP16:
+ TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS);
+ break;
+ default:
+ return(EINVAL);
+ }
+
+ if (IFM_TYPE_OPTIONS(ifm->ifm_media) & IFM_TOK_ETR)
+ printf("oltr%d: ETR not implemented\n", sc->unit);
+ if (IFM_TYPE_OPTIONS(ifm->ifm_media) & IFM_TOK_SRCRT)
+ printf("oltr%d: source-routing not implemented\n", sc->unit);
+ if (IFM_TYPE_OPTIONS(ifm->ifm_media) & IFM_TOK_ALLR)
+ printf("oltr%d: all source routes not implemented\n", sc->unit);
+ if (IFM_TYPE_OPTIONS(ifm->ifm_media) & IFM_TOK_DTR) {
+ sc->AdapterMode |= TRLLD_MODE_FORCE_TXI;
+ sc->AdapterMode &= ~TRLLD_MODE_FORCE_TKP;
+ }
+ if (IFM_TYPE_OPTIONS(ifm->ifm_media) & IFM_TOK_CLASSIC) {
+ sc->AdapterMode |= TRLLD_MODE_FORCE_TKP;
+ sc->AdapterMode &= ~TRLLD_MODE_FORCE_TXI;
+ }
+ if (IFM_TYPE_OPTIONS(ifm->ifm_media) & IFM_TOK_AUTO)
+ sc->AdapterMode &= ~(TRLLD_MODE_FORCE_TXI | TRLLD_MODE_FORCE_TKP);
+
+ if (IFM_TYPE_OPTIONS(ifm->ifm_media) & ~ALL_OPTIONS)
+ return(EINVAL);
+
+ return(0);
+}
+
+static void
+oltr_ifmedia_sts(ifp, ifmr)
+ struct ifnet *ifp;
+ struct ifmediareq *ifmr;
+{
+ struct oltr_softc *sc = ifp->if_softc;
+ struct ifmedia *ifm = &sc->ifmedia;
+
+ ifmr->ifm_active = IFM_TYPE(ifm->ifm_media)|IFM_SUBTYPE(ifm->ifm_media)|IFM_TYPE_OPTIONS(ifm->ifm_media);
+
+ return;
+}
+
+void
+oltr_timeout(token)
+ void *token;
+{
+ struct oltr_softc *sc = &oltr_softc[(int)token];
+ int unit = (int)token, s;
+
+ s = splimp();
+
+ printf("oltr%d: adapter timed out (%x)\n", unit, sc->hw_state);
+
+ splx(s);
+}
+
+
+void
+adapter_poll(token)
+ void *token;
+{
+ int unit = (int)token, poll_timeout = 0, s;
+ struct oltr_softc *sc = &oltr_softc[unit];
+#if 0
+ static int rx_buffers = 0, tx_buffers = 0, rc;
+#endif
+
+ s = splimp();
+
+ /* Check to make sure we are not polling a dead card */
+ if ((sc->hw_state == HW_BAD) || (sc->hw_state == HW_UNKNOWN)) {
+ sc->poll_adapter = -1;
+ splx(s);
+ return;
+ }
+
+ /*printf("oltr%d: adapter poll.\n", unit);*/
+
+ /* If the adapter is to be polled again, then set up
+ * next timeout poll
+ */
+ if (sc->poll_adapter) {
+ poll_timeout = TRlldPoll(sc->TRlldAdapter);
+ sc->poll_ch = timeout(adapter_poll, (void *)unit, (poll_timeout * hz)/1000);
+ }
+#if 0
+ rc = TRlldReceiveFree(sc->TRlldAdapter);
+ if (rx_buffers != rc) {
+ printf("oltr%d: %d receive buffers available\n", sc->unit, rc);
+ rx_buffers = rc;
+ }
+ rc = TRlldTransmitFree(sc->TRlldAdapter);
+ if (tx_buffers != rc) {
+ printf("oltr%d: %d transmit buffers available\n", sc->unit, rc);
+ tx_buffers = rc;
+ }
+#endif
+
+ splx(s);
+}
+
+static void
+oltr_init(sc)
+ struct oltr_softc *sc;
+{
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ int i, rc;
+
+ /*printf("oltr%d: oltr_init\n", sc->unit);*/
+
+ /*
+ * Adapter should be freshly downloaded or previously closed before
+ * bringing it back on line.
+ */
+ if ((sc->hw_state != HW_CLOSED) && (sc->hw_state != HW_LOADING) && (sc->hw_state != HW_CLOSING2)) {
+ printf("oltr%d: adapter not ready to be opened (%d).\n", sc->unit, sc->hw_state);
+ return;
+ }
+
+ /* Allocate and set up the DMA channel */
+ if (sc->config->dmalevel != TRLLD_DMA_PIO) {
+ rc = isa_dma_acquire(sc->config->dmalevel);
+ isa_dmacascade(sc->config->dmalevel);
+ }
+
+ /* Open the adapter */
+ sc->hw_state = HW_OPENING;
+ rc = TRlldOpen(sc->TRlldAdapter, sc->arpcom.ac_enaddr, sc->GroupAddress,
+ sc->FunctionalAddress, ifp->if_mtu + 52, sc->AdapterMode);
+ if (rc != TRLLD_OPEN_OK) {
+ printf("oltr%d: Adapter failed to open (rc = %x)\n", sc->unit, rc);
+ sc->hw_state = HW_FAILED;
+ } else {
+ /*printf("oltr%d: adapter opening...\n", sc->unit);*/
+ /*ifp->if_flags |= (IFF_UP | IFF_RUNNING);*/
+ ifp->if_flags &= ~IFF_OACTIVE;
+ }
+ sc->oltr_ch = timeout(oltr_timeout, (void *)sc->unit, 30*hz);
+ tsleep((void *)sc->unit, 1, "oltrop", 30*hz);
+
+ /* Give the receive buffers to the adapter */
+ for (i = 0; i < RX_LIST_SIZE; i++) {
+ rc = TRlldReceiveFragment(sc->TRlldAdapter,
+ (void *)sc->rx_buffer[sc->rx_next & RX_LIST_MASK].buf,
+ kvtop(sc->rx_buffer[sc->rx_next & RX_LIST_MASK].buf),
+ RX_BUFFER_LEN,
+ (void *)sc->rx_buffer[sc->rx_next & RX_LIST_MASK].index);
+ if (rc != TRLLD_RECEIVE_OK) {
+ printf("oltr%d: Adapter refused fragment %d (rc = %d).\n", sc->unit, i, rc);
+ break;
+ } else {
+ sc->rx_avail--;
+ }
+ sc->rx_next++;
+ }
+ sc->tx_frame.FragmentCount = 0;
+
+ return;
+}
+
+static void
+oltr_intr(unit)
+ int unit;
+{
+ struct oltr_softc *sc = &oltr_softc[unit];
+ int rc;
+
+ /*printf("oltr%d: oltr_intr\n", unit);*/ /* Too noisy */
+ rc= TRlldInterruptService(sc->TRlldAdapter);
+ if (rc == TRLLD_NO_INTERRUPT)
+ printf("oltr%d: interrupt not serviced.\n", unit);
+}
+
+#if NPCI > 0
+static void
+oltr_pci_intr(psc)
+ void *psc;
+{
+ struct oltr_softc *sc = (struct oltr_softc *)psc;
+ int rc = 0;
+
+ /*printf("oltr%d: oltr_pci_intr\n", sc->unit);*/ /* Too noisy */
+ rc = TRlldInterruptService(sc->TRlldAdapter);
+ if (rc == TRLLD_NO_INTERRUPT)
+ printf("oltr%d: pci interrupt not serviced.\n", sc->unit);
+}
+#endif /* NPCI */
+
+static void
+oltr_start(ifp)
+ struct ifnet *ifp;
+{
+ struct oltr_softc *sc = &oltr_softc[ifp->if_unit];
+ struct mbuf *m0, *m;
+ int len, i, k, rc;
+
+ /*printf("oltr%d: oltr_start\n", sc->unit);*/
+
+outloop:
+
+ i = (sc->tx_next & TX_LIST_MASK); /* Just to shorten thing up */
+
+ /* Check to see if we have enough room to transmit */
+ if (sc->tx_avail <= 0) {
+ /* No free buffers, hold off the upper layers */
+ /*printf("oltr%d: transmit queue full.\n", sc->unit);*/
+ ifp->if_flags |= IFF_OACTIVE;
+ return;
+ }
+
+ if (sc->tx_frame.FragmentCount > 0) {
+ if (!(sc->config->mode & TRLLD_MODE_16M)) {
+ sc->tx_next++;
+ m0 = sc->tx_buffer[i].m;
+ goto restart;
+ }
+ }
+
+ IF_DEQUEUE(&ifp->if_snd, m);
+ if (m == 0) {
+ /*printf("oltr%d: oltr_start NULL packet dequeued.\n", sc->unit);*/
+ ifp->if_flags &= ~IFF_OACTIVE;
+ return;
+ }
+
+ /* Keep a pointer to the head of the packet */
+ m0 = m;
+
+ if (sc->config->mode & TRLLD_MODE_16M) { /* ISA Adapters - bounce buffers */
+
+ for (len = 0; m != 0; m = m->m_next) {
+ sc->tx_frame.TransmitFragment[0].VirtualAddress = sc->tx_buffer[i].buf;
+ sc->tx_frame.TransmitFragment[0].PhysicalAddress = kvtop(sc->tx_buffer[i].buf);
+ bcopy(mtod(m, caddr_t), sc->tx_buffer[i].buf + len, m->m_len);
+ len += m->m_len;
+ }
+ sc->tx_frame.FragmentCount = 1;
+ sc->tx_frame.TransmitFragment[0].count = len;
+
+ sc->tx_next++;
+ sc->tx_avail--;
+
+ } else { /* PCI Adapters w/DMA */
+
+ for (k = 0; m!= 0; m = m->m_next) {
+ sc->tx_frame.TransmitFragment[k].VirtualAddress = mtod(m, caddr_t);
+ sc->tx_frame.TransmitFragment[k].PhysicalAddress = kvtop(mtod(m, caddr_t));
+ sc->tx_frame.TransmitFragment[k].count = m->m_len;
+ k++;
+ sc->tx_avail--;
+ }
+ sc->tx_frame.FragmentCount = k;
+ sc->tx_buffer[i].count = k;
+ sc->tx_buffer[i].m = m0;
+
+ if (sc->tx_avail < 0) {
+ /*printf("oltr%d: transmit buffers exhausted.\n", sc->unit);*/
+ goto nobuffers;
+ }
+ sc->tx_next++;
+ }
+
+restart:
+ rc = TRlldTransmitFrame(sc->TRlldAdapter, &sc->tx_frame, (void *)sc->tx_buffer[i].index);
+ sc->tx_frame.FragmentCount = 0;
+
+ if (rc != TRLLD_TRANSMIT_OK) {
+ printf("oltr%d: TRlldTransmitFrame returned (%x)\n", sc->unit, rc);
+ ifp->if_oerrors++;
+ goto bad;
+ }
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtap(ifp, m0);
+#endif
+
+bad:
+
+ if (sc->config->mode & TRLLD_MODE_16M) {
+ m_freem(m0);
+ }
+
+ goto outloop;
+
+nobuffers:
+
+ ifp->if_flags |= IFF_OACTIVE;
+
+ return;
+}
+
+static void
+oltr_stop(sc)
+ struct oltr_softc *sc;
+{
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ printf("oltr%d: otlr_stop\n", sc->unit);
+ ifp->if_flags &= ~(IFF_UP | IFF_RUNNING | IFF_OACTIVE);
+ sc->hw_state = HW_CLOSING;
+ TRlldClose(sc->TRlldAdapter, 0);
+ sc->oltr_ch = timeout(oltr_timeout, (void *)sc->unit, 30*hz);
+ tsleep((void *)sc->unit, 1, "oltrcl", 30*hz);
+}
+
+static int
+oltr_ioctl(ifp, cmd, data)
+ struct ifnet *ifp;
+ u_long cmd;
+ caddr_t data;
+{
+ struct oltr_softc *sc = &oltr_softc[ifp->if_unit];
+ struct ifreq *ifr = (struct ifreq *)data;
+ int error = 0, s;
+
+ /*printf("oltr%d: oltr_ioctl\n", ifp->if_unit);*/
+
+ s = splimp();
+
+ switch (cmd) {
+
+ case SIOCSIFADDR:
+ case SIOCGIFADDR:
+ case SIOCSIFMTU:
+ error = iso88025_ioctl(ifp, cmd, data);
+ break;
+
+ case SIOCSIFFLAGS:
+ /*
+ * If the interface is marked up and stopped, then start it.
+ * If it is marked down and running, then stop it.
+ */
+ if (ifp->if_flags & IFF_UP) {
+ if ((ifp->if_flags & IFF_RUNNING) == 0)
+ oltr_init(sc);
+ } else {
+ if (ifp->if_flags & IFF_RUNNING) {
+ oltr_stop(sc);
+ ifp->if_flags &= ~IFF_RUNNING;
+ }
+ }
+
+ if ((ifp->if_flags & IFF_PROMISC) != sc->PromiscMode) {
+ if (ifp->if_flags & IFF_PROMISC)
+ TRlldSetPromiscuousMode(sc->TRlldAdapter, OLTR_PROMISC_MODE);
+ else
+ TRlldSetPromiscuousMode(sc->TRlldAdapter, 0);
+ sc->PromiscMode = (ifp->if_flags & IFF_PROMISC);
+ }
+
+ break;
+ case SIOCGIFMEDIA:
+ case SIOCSIFMEDIA:
+ error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, cmd);
+ break;
+ default:
+ error = EINVAL;
+ }
+ splx(s);
+ return(error);
+}
+
+/*
+ * PMW Callback functions ----------------------------------------------------
+ */
+
+static void
+DriverSuspend(MicroSeconds)
+ unsigned short MicroSeconds;
+{
+ DELAY(MicroSeconds);
+}
+
+
+static void
+DriverStatus(DriverHandle, Status)
+ void *DriverHandle;
+ TRlldStatus_t *Status;
+{
+ struct oltr_softc *sc = &oltr_softc[(int)DriverHandle];
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+
+ switch (Status->Type) {
+ case TRLLD_STS_ON_WIRE:
+ if (sc->hw_state == HW_OPENING) {
+ sc->hw_state = HW_OPEN;
+ ifp->if_flags |= (IFF_UP | IFF_RUNNING);
+ /*printf("oltr%d: Adapter inserted.\n", sc->unit);*/
+ untimeout(oltr_timeout, (void *)sc->unit, sc->oltr_ch);
+ wakeup_one((void *)sc->unit);
+ }
+ break;
+ case TRLLD_STS_SELFTEST_STATUS:
+ if (Status->Specification.SelftestStatus == TRLLD_ST_OK) {
+ printf("oltr%d: adapter status good. (close completed/self-test)\n", sc->unit);
+ if ((sc->hw_state == HW_LOADING) || (sc->hw_state == HW_CLOSING) || (sc->hw_state == HW_CLOSING2)) {
+ sc->hw_state = HW_CLOSED;
+ break;
+ }
+ } else {
+ printf("oltr%d: Self test failed: ", sc->unit);
+ switch (Status->Specification.SelftestStatus) {
+ case TRLLD_ST_ERROR + 0: printf("Initial Test Error\n"); break;
+ case TRLLD_ST_ERROR + 1: printf("Adapter Software Checksum Error\n"); break;
+ case TRLLD_ST_ERROR + 2: printf("Adapter RAM Error\n"); break;
+ case TRLLD_ST_ERROR + 4: printf("Instruction Test Error\n"); break;
+ case TRLLD_ST_ERROR + 5: printf("Protocol Handler/RI Hw Error\n"); break;
+ case TRLLD_ST_ERROR + 6: printf("System Interface Register Error\n"); break;
+ case TRLLD_ST_TIMEOUT: printf("Selftest did not complete\n"); break;
+ default: printf("Unknown error (%x)\n", Status->Specification.SelftestStatus);
+ }
+ }
+ break;
+ case TRLLD_STS_INIT_STATUS:
+ printf("oltr%d: Adapter initialization failed: ", sc->unit);
+ switch(Status->Specification.InitStatus) {
+ case TRLLD_INIT_ERROR + 0x01: printf("Invalid init block (LLD error)\n"); break;
+ case TRLLD_INIT_ERROR + 0x02: printf("Invalid options (LLD error)\n"); break;
+ case TRLLD_INIT_ERROR + 0x03: printf("Invalid rcv burst (LLD error)\n"); break;
+ case TRLLD_INIT_ERROR + 0x04: printf("Invalid xmt burst (LLD error)\n"); break;
+ case TRLLD_INIT_ERROR + 0x05: printf("Invalid DMA threshold (LLD error)\n"); break;
+ case TRLLD_INIT_ERROR + 0x06: printf("Invalid scb addr\n"); break;
+ case TRLLD_INIT_ERROR + 0x07: printf("Invalid ssb addr\n"); break;
+ case TRLLD_INIT_ERROR + 0x08: printf("DIO parity error (HW error)\n"); break;
+ case TRLLD_INIT_ERROR + 0x09: printf("DMA timeout (May be interrupt failing if PIO mode or PCI2)\n"); break;
+ case TRLLD_INIT_ERROR + 0x0A: printf("DMA parity error (HW error)\n"); break;
+ case TRLLD_INIT_ERROR + 0x0B: printf("DMA bus error (HW error)\n"); break;
+ case TRLLD_INIT_ERROR + 0x0C: printf("DMA data error\n"); break;
+ case TRLLD_INIT_ERROR + 0x0D: printf("Adapter Check\n"); break;
+ case TRLLD_INIT_TIMEOUT: printf("Adapter initialization did not complete\n"); break;
+ case TRLLD_INIT_DMA_ERROR: printf("Adapter cannot access system memory\n"); break;
+ case TRLLD_INIT_INTR_ERROR: printf("Adapter cannot interrupt\n"); break;
+ case TRLLD_OPEN_TIMEOUT: printf("Adapter did not complete open within 30 seconds\n"); break;
+ case TRLLD_OPEN_ERROR + 0x01: printf("Invalid open options (LLD error)\n"); break;
+ case TRLLD_OPEN_ERROR + 0x04: printf("TxBuffer count error (LLD error)\n"); break;
+ case TRLLD_OPEN_ERROR + 0x10: printf("Buffer size error (LLD error)\n"); break;
+ case TRLLD_OPEN_ERROR + 0x20: printf("List size error (LLD error)\n"); break;
+ default:
+ if (Status->Specification.InitStatus & 0x700) {
+ switch (Status->Specification.InitStatus & 0x70F) {
+ case TRLLD_OPEN_REPEAT + 0x01: printf("Lobe media test - "); break;
+ case TRLLD_OPEN_REPEAT + 0x02: printf("Physical insertion - "); break;
+ case TRLLD_OPEN_REPEAT + 0x03: printf("Address verification - "); break;
+ case TRLLD_OPEN_REPEAT + 0x04: printf("Participation in ring poll - "); break;
+ case TRLLD_OPEN_REPEAT + 0x05: printf("Request initialization - "); break;
+ case TRLLD_OPEN_REPEAT + 0x09: printf("Request registration (TXI) - "); break;
+ case TRLLD_OPEN_REPEAT + 0x0A: printf("Lobe media test (TXI) - "); break;
+ default: printf("Unknown phase (%x) - ", Status->Specification.InitStatus & 0x00F);
+ }
+ switch (Status->Specification.InitStatus & 0x7F0) {
+ case TRLLD_OPEN_REPEAT + 0x10: printf("Function failure (No cable?)\n"); break;
+ case TRLLD_OPEN_REPEAT + 0x20: printf("Signal loss\n"); break;
+ case TRLLD_OPEN_REPEAT + 0x50: printf("Timeout\n"); break;
+ case TRLLD_OPEN_REPEAT + 0x60: printf("Ring failure (TKP) / Protocol error (TXI)\n"); break;
+ case TRLLD_OPEN_REPEAT + 0x70: printf("Ring beaconing\n"); break;
+ case TRLLD_OPEN_REPEAT + 0x80: printf("Duplicate node address (TKP) / Insert denied (TXI)\n"); break;
+ case TRLLD_OPEN_REPEAT + 0x90: printf("Request initialization (TKP)\n"); break;
+ case TRLLD_OPEN_REPEAT + 0xa0: printf("Remove received\n"); break;
+ case TRLLD_OPEN_REPEAT + 0xb0: printf("C-port address changed (TXI)\n"); break;
+ default: printf("Unknown type (%x)\n", Status->Specification.InitStatus & 0x0F0);
+ }
+ } else {
+ printf("Unknown error (%x)\n", Status->Specification.InitStatus);
+ }
+ }
+ break;
+ case TRLLD_STS_RING_STATUS:
+ if (Status->Specification.RingStatus != 0) {
+ printf("oltr%d: Ring status change: ", sc->unit);
+ if (Status->Specification.RingStatus & TRLLD_RS_HARD_ERROR) printf("[Hard error] ");
+ if (Status->Specification.RingStatus & TRLLD_RS_SOFT_ERROR) printf("[Soft error] ");
+ if (Status->Specification.RingStatus & TRLLD_RS_TRANSMIT_BEACON) printf("[Transmit beacon] ");
+ if (Status->Specification.RingStatus & TRLLD_RS_LOBE_WIRE_FAULT) printf("[Wire fault] ");
+ if (Status->Specification.RingStatus & TRLLD_RS_AUTO_REMOVAL_ERROR) printf("[Auto removal] ");
+ if (Status->Specification.RingStatus & TRLLD_RS_REMOVE_RECEIVED) printf("[Remove received] ");
+ if (Status->Specification.RingStatus & TRLLD_RS_COUNTER_OVERFLOW) printf("[Counter overflow] ");
+ if (Status->Specification.RingStatus & TRLLD_RS_SINGLE_STATION) printf("[Single station] ");
+ if (Status->Specification.RingStatus & TRLLD_RS_RING_RECOVERY) printf("[Ring recovery] ");
+ printf("\n");
+ }
+ break;
+ case TRLLD_STS_ADAPTER_CHECK:
+ printf("oltr%d: Adapter check (%x %x %x %x)\n", sc->unit, Status->Specification.AdapterCheck[0],
+ Status->Specification.AdapterCheck[1], Status->Specification.AdapterCheck[2],
+ Status->Specification.AdapterCheck[3]);
+ break;
+ case TRLLD_STS_PROMISCUOUS_STOPPED:
+ printf("oltr%d: Promiscuous mode stopped: ", sc->unit);
+ switch(Status->Specification.PromRemovedCause) {
+ case TRLLD_PROM_REMOVE_RECEIVED: printf("Remove received\n"); break;
+ case TRLLD_PROM_POLL_FAILURE: printf("Poll failure\n"); break;
+ default: printf("Unknown (%x)\n", Status->Specification.PromRemovedCause);
+ }
+ break;
+ case TRLLD_STS_LLD_ERROR:
+ printf("oltr%d: LLD error (%x %x %x %x) ", sc->unit, Status->Specification.InternalError[0],
+ Status->Specification.InternalError[1], Status->Specification.InternalError[2],
+ Status->Specification.InternalError[3]);
+ break;
+ case TRLLD_STS_ADAPTER_TIMEOUT:
+ printf("oltr%d: Adapter operation timed out: ", sc->unit);
+ switch(Status->Specification.AdapterTimeout) {
+ case TRLLD_COMMAND_TIMEOUT: printf("Command\n");
+ case TRLLD_TRANSMIT_TIMEOUT: printf("Transmit\n");
+ case TRLLD_INTERRUPT_TIMEOUT: printf("Interrupt\n");
+ default: printf("Unknown (%x)\n", Status->Specification.AdapterTimeout);
+ }
+ break;
+ default:
+ printf("oltr%d: Unknown status type (%x)\n", sc->unit, Status->Type);
+
+ }
+ if (Status->Closed) {
+ if (sc->hw_state > HW_BAD) {
+ sc->hw_state = HW_FAILED;
+ printf("oltr%d: closing adapter due to failure.\n", sc->unit);
+ oltr_stop(sc);
+ }
+ }
+}
+
+static void
+DriverCloseCompleted(DriverHandle)
+ void *DriverHandle;
+{
+ struct oltr_softc *sc = &oltr_softc[(int)DriverHandle];
+
+ printf("oltr%d: DriverCloseCompleted\n", sc->unit);
+
+ untimeout(oltr_timeout, (void *)sc->unit, sc->oltr_ch);
+ wakeup_one((void *)sc->unit);
+
+ if ((sc->hw_state != HW_CLOSING) && (sc->hw_state != HW_CLOSING2) && (sc->hw_state != HW_CLOSED)) {
+ printf("oltr%d: adapter close complete called in wrong state (%d)\n", sc->unit, sc->hw_state);
+ return;
+ }
+ sc->hw_state = HW_CLOSING2;
+ if (sc->config->dmalevel != TRLLD_DMA_PIO)
+ isa_dma_release(sc->config->dmalevel);
+
+}
+
+static void
+DriverStatistics(DriverHandle, Statistics)
+ void *DriverHandle;
+ TRlldStatistics_t *Statistics;
+{
+ printf("oltr: DriverStatistics\n");
+}
+
+static void
+DriverTransmitFrameCompleted(DriverHandle, FrameHandle, TransmitStatus)
+ void *DriverHandle;
+ void *FrameHandle;
+ int TransmitStatus;
+{
+ int frame = (int)FrameHandle;
+ struct oltr_softc *sc = &oltr_softc[(int)DriverHandle];
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+
+ /*printf("oltr%d: transmit complete frame %d\n", sc->unit, frame);*/
+ if (TransmitStatus == TRLLD_TRANSMIT_OK) {
+ ifp->if_opackets++;
+ } else {
+ printf("oltr%d: DriverTransmitFrameCompleted (frame %d status %x)\n", sc->unit, frame, TransmitStatus);
+ ifp->if_oerrors++;
+ }
+
+ if ((frame < 0) || (frame > TX_LIST_SIZE)) {
+ printf("oltr%d: bogus transmit frame. (%d)\n", sc->unit, frame);
+ return;
+ }
+
+ if (sc->config->mode & TRLLD_MODE_16M) {
+ sc->tx_avail++;
+ } else {
+ m_freem(sc->tx_buffer[frame].m);
+ sc->tx_avail += sc->tx_buffer[frame].count;
+ }
+
+ if ((ifp->if_flags & IFF_OACTIVE) && (sc->tx_avail > 0)) {
+ ifp->if_flags &= ~(IFF_OACTIVE);
+ oltr_start(ifp);
+ }
+
+}
+
+static void
+DriverReceiveFrameCompleted(DriverHandle, ByteCount, FragmentCount, FragmentHandle, ReceiveStatus)
+ void *DriverHandle;
+ int ByteCount;
+ int FragmentCount;
+ void *FragmentHandle;
+ int ReceiveStatus;
+{
+ struct oltr_softc *sc = &oltr_softc[(int)DriverHandle];
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ struct iso88025_header *th;
+ struct mbuf *m0, *m1, *m;
+ int j = (int)FragmentHandle, rc, frame_len = ByteCount, mac_hdr_len;
+ int mbuf_offset, mbuf_size, frag_offset, length;
+ char *frag = sc->rx_buffer[j].buf;
+
+ /*printf("oltr%d: ReceiveFrameCompleted (Size %d Count %d Start %d)\n", sc->unit, ByteCount, FragmentCount, j);*/
+
+ if (sc->hw_state >= HW_OPEN) { /* Hardware operating normally */
+ if (frag != sc->rx_buffer[sc->rx_next & RX_LIST_MASK].buf) {
+ printf("oltr%d: ring buffer pointer blown\n", sc->unit);
+ oltr_stop(sc);
+ return;
+ }
+ if (ReceiveStatus == TRLLD_RCV_OK) { /* Receive good frame */
+ MGETHDR(m0, M_DONTWAIT, MT_DATA);
+ mbuf_size = MHLEN;
+ if (m0 == NULL) {
+ ifp->if_ierrors++;
+ goto out;
+ }
+ if (ByteCount + 2 > MHLEN) {
+ MCLGET(m0, M_DONTWAIT);
+ mbuf_size = MCLBYTES;
+ if ((m0->m_flags & M_EXT) == 0) {
+ m_freem(m0);
+ ifp->if_ierrors++;
+ goto out;
+ }
+ }
+
+ m0->m_pkthdr.rcvif = &sc->arpcom.ac_if;
+ m0->m_pkthdr.len = ByteCount;
+ m0->m_len = 0;
+ m0->m_data += 2;
+ mbuf_size -=2;
+ th = mtod(m0, struct iso88025_header *);
+ m0->m_pkthdr.header = (void *)th;
+
+ m = m0; mbuf_offset = 0; frag_offset = 0;
+ while (frame_len > 0) {
+ length = MIN3(frame_len, (RX_BUFFER_LEN - frag_offset), (mbuf_size - mbuf_offset));
+ bcopy(frag + frag_offset, mtod(m, char *) + mbuf_offset, length);
+ m->m_len += length;
+ mbuf_offset += length;
+ frag_offset += length;
+ frame_len -= length;
+ if (frag_offset == RX_BUFFER_LEN) {
+ frag = sc->rx_buffer[++j].buf;
+ frag_offset = 0;
+ }
+ if ((mbuf_offset == mbuf_size) && (frame_len > 0)) {
+ MGET(m1, M_DONTWAIT, MT_DATA);
+ mbuf_size = MHLEN;
+ if (m1 == NULL) {
+ ifp->if_ierrors++;
+ m_freem(m0);
+ goto out;
+ }
+ if (frame_len > MHLEN) {
+ MCLGET(m1, M_DONTWAIT);
+ mbuf_size = MCLBYTES;
+ if ((m1->m_flags & M_EXT) == 0) {
+ m_freem(m0);
+ m_freem(m1);
+ ifp->if_ierrors++;
+ goto out;
+ }
+ }
+ m->m_next = m1;
+ m = m1;
+ mbuf_offset = 0;
+ m->m_len = 0;
+ }
+ }
+ ifp->if_ipackets++;
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtap(ifp, m0);
+#endif
+
+ if (ifp->if_flags & IFF_PROMISC)
+ if (bcmp(th->iso88025_dhost, etherbroadcastaddr, sizeof(th->iso88025_dhost)) != 0) {
+ if (((th->iso88025_dhost[0] & 0x7f) != sc->arpcom.ac_enaddr[0]) ||
+ (bcmp(th->iso88025_dhost + 1, sc->arpcom.ac_enaddr + 1, ISO88025_ADDR_LEN - 1))) {
+ m_freem(m0);
+ goto out;
+ }
+ }
+
+ mac_hdr_len = ISO88025_HDR_LEN;
+ if (th->iso88025_shost[0] & 0x80) /* Check for source routing info */
+ mac_hdr_len += (ntohs(th->rcf) & 0x1f00) >> 8;
+
+ m0->m_pkthdr.len -= mac_hdr_len;
+ m0->m_len -= mac_hdr_len;
+ m0->m_data += mac_hdr_len;
+
+ iso88025_input(&sc->arpcom.ac_if, th, m0);
+
+ } else {
+ if (ReceiveStatus != TRLLD_RCV_NO_DATA) {
+ printf("oltr%d: receive error. (ReceiveStatus=%d)\n", sc->unit, ReceiveStatus);
+ ifp->if_ierrors++;
+ }
+ }
+out:
+ while (FragmentCount > 0) {
+ rc = TRlldReceiveFragment(sc->TRlldAdapter,
+ (void *)sc->rx_buffer[sc->rx_next & RX_LIST_MASK].buf,
+ kvtop(sc->rx_buffer[sc->rx_next & RX_LIST_MASK].buf),
+ RX_BUFFER_LEN,
+ (void *)sc->rx_buffer[sc->rx_next & RX_LIST_MASK].index);
+ if (rc == TRLLD_RECEIVE_OK) {
+ sc->rx_next++;
+ FragmentCount--;
+ } else {
+ printf("oltr%d: Adapter refused fragment (%d).\n", sc->unit, sc->rx_next - 1);
+ sc->rx_avail += FragmentCount;
+ break;
+ }
+ }
+ } else { /* Hardware being closed */
+ if (frag != sc->rx_buffer[sc->rx_next++ & RX_LIST_MASK].buf) {
+ printf("oltr%d: ring buffer pointer blown\n", sc->unit);
+ }
+ sc->rx_avail += FragmentCount;
+ }
+
+}
+
+
+/*
+ * ---------------------------- PMW Glue -------------------------------
+ */
+
+#ifndef TRlldInlineIO
+
+static void
+DriverOutByte(IOAddress, value)
+ unsigned short IOAddress;
+ unsigned char value;
+{
+ outb(IOAddress, value);
+}
+
+static void
+DriverOutWord(IOAddress, value)
+ unsigned short IOAddress;
+ unsigned short value;
+{
+ outw(IOAddress, value);
+}
+
+static void
+DriverOutDword(IOAddress, value)
+ unsigned short IOAddress;
+ unsigned long value;
+{
+ outl(IOAddress, value);
+}
+
+static void
+DriverRepOutByte(IOAddress, DataPointer, ByteCount)
+ unsigned short IOAddress;
+ unsigned char *DataPointer;
+ int ByteCount;
+{
+ outsb(IOAddress, (void *)DataPointer, ByteCount);
+}
+
+static void
+DriverRepOutWord(IOAddress, DataPointer, WordCount)
+ unsigned short IOAddress;
+ unsigned short *DataPointer;
+ int WordCount;
+{
+ outsw(IOAddress, (void *)DataPointer, WordCount);
+}
+
+static void
+DriverRepOutDword(IOAddress, DataPointer, DWordCount)
+ unsigned short IOAddress;
+ unsigned long *DataPointer;
+ int DWordCount;
+{
+ outsl(IOAddress, (void *)DataPointer, DWordCount);
+}
+
+static unsigned char
+DriverInByte(IOAddress)
+ unsigned short IOAddress;
+{
+ return(inb(IOAddress));
+}
+
+static unsigned short
+DriverInWord(IOAddress)
+ unsigned short IOAddress;
+{
+ return(inw(IOAddress));
+}
+
+static unsigned long
+DriverInDword(IOAddress)
+ unsigned short IOAddress;
+{
+ return(inl(IOAddress));
+}
+
+static void
+DriverRepInByte(IOAddress, DataPointer, ByteCount)
+ unsigned short IOAddress;
+ unsigned char *DataPointer;
+ int ByteCount;
+{
+ insb(IOAddress, (void *)DataPointer, ByteCount);
+}
+
+static void
+DriverRepInWord(IOAddress, DataPointer, WordCount)
+ unsigned short IOAddress;
+ unsigned short *DataPointer;
+ int WordCount;
+{
+ insw(IOAddress, (void *)DataPointer, WordCount);
+}
+static void
+DriverRepInDword(IOAddress, DataPointer, DWordCount)
+ unsigned short IOAddress;
+ unsigned long *DataPointer;
+ int DWordCount;
+{
+ insl(IOAddress, (void *)DataPointer, DWordCount);
+}
+#endif /* TRlldInlineIO */
+
+#endif /* NOLTR */
OpenPOWER on IntegriCloud