[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