[prev in list] [next in list] [prev in thread] [next in thread] 

List:       freebsd-hackers
Subject:    ifmedia and token-ring (Help!!) (fwd)
From:       Larry Lile <lile () stdio ! com>
Date:       1998-12-31 15:34:44
[Download RAW message or body]

I am trying to get ifmedia working for my Olicom token-ring driver
but I am having some strange problems.

First when I have probed/attached the card and ifconfig it it comes
up with this:

oltr1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 18000
	inet 10.0.0.1 netmask 0xffffff00 broadcast 10.0.0.255
	lladdr 00:00:83:2f:c3:ad
	media: autoselect (<unknown type>)
	supported media: UTP/16Mbit UTP/4Mbit autoselect

I really don't understand why I am getting "(<unknown type>)"
and I can only select "UTP/4Mbit" or "autoselect" but not
"UTP/16Mbit".

I have attached my patches to the if_media.h file and my driver.
I am not attached to to names or values for anything I changed
in if_media.  I also forgot to add the 4/16 Fiber values...

Their is also an issue of mode, there is "classic" mode which is 
compatible with the old ibm type of token-ring, "dedicated" mode
where you are expected to be hooked directly to a token-ring
switch and also a autosense mode.  I am not quite sure where
this should fit in but I put it in as a type option.

Any help?

Larry Lile
lile@stdio.com



["if_oltr.c" (TEXT/PLAIN)]

/* 
 * 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.13 1998/12/10 18:55:12 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

#ifndef TRLLD_SPEED_AUTO
#define TRLLD_SPEED_AUTO 0
#endif

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;
    char *buf;
} 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   4096
#define TX_BUFFER_LEN   4096

struct oltr_softc {
    struct arpcom arpcom;
    struct ifmedia ifmedia;
    TRlldAdapterConfig_t *config;
    TRlldAdapter_t *TRlldAdapter;
    int unit;
    u_char  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];

    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;

    /* 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;

    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;

    /* 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

    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);
        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)) {
        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, 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 transmit 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++;
    }
    
    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;
    struct iso88025_header *th;
    TRlldTransmit_t frame;
    int  len, i, rc;

    /*printf("oltr%d: oltr_start\n", sc->unit);*/

outloop:

    /* 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_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;
    }

    th = mtod(m, struct iso88025_header *);
    th->ac = 0x10;
    th->fc = 0x40;
    
    /* Keep a pointer to the head of the packet */
    m0 = m;

    i = (sc->tx_next & TX_LIST_MASK); /* Just to shorten thing up */

    for (len = 0; m != 0; m = m->m_next) {
        frame.TransmitFragment[0].VirtualAddress = sc->tx_buffer[i].buf;
        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;
    }
    frame.FragmentCount = 1;
    frame.TransmitFragment[0].count = len;

    rc = TRlldTransmitFrame(sc->TRlldAdapter, &frame, (void \
*)sc->tx_buffer[i].index);  if (rc != TRLLD_TRANSMIT_OK) {
        printf("oltr%d: TRlldTransmitFrame returned (%x)\n", sc->unit, rc);
        ifp->if_oerrors++;
        goto bad;
    }

    sc->tx_next++;
    sc->tx_avail--;

#if NBPFILTER > 0
    if (ifp->if_bpf)
        bpf_mtap(ifp, m0);
#endif

bad:
    m_freem(m0);
    goto outloop;
    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;
                    }
            }
            
            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;

    if (ifp->if_flags & IFF_OACTIVE)
        ifp->if_flags &= ~(IFF_OACTIVE);

    /*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 buffer. (%d)\n", sc->unit, frame);
        return;
    }

    sc->tx_avail++;

}

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 *m;
    int i, j = (int)FragmentHandle, rc, frame_len = ByteCount, mac_hdr_len;
    char *frag = sc->rx_buffer[j].buf;

    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(m, M_DONTWAIT, MT_DATA);
            if (m == NULL) {
                ifp->if_ierrors++;
                goto out;
            }
            if (frame_len + 2 > MHLEN) {
                MCLGET(m, M_DONTWAIT);
                if ((m->m_flags & M_EXT) == 0) {
                    printf("oltr%d: unable to get mbuf cluster during receive.\n", \
sc->unit);  m_freem(m);
                    ifp->if_ierrors++;
                    goto out;
                }
            }
            ifp->if_ipackets++;

            m->m_pkthdr.rcvif = &sc->arpcom.ac_if;
            m->m_pkthdr.len = m->m_len = frame_len;
            m->m_data += 2;
            th = mtod(m, struct iso88025_header *);

            i = 0;
            while (frame_len > RX_BUFFER_LEN) {
                bcopy(frag, mtod(m, char *) + i, RX_BUFFER_LEN);
                i += RX_BUFFER_LEN;
                frame_len -= RX_BUFFER_LEN;
                frag = sc->rx_buffer[++j].buf;
            }
            bcopy(frag, mtod(m, char *) + i, frame_len);
        
#if NBPFILTER > 0
            if (ifp->if_bpf)
                bpf_mtap(ifp, m);
#endif

            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;
            
            m->m_pkthdr.len = m->m_len = ByteCount - mac_hdr_len;
            m->m_data += mac_hdr_len;

            iso88025_input(&sc->arpcom.ac_if, th, m);

        } 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 re



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic