Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 9 Feb 1999 13:46:58 -0500 (EST)
From:      Larry Lile <lile@stdio.com>
To:        Julian Elischer <julian@whistle.com>
Cc:        hackers@FreeBSD.ORG
Subject:   Re: Why did this panic?
Message-ID:  <Pine.BSF.4.05.9902091338150.14147-300000@heathers.stdio.com>
In-Reply-To: <Pine.BSF.3.95.990209103135.5802D-100000@current1.whistle.com>

index | next in thread | previous in thread | raw e-mail

[-- Attachment #1 --]

It looks like Jan 20 21:15 (EST) judging from the CVS directory and 
sounds about right as I recall.

drwxr-xr-x 2 root wheel 512 Jan 20 21:15 CVS

I included the kernel config for you, the problem is that I am
working on token-ring drivers and my code could easily be wrong.
The funny thing is, I only see the problem with high mtu's
like 4K.  No problems at 1500.  Also, I have an fxp interface
in the machine (in reference to the last thread).

I have also included the source to the oltr driver in-case you
want to look at the code where I allocate the mubfs...  Things
appeared to start to go wrong in ReceiveFrameCompleted.
The tok (IBM) driver is compiled in but the interface was down.

Larry Lile
lile@stdio.com


On Tue, 9 Feb 1999, Julian Elischer wrote:

> ah yes that's what I want..
> mclfree is garbage....
> exactly liek we saw on our mystery crash
> 
> This indicates that an mbuf cluster was used after it was freed,
> or it was allocated to two differnt users.
> 
> 
> that's exactly what we saw.
> 
> What version EXACTLY (date etc) of FreeBSD?
> 
> 
> tell me..
> what protocols are compiled in? 
> and what netowrking drivers and 
> what machines are on your nets (specifically, do you have MACS
> and the netatalk code compiled in?
> 
> 
> On Tue, 9 Feb 1999, Larry Lile wrote:
> 
> > 
> > Is this what you were looking for?
> > 
> > (kgdb) print *m0
> > $4 = {m_hdr = {mh_next = 0x0, mh_nextpkt = 0x0, mh_data = 0xf0756a20 "(rc=", 
> >     mh_len = 40, mh_type = 1, mh_flags = 2}, M_dat = {MH = {MH_pkthdr = {
> >         rcvif = 0x0, len = 1492, header = 0x4000000}, MH_dat = {MH_ext = {
> >           ext_buf = 0x3d637228 <Address 0x3d637228 out of bounds>, 
> >           ext_free = 0, ext_size = 2048, ext_ref = 0}, 
> >         MH_databuf = "(rc=\000\000\000\000\000\b\000\000\000\000\000\000E\b\005Ô1º@\000@\006ï_\n\000\000\001\n\000\000\002\000\024\004\r\t\211ô¾\013ø¶\002P\020D\020Z²\000\000sap f4 ui/C len=\020@\020\000Z±Åì\000\000\203/íªª\003\000\000\000\b\000le"}}, 
> >     M_databuf = "\000\000\000\000Ô\005\000\000\000\000\000\004(rc=\000\000\000\000\000\b\000\000\000\000\000\000E\b\005Ô1º@\000@\006ï_\n\000\000\001\n\000\000\002\000\024\004\r\t\211ô¾\013ø¶\002P\020D\020Z²\000\000sap f4 ui/C len=\020@\020\000Z±Åì\000\000\203/íªª\003\000\000\000\b\000le"}}
> > 
> > (kgdb) print m0.M_dat.MH.MH_dat.MH_ext
> > $6 = {ext_buf = 0x3d637228 <Address 0x3d637228 out of bounds>, ext_free = 0, 
> >   ext_size = 2048, ext_ref = 0}
> > 
> > (kgdb) print ((union mcluster *)(m0.M_dat.MH.MH_dat.MH_ext.ext_buf))->mcl_next
> > Cannot access memory at address 0x3d637228.
> > 
> > or more to the point:
> > 
> > (kgdb) print mclfree
> > $8 = (union mcluster *) 0x3d637228
> 
> *blam*
> Somethings not freeing mbuf clusters correctly.
> 
> > (kgdb) print *mclfree
> > Cannot access memory at address 0x3d637228.
> > (kgdb) 
> > 
> > Or am I misenterpreting MCLGET/MCLALLOC?
> > 
> > I must have missed the messages about this, was it fixed?
> > 
> > Larry Lile
> > lile@stdio.com
> > 
> > On Tue, 9 Feb 1999, Julian Elischer wrote:
> > 
> > > I think We saw this last week..
> > > it crashed on MCLGET..
> > > what is the pointer to the next free mbuf cluster?
> > > (not the next mbuf) (check the MCLGET macro to see what I mean)
> > > 
> > > 
> > > On Tue, 9 Feb 1999, Larry Lile wrote:
> > > 
> > > > 
> > > > I am working on improving the mtu sizes (above 1500) for the Olicom 
> > > > token ring driver but I just ran across this panic that I really
> > > > don't understand.  Any ideas? 
> > > > 
> > > > Larry Lile
> > > > lile@stdio.com
> > > > 
> > > > 
> > > > Fatal trap 12: page fault while in kernel mode
> > > > fault virtual address	= 0xf07eddc2
> > > > fault code		= supervisor write, page not present
> > > > instruction pointer	= 0x8:0xf02096ff
> > > > stack pointer	        = 0x10:0xf6829cdc
> > > > frame pointer	        = 0x10:0xf6829d14
> > > > code segment		= base 0x0, limit 0xfffff, type 0x1b
> > > > 			= DPL 0, pres 1, def32 1, gran 1
> > > > processor eflags	= interrupt enabled, resume, IOPL = 0
> > > > current process		= 352 (ftpd)
> > > > interrupt mask		= net 
> > > > trap number		= 12
> > > > panic: page fault
> > > > 
> > > > syncing disks... 7 7 done
> > > > 
> > > > dumping to dev 20419, offset 761856
> > > > dump 128 127 126 125 124 123 122 121 120 119 118 117 116 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 100 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 
> > > > ---
> > > > #0  boot (howto=256) at ../../kern/kern_shutdown.c:285
> > > > 285			dumppcb.pcb_cr3 = rcr3();
> > > > (kgdb) bt
> > > > #0  boot (howto=256) at ../../kern/kern_shutdown.c:285
> > > > #1  0xf013f55d in panic (fmt=0xf023f25b "page fault")
> > > >     at ../../kern/kern_shutdown.c:446
> > > > #2  0xf02024da in trap_fatal (frame=0xf6829ca0, eva=4034846146)
> > > >     at ../../i386/i386/trap.c:942
> > > > #3  0xf0202193 in trap_pfault (frame=0xf6829ca0, usermode=0, eva=4034846146)
> > > >     at ../../i386/i386/trap.c:835
> > > > #4  0xf0201daa in trap (frame={tf_es = 16, tf_ds = 16, tf_edi = -260740608, 
> > > >       tf_esi = -260740576, tf_ebp = -159212268, tf_isp = -159212344, 
> > > >       tf_ebx = -1073314688, tf_edx = 630210, tf_ecx = -265747636, 
> > > >       tf_eax = -260751360, tf_trapno = 12, tf_err = 2, tf_eip = -266299649, 
> > > >       tf_cs = 8, tf_eflags = 66066, tf_esp = -250238026, tf_ss = -250238028})
> > > >     at ../../i386/i386/trap.c:437
> > > > #5  0xf02096ff in DriverReceiveFrameCompleted (DriverHandle=0x1, 
> > > >     ByteCount=1514, FragmentCount=1, FragmentHandle=0x9, ReceiveStatus=0)
> > > >     at ../../i386/isa/if_oltr.c:1236
> > > > #6  0xf0210acc in ReturnCompletedBuffers ()
> > > > #7  0x631000 in ?? ()
> > > > #8  0xecc5b15a in ?? ()
> > > > Cannot access memory at address 0x104018.
> > > > (kgdb) up 5
> > > > #5  0xf02096ff in DriverReceiveFrameCompleted (DriverHandle=0x1, 
> > > >     ByteCount=1514, FragmentCount=1, FragmentHandle=0x9, ReceiveStatus=0)
> > > >     at ../../i386/isa/if_oltr.c:1236
> > > > 1236	                MCLGET(m0, M_DONTWAIT);
> > > > (kgdb) print m0
> > > > $1 = (struct mbuf *) 0xf0756a00
> > > > (kgdb) list
> > > > 1231	            if (m0 == NULL) {
> > > > 1232	                ifp->if_ierrors++;
> > > > 1233	                goto out;
> > > > 1234	            }
> > > > 1235	            if (ByteCount + 2 > MHLEN) {
> > > > 1236	                MCLGET(m0, M_DONTWAIT);
> > > > 1237	                mbuf_size = MCLBYTES;
> > > > 1238	                if ((m0->m_flags & M_EXT) == 0) {
> > > > 1239	                    m_freem(m0);
> > > > 1240	                    ifp->if_ierrors++;
> > > > (kgdb) print mbstat
> > > > $3 = {m_mbufs = 128, m_clusters = 100, m_spare = 0, m_clfree = 27, 
> > > >   m_drops = 0, m_wait = 0, m_drain = 0, m_mtypes = {65453, 79, 4, 
> > > >     0 <repeats 253 times>}, m_mcfail = 0, m_mpfail = 0, m_msize = 128, 
> > > >   m_mclbytes = 2048, m_minclsize = 204, m_mlen = 108, m_mhlen = 96}
> > > > (kgdb) print *m0
> > > > $4 = {m_hdr = {mh_next = 0x0, mh_nextpkt = 0x0, mh_data = 0xf0756a20 "(rc=", 
> > > >     mh_len = 40, mh_type = 1, mh_flags = 2}, M_dat = {MH = {MH_pkthdr = {
> > > >         rcvif = 0x0, len = 1492, header = 0x4000000}, MH_dat = {MH_ext = {
> > > >           ext_buf = 0x3d637228 <Address 0x3d637228 out of bounds>, 
> > > >           ext_free = 0, ext_size = 2048, ext_ref = 0}, 
> > > >         MH_databuf = "(rc=\000\000\000\000\000\b\000\000\000\000\000\000E\b\005Ô1º@\000@\006ï_\n\000\000\001\n\000\000\002\000\024\004\r\t\211ô¾\013ø¶\002P\020D\020Z²\000\000sap f4 ui/C len=\020@\020\000Z±Åì\000\000\203/íªª\003\000\000\000\b\000le"}}, 
> > > >     M_databuf = "\000\000\000\000Ô\005\000\000\000\000\000\004(rc=\000\000\000\000\000\b\000\000\000\000\000\000E\b\005Ô1º@\000@\006ï_\n\000\000\001\n\000\000\002\000\024\004\r\t\211ô¾\013ø¶\002P\020D\020Z²\000\000sap f4 ui/C len=\020@\020\000Z±Åì\000\000\203/íªª\003\000\000\000\b\000le"}}
> > > > (kgdb)
> > > > 
> > > > 
> > > > To Unsubscribe: send mail to majordomo@FreeBSD.org
> > > > with "unsubscribe freebsd-hackers" in the body of the message
> > > > 
> > > 
> > > 
> > > To Unsubscribe: send mail to majordomo@FreeBSD.org
> > > with "unsubscribe freebsd-hackers" in the body of the message
> > > 
> > 
> > 
> 

[-- Attachment #2 --]
/* 
 * 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.15 1999/02/08 23:37:45 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   (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];

    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;

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

            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;

    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 *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;
            th = mtod(m0, struct iso88025_header *);

            m = m0; mbuf_offset = 0; frag_offset = 0;
            while (frame_len > 0) {
                length = (RX_BUFFER_LEN - frag_offset) > (mbuf_size - mbuf_offset) ? (mbuf_size - mbuf_offset) :
                                                                                     (RX_BUFFER_LEN - frag_offset);
                length = length > frame_len ? frame_len : length;
                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 */

[-- Attachment #3 --]
#
# GENERIC -- Generic machine with WD/AHx/NCR/BTx family disks
#
# For more information read the handbook part System Administration -> 
# Configuring the FreeBSD Kernel -> The Configuration File. 
# The handbook is available in /usr/share/doc/handbook or online as
# latest version from the FreeBSD World Wide Web server 
# <URL:http://www.FreeBSD.ORG/>;
#
# An exhaustive list of options and more detailed explanations of the 
# device lines is present in the ./LINT configuration file. If you are 
# in doubt as to the purpose or necessity of a line, check first in LINT.
#
#	$Id: GENERIC,v 1.118 1998/09/18 00:46:40 mjacob Exp $

machine		"i386"
#cpu		"I386_CPU"
cpu		"I486_CPU"
cpu		"I586_CPU"
#cpu		"I686_CPU"
ident		anarchy
maxusers	32

options		"MAXMEM=(128*1024)"
options         NMBCLUSTERS=4096

options		MATH_EMULATE		#Support for x87 emulation
options		INET			#InterNETworking
options		FFS			#Berkeley Fast Filesystem
options		NFS			#Network Filesystem
options		MSDOSFS			#MSDOS Filesystem
options		"CD9660"		#ISO 9660 Filesystem
options		"CD9660_ROOT"		#CD-ROM usable as root device
options		FFS_ROOT		#FFS usable as root device [keep this!]
options		NFS_ROOT		#NFS usable as root device
options		PROCFS			#Process filesystem
options		"COMPAT_43"		#Compatible with BSD 4.3 [KEEP THIS!]
options		SCSI_DELAY=8000 	#Be pessimistic about Joe SCSI device
options		UCONSOLE		#Allow users to grab the console
options		FAILSAFE		#Be conservative
options		USERCONFIG		#boot -c editor
options		VISUAL_USERCONFIG	#visual boot -c editor

options         SOFTUPDATES

options		DDB
options		DDB_UNATTENDED

config		kernel	root on da0

controller	isa0
#controller	eisa0
controller	pci0

controller      pnp0

#controller      snd0
#device sb0      at isa? port 0x220 irq 5 drq 1 vector sbintr
#device sbxvi0   at isa? drq 5
#device sbmidi0  at isa? port 0x330

controller	fdc0	at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr
disk		fd0	at fdc0 drive 0
#disk		fd1	at fdc0 drive 1
# Unless you know very well what you're doing, leave ft0 at drive 2, or
# remove the line entirely if you don't need it.  Trying to configure
# it on another unit might cause surprises, see PR kern/7176.
#tape		ft0	at fdc0 drive 2

#options		"CMD640"	# work around CMD640 chip deficiency
#controller	wdc0	at isa? port "IO_WD1" bio irq 14 vector wdintr
#disk		wd0	at wdc0 drive 0
#disk		wd1	at wdc0 drive 1

#controller	wdc1	at isa? port "IO_WD2" bio irq 15 vector wdintr
#disk		wd2	at wdc1 drive 0
#disk		wd3	at wdc1 drive 1

#options		ATAPI		#Enable ATAPI support for IDE bus
#options		ATAPI_STATIC	#Don't do it as an LKM
#device		wcd0		#IDE CD-ROM
#device		wfd0		#IDE Floppy (e.g. LS-120)

# A single entry for any of these controllers (ncr, ahb, ahc, amd) is
# sufficient for any number of installed devices.
controller	ncr0
#controller	amd0
#controller	ahb0
#controller	ahc0
#controller	isp0

# This controller offers a number of configuration options, too many to
# document here  - see the LINT file in this directory and look up the
# dpt0 entry there for much fuller documentation on this.  The options
# line following dpt0 here is also currently a *required* option for it.
# controller      dpt0
# options DPT_MEASURE_PERFORMANCE

#controller	adv0	at isa? port ? cam irq ?
#controller	bt0	at isa? port ? cam irq ?
#controller	aha0	at isa? port ? cam irq ?
#controller	uha0	at isa? port "IO_UHA0" bio irq ? drq 5 vector uhaintr
#controller	aic0	at isa? port 0x340 bio irq 11 vector aicintr
#controller	nca0	at isa? port 0x1f88 bio irq 10 vector ncaintr
#controller	nca1	at isa? port 0x350 bio irq 5 vector ncaintr
#controller	sea0	at isa? bio irq 5 iomem 0xc8000 iosiz 0x2000 vector seaintr

controller	scbus0

device		da0

device          od0     #See LINT for possible `od' options.
#options         OD_BOGUS_NOT_READY      

device		sa0

device		pass0

device		cd0	#Only need one of these, the code dynamically grows

#device		wt0	at isa? port 0x300 bio irq 5 drq 1 vector wtintr
#device		mcd0	at isa? port 0x300 bio irq 10 vector mcdintr

#controller	matcd0	at isa? port 0x230 bio

#device		scd0	at isa? port 0x230 bio

# atkbdc0 controlls both the keyboard and the PS/2 mouse
controller	atkbdc0	at isa? port IO_KBD tty
device		atkbd0	at isa? tty irq 1
device		psm0	at isa? tty irq 12

device		vga0	at isa? port ? conflicts

# splash screen/screen saver
pseudo-device	splash

# syscons is the default console driver, resembling an SCO console
device		sc0	at isa? tty
# Enable this and PCVT_FREEBSD for pcvt vt220 compatible console driver
#device		vt0	at isa? tty
options		XSERVER			# support for X server
#options		FAT_CURSOR		# start with block cursor
# If you have a ThinkPAD, uncomment this along with the rest of the PCVT lines
#options		PCVT_SCANSET=2		# IBM keyboards are non-std

device		npx0	at isa? port "IO_NPX" irq 13 vector npxintr

#
# Laptop support (see LINT for more options)
#
#device		apm0    at isa?	disable	flags 0x31 # Advanced Power Management

# PCCARD (PCMCIA) support
#controller	card0
#device		pcic0	at card?
#device		pcic1	at card?

device		sio0	at isa? port "IO_COM1" flags 0x10 tty irq 4 vector siointr
device		sio1	at isa? port "IO_COM2" tty irq 3 vector siointr
device		sio2	at isa? disable port "IO_COM3" tty irq 5 vector siointr
device		sio3	at isa? disable port "IO_COM4" tty irq 9 vector siointr

#device		lpt0	at isa? port? tty irq 7 vector lptintr
#device		lpt1	at isa? port? tty
#device		mse0	at isa? port 0x23c tty irq 5 vector mseintr

#device		psm0	at isa? port "IO_KBD" conflicts tty irq 12 vector psmintr

# Order is important here due to intrusive probes, do *not* alphabetize
# this list of network interfaces until the probes have been fixed.
# Right now it appears that the ie0 must be probed before ep0. See
# revision 1.20 of this file.
#device de0
device fxp0
#device tl0
#device tx0
#device vx0
#device xl0

device oltr0 at isa? 
device tok0 at isa? port 0xa20 net irq 7 iomem 0xd8000
#device ed0 at isa? port 0x280 net irq 10 iomem 0xd8000 vector edintr
#device ie0 at isa? port 0x300 net irq 10 iomem 0xd0000 vector ieintr
#device ep0 at isa? port 0x300 net irq 10 vector epintr
#device ex0 at isa? port? net irq? vector exintr
#device fe0 at isa? port 0x300 net irq ? vector feintr
#device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr
#device lnc0 at isa? port 0x280 net irq 10 drq 0 vector lncintr
#device ze0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zeintr
#device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zpintr
#device cs0 at isa? port 0x300 net irq ? vector csintr

pseudo-device	loop
pseudo-device	ether
pseudo-device	token
#pseudo-device	sl	1
#pseudo-device	ppp	1
#pseudo-device	tun	1
pseudo-device   bpfilter 4
pseudo-device	pty	64
pseudo-device   snp     4
pseudo-device	gzip		# Exec gzipped a.out's

# KTRACE enables the system-call tracing facility ktrace(2).
# This adds 4 KB bloat to your kernel, and slightly increases
# the costs of each syscall.
options		KTRACE		#kernel tracing

# This provides support for System V shared memory.
#
options		SYSVSHM
options         SYSVSEM
options         SYSVMSG
help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.05.9902091338150.14147-300000>