Annotation of qemu/roms/ipxe/src/drivers/net/ns8390.c, revision 1.1

1.1     ! root        1: /**************************************************************************
        !             2: ETHERBOOT -  BOOTP/TFTP Bootstrap Program
        !             3: 
        !             4: Author: Martin Renters
        !             5:   Date: May/94
        !             6: 
        !             7:  This code is based heavily on David Greenman's if_ed.c driver
        !             8: 
        !             9:  Copyright (C) 1993-1994, David Greenman, Martin Renters.
        !            10:   This software may be used, modified, copied, distributed, and sold, in
        !            11:   both source and binary form provided that the above copyright and these
        !            12:   terms are retained. Under no circumstances are the authors responsible for
        !            13:   the proper functioning of this software, nor do the authors assume any
        !            14:   responsibility for damages incurred with its use.
        !            15: 
        !            16: Multicast support added by Timothy Legge ([email protected]) 09/28/2003
        !            17: Relocation support added by Ken Yap ([email protected]) 28/12/02
        !            18: 3c503 support added by Bill Paul ([email protected]) on 11/15/94
        !            19: SMC8416 support added by Bill Paul ([email protected]) on 12/25/94
        !            20: 3c503 PIO support added by Jim Hague ([email protected]) on 2/17/98
        !            21: RX overrun by Klaus Espenlaub ([email protected]) on 3/10/99
        !            22:   parts taken from the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
        !            23: SMC8416 PIO support added by Andrew Bettison ([email protected]) on 4/3/02
        !            24:   based on the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
        !            25: 
        !            26: **************************************************************************/
        !            27: 
        !            28: FILE_LICENCE ( BSD2 );
        !            29: 
        !            30: /* #warning "ns8390.c: FIXME: split ISA and PCI, clean up" */
        !            31: 
        !            32: #if 1
        !            33: 
        !            34: #if !defined(INCLUDE_NS8390) && !defined(INCLUDE_WD) && \
        !            35:     !defined(INCLUDE_NE) && !defined(INCLUDE_3C503)
        !            36:   /* The driver named ns8390 is the PCI driver, often called
        !            37:      "PCI ne2000 clones". */
        !            38: # define INCLUDE_NS8390 1
        !            39: #endif
        !            40: 
        !            41: #include "etherboot.h"
        !            42: #include "nic.h"
        !            43: #include "ns8390.h"
        !            44: #include <ipxe/ethernet.h>
        !            45: #ifdef INCLUDE_NS8390
        !            46: #include <ipxe/pci.h>
        !            47: #else
        !            48: #include <ipxe/isa.h>
        !            49: #endif
        !            50: 
        !            51: static unsigned char   eth_vendor, eth_flags;
        !            52: #ifdef INCLUDE_WD
        !            53: static unsigned char   eth_laar;
        !            54: #endif
        !            55: static unsigned short  eth_nic_base, eth_asic_base;
        !            56: static unsigned char   eth_memsize, eth_rx_start, eth_tx_start;
        !            57: static Address         eth_bmem, eth_rmem;
        !            58: static unsigned char   eth_drain_receiver;
        !            59: 
        !            60: #ifdef INCLUDE_WD
        !            61: static struct wd_board {
        !            62:        const char *name;
        !            63:        char id;
        !            64:        char flags;
        !            65:        char memsize;
        !            66: } wd_boards[] = {
        !            67:        {"WD8003S",     TYPE_WD8003S,   0,                      MEM_8192},
        !            68:        {"WD8003E",     TYPE_WD8003E,   0,                      MEM_8192},
        !            69:        {"WD8013EBT",   TYPE_WD8013EBT, FLAG_16BIT,             MEM_16384},
        !            70:        {"WD8003W",     TYPE_WD8003W,   0,                      MEM_8192},
        !            71:        {"WD8003EB",    TYPE_WD8003EB,  0,                      MEM_8192},
        !            72:        {"WD8013W",     TYPE_WD8013W,   FLAG_16BIT,             MEM_16384},
        !            73:        {"WD8003EP/WD8013EP",
        !            74:                        TYPE_WD8013EP,  0,                      MEM_8192},
        !            75:        {"WD8013WC",    TYPE_WD8013WC,  FLAG_16BIT,             MEM_16384},
        !            76:        {"WD8013EPC",   TYPE_WD8013EPC, FLAG_16BIT,             MEM_16384},
        !            77:        {"SMC8216T",    TYPE_SMC8216T,  FLAG_16BIT | FLAG_790,  MEM_16384},
        !            78:        {"SMC8216C",    TYPE_SMC8216C,  FLAG_16BIT | FLAG_790,  MEM_16384},
        !            79:        {"SMC8416T",    TYPE_SMC8416T,  FLAG_16BIT | FLAG_790,  MEM_8192},
        !            80:        {"SMC8416C/BT", TYPE_SMC8416C,  FLAG_16BIT | FLAG_790,  MEM_8192},
        !            81:        {"SMC8013EBP",  TYPE_SMC8013EBP,FLAG_16BIT,             MEM_16384},
        !            82:        {NULL,          0,              0,                      0}
        !            83: };
        !            84: #endif
        !            85: 
        !            86: #ifdef INCLUDE_3C503
        !            87: static unsigned char   t503_output;    /* AUI or internal xcvr (Thinnet) */
        !            88: #endif
        !            89: 
        !            90: #if    defined(INCLUDE_WD)
        !            91: #define        ASIC_PIO        WD_IAR
        !            92: #define        eth_probe       wd_probe
        !            93: #if    defined(INCLUDE_3C503) || defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
        !            94: Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
        !            95: #endif
        !            96: #endif
        !            97: 
        !            98: #if    defined(INCLUDE_3C503)
        !            99: #define        eth_probe       t503_probe
        !           100: #if    defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || defined(INCLUDE_WD)
        !           101: Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
        !           102: #endif
        !           103: #endif
        !           104: 
        !           105: #if    defined(INCLUDE_NE)
        !           106: #define        eth_probe       ne_probe
        !           107: #if    defined(INCLUDE_NS8390) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
        !           108: Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
        !           109: #endif
        !           110: #endif
        !           111: 
        !           112: #if    defined(INCLUDE_NS8390)
        !           113: #define        eth_probe       nepci_probe
        !           114: #if    defined(INCLUDE_NE) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
        !           115: Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
        !           116: #endif
        !           117: #endif
        !           118: 
        !           119: #if    defined(INCLUDE_3C503)
        !           120: #define        ASIC_PIO        _3COM_RFMSB
        !           121: #else
        !           122: #if    defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
        !           123: #define        ASIC_PIO        NE_DATA
        !           124: #endif
        !           125: #endif
        !           126: 
        !           127: #if    defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
        !           128: /**************************************************************************
        !           129: ETH_PIO_READ - Read a frame via Programmed I/O
        !           130: **************************************************************************/
        !           131: static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt)
        !           132: {
        !           133: #ifdef INCLUDE_WD
        !           134:        outb(src & 0xff, eth_asic_base + WD_GP2);
        !           135:        outb(src >> 8, eth_asic_base + WD_GP2);
        !           136: #else
        !           137:        outb(D8390_COMMAND_RD2 |
        !           138:                D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
        !           139:        outb(cnt, eth_nic_base + D8390_P0_RBCR0);
        !           140:        outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
        !           141:        outb(src, eth_nic_base + D8390_P0_RSAR0);
        !           142:        outb(src>>8, eth_nic_base + D8390_P0_RSAR1);
        !           143:        outb(D8390_COMMAND_RD0 |
        !           144:                D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
        !           145: 
        !           146: #ifdef INCLUDE_3C503
        !           147:        outb(src & 0xff, eth_asic_base + _3COM_DALSB);
        !           148:        outb(src >> 8, eth_asic_base + _3COM_DAMSB);
        !           149:        outb(t503_output | _3COM_CR_START, eth_asic_base + _3COM_CR);
        !           150: #endif
        !           151: #endif
        !           152: 
        !           153:        if (eth_flags & FLAG_16BIT)
        !           154:                cnt = (cnt + 1) >> 1;
        !           155: 
        !           156:        while(cnt--) {
        !           157: #ifdef INCLUDE_3C503
        !           158:                while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
        !           159:                        ;
        !           160: #endif
        !           161: 
        !           162:                if (eth_flags & FLAG_16BIT) {
        !           163:                        *((unsigned short *)dst) = inw(eth_asic_base + ASIC_PIO);
        !           164:                        dst += 2;
        !           165:                }
        !           166:                else
        !           167:                        *(dst++) = inb(eth_asic_base + ASIC_PIO);
        !           168:        }
        !           169: 
        !           170: #ifdef INCLUDE_3C503
        !           171:        outb(t503_output, eth_asic_base + _3COM_CR);
        !           172: #endif
        !           173: }
        !           174: 
        !           175: /**************************************************************************
        !           176: ETH_PIO_WRITE - Write a frame via Programmed I/O
        !           177: **************************************************************************/
        !           178: static void eth_pio_write(const unsigned char *src, unsigned int dst, unsigned int cnt)
        !           179: {
        !           180: #ifdef COMPEX_RL2000_FIX
        !           181:        unsigned int x;
        !           182: #endif /* COMPEX_RL2000_FIX */
        !           183: #ifdef INCLUDE_WD
        !           184:        outb(dst & 0xff, eth_asic_base + WD_GP2);
        !           185:        outb(dst >> 8, eth_asic_base + WD_GP2);
        !           186: #else
        !           187:        outb(D8390_COMMAND_RD2 |
        !           188:                D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
        !           189:        outb(D8390_ISR_RDC, eth_nic_base + D8390_P0_ISR);
        !           190:        outb(cnt, eth_nic_base + D8390_P0_RBCR0);
        !           191:        outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
        !           192:        outb(dst, eth_nic_base + D8390_P0_RSAR0);
        !           193:        outb(dst>>8, eth_nic_base + D8390_P0_RSAR1);
        !           194:        outb(D8390_COMMAND_RD1 |
        !           195:                D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
        !           196: 
        !           197: #ifdef INCLUDE_3C503
        !           198:        outb(dst & 0xff, eth_asic_base + _3COM_DALSB);
        !           199:        outb(dst >> 8, eth_asic_base + _3COM_DAMSB);
        !           200: 
        !           201:        outb(t503_output | _3COM_CR_DDIR | _3COM_CR_START, eth_asic_base + _3COM_CR);
        !           202: #endif
        !           203: #endif
        !           204: 
        !           205:        if (eth_flags & FLAG_16BIT)
        !           206:                cnt = (cnt + 1) >> 1;
        !           207: 
        !           208:        while(cnt--)
        !           209:        {
        !           210: #ifdef INCLUDE_3C503
        !           211:                while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
        !           212:                        ;
        !           213: #endif
        !           214: 
        !           215:                if (eth_flags & FLAG_16BIT) {
        !           216:                        outw(*((unsigned short *)src), eth_asic_base + ASIC_PIO);
        !           217:                        src += 2;
        !           218:                }
        !           219:                else
        !           220:                        outb(*(src++), eth_asic_base + ASIC_PIO);
        !           221:        }
        !           222: 
        !           223: #ifdef INCLUDE_3C503
        !           224:        outb(t503_output, eth_asic_base + _3COM_CR);
        !           225: #else
        !           226: #ifdef COMPEX_RL2000_FIX
        !           227:        for (x = 0;
        !           228:                x < COMPEX_RL2000_TRIES &&
        !           229:                (inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
        !           230:                != D8390_ISR_RDC;
        !           231:                ++x);
        !           232:        if (x >= COMPEX_RL2000_TRIES)
        !           233:                printf("Warning: Compex RL2000 aborted wait!\n");
        !           234: #endif /* COMPEX_RL2000_FIX */
        !           235: #ifndef        INCLUDE_WD
        !           236:        while((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
        !           237:                != D8390_ISR_RDC);
        !           238: #endif
        !           239: #endif
        !           240: }
        !           241: #else
        !           242: /**************************************************************************
        !           243: ETH_PIO_READ - Dummy routine when NE2000 not compiled in
        !           244: **************************************************************************/
        !           245: static void eth_pio_read(unsigned int src __unused, unsigned char *dst  __unused, unsigned int cnt __unused) {}
        !           246: #endif
        !           247: 
        !           248: 
        !           249: /**************************************************************************
        !           250: enable_multycast - Enable Multicast
        !           251: **************************************************************************/
        !           252: static void enable_multicast(unsigned short eth_nic_base) 
        !           253: {
        !           254:        unsigned char mcfilter[8];
        !           255:        int i;
        !           256:        memset(mcfilter, 0xFF, 8);
        !           257:        outb(4, eth_nic_base+D8390_P0_RCR);     
        !           258:        outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS1, eth_nic_base + D8390_P0_COMMAND);
        !           259:        for(i=0;i<8;i++)
        !           260:        {
        !           261:                outb(mcfilter[i], eth_nic_base + 8 + i);
        !           262:                if(inb(eth_nic_base + 8 + i)!=mcfilter[i])
        !           263:                        printf("Error SMC 83C690 Multicast filter read/write mishap %d\n",i);
        !           264:        }
        !           265:        outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS0, eth_nic_base + D8390_P0_COMMAND);
        !           266:        outb(4 | 0x08, eth_nic_base+D8390_P0_RCR);
        !           267: }
        !           268: 
        !           269: /**************************************************************************
        !           270: NS8390_RESET - Reset adapter
        !           271: **************************************************************************/
        !           272: static void ns8390_reset(struct nic *nic)
        !           273: {
        !           274:        int i;
        !           275: 
        !           276:        eth_drain_receiver = 0;
        !           277: #ifdef INCLUDE_WD
        !           278:        if (eth_flags & FLAG_790)
        !           279:                outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
        !           280:        else
        !           281: #endif
        !           282:                outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
        !           283:                        D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
        !           284:        if (eth_flags & FLAG_16BIT)
        !           285:                outb(0x49, eth_nic_base+D8390_P0_DCR);
        !           286:        else
        !           287:                outb(0x48, eth_nic_base+D8390_P0_DCR);
        !           288:        outb(0, eth_nic_base+D8390_P0_RBCR0);
        !           289:        outb(0, eth_nic_base+D8390_P0_RBCR1);
        !           290:        outb(0x20, eth_nic_base+D8390_P0_RCR);  /* monitor mode */
        !           291:        outb(2, eth_nic_base+D8390_P0_TCR);
        !           292:        outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
        !           293:        outb(eth_rx_start, eth_nic_base+D8390_P0_PSTART);
        !           294: #ifdef INCLUDE_WD
        !           295:        if (eth_flags & FLAG_790) {
        !           296: #ifdef WD_790_PIO
        !           297:                outb(0x10, eth_asic_base + 0x06); /* disable interrupts, enable PIO */
        !           298:                outb(0x01, eth_nic_base + 0x09); /* enable ring read auto-wrap */
        !           299: #else
        !           300:                outb(0, eth_nic_base + 0x09);
        !           301: #endif
        !           302:        }
        !           303: #endif
        !           304:        outb(eth_memsize, eth_nic_base+D8390_P0_PSTOP);
        !           305:        outb(eth_memsize - 1, eth_nic_base+D8390_P0_BOUND);
        !           306:        outb(0xFF, eth_nic_base+D8390_P0_ISR);
        !           307:        outb(0, eth_nic_base+D8390_P0_IMR);
        !           308: #ifdef INCLUDE_WD
        !           309:        if (eth_flags & FLAG_790)
        !           310:                outb(D8390_COMMAND_PS1 |
        !           311:                        D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
        !           312:        else
        !           313: #endif
        !           314:                outb(D8390_COMMAND_PS1 |
        !           315:                        D8390_COMMAND_RD2 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
        !           316:        for (i=0; i<ETH_ALEN; i++)
        !           317:                outb(nic->node_addr[i], eth_nic_base+D8390_P1_PAR0+i);
        !           318:        for (i=0; i<ETH_ALEN; i++)
        !           319:                outb(0xFF, eth_nic_base+D8390_P1_MAR0+i);
        !           320:        outb(eth_rx_start, eth_nic_base+D8390_P1_CURR);
        !           321: #ifdef INCLUDE_WD
        !           322:        if (eth_flags & FLAG_790)
        !           323:                outb(D8390_COMMAND_PS0 |
        !           324:                        D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
        !           325:        else
        !           326: #endif
        !           327:                outb(D8390_COMMAND_PS0 |
        !           328:                        D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
        !           329:        outb(0xFF, eth_nic_base+D8390_P0_ISR);
        !           330:        outb(0, eth_nic_base+D8390_P0_TCR);     /* transmitter on */
        !           331:        outb(4, eth_nic_base+D8390_P0_RCR);     /* allow rx broadcast frames */
        !           332: 
        !           333:        enable_multicast(eth_nic_base);
        !           334: 
        !           335: #ifdef INCLUDE_3C503
        !           336:         /*
        !           337:          * No way to tell whether or not we're supposed to use
        !           338:          * the 3Com's transceiver unless the user tells us.
        !           339:          * 'flags' should have some compile time default value
        !           340:          * which can be changed from the command menu.
        !           341:          */
        !           342:        t503_output = (nic->flags) ? 0 : _3COM_CR_XSEL;
        !           343:        outb(t503_output, eth_asic_base + _3COM_CR);
        !           344: #endif
        !           345: }
        !           346: 
        !           347: static int ns8390_poll(struct nic *nic, int retrieve);
        !           348: 
        !           349: #ifndef        INCLUDE_3C503
        !           350: /**************************************************************************
        !           351: ETH_RX_OVERRUN - Bring adapter back to work after an RX overrun
        !           352: **************************************************************************/
        !           353: static void eth_rx_overrun(struct nic *nic)
        !           354: {
        !           355:        int start_time;
        !           356: 
        !           357: #ifdef INCLUDE_WD
        !           358:        if (eth_flags & FLAG_790)
        !           359:                outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
        !           360:        else
        !           361: #endif
        !           362:                outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
        !           363:                        D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
        !           364: 
        !           365:        /* wait for at least 1.6ms - we wait one timer tick */
        !           366:        start_time = currticks();
        !           367:        while (currticks() - start_time <= 1)
        !           368:                /* Nothing */;
        !           369: 
        !           370:        outb(0, eth_nic_base+D8390_P0_RBCR0);   /* reset byte counter */
        !           371:        outb(0, eth_nic_base+D8390_P0_RBCR1);
        !           372: 
        !           373:        /*
        !           374:         * Linux driver checks for interrupted TX here. This is not necessary,
        !           375:         * because the transmit routine waits until the frame is sent.
        !           376:         */
        !           377: 
        !           378:        /* enter loopback mode and restart NIC */
        !           379:        outb(2, eth_nic_base+D8390_P0_TCR);
        !           380: #ifdef INCLUDE_WD
        !           381:        if (eth_flags & FLAG_790)
        !           382:                outb(D8390_COMMAND_PS0 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
        !           383:        else
        !           384: #endif
        !           385:                outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
        !           386:                        D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
        !           387: 
        !           388:        /* clear the RX ring, acknowledge overrun interrupt */
        !           389:        eth_drain_receiver = 1;
        !           390:        while (ns8390_poll(nic, 1))
        !           391:                /* Nothing */;
        !           392:        eth_drain_receiver = 0;
        !           393:        outb(D8390_ISR_OVW, eth_nic_base+D8390_P0_ISR);
        !           394: 
        !           395:        /* leave loopback mode - no packets to be resent (see Linux driver) */
        !           396:        outb(0, eth_nic_base+D8390_P0_TCR);
        !           397: }
        !           398: #endif /* INCLUDE_3C503 */
        !           399: 
        !           400: /**************************************************************************
        !           401: NS8390_TRANSMIT - Transmit a frame
        !           402: **************************************************************************/
        !           403: static void ns8390_transmit(
        !           404:        struct nic *nic,
        !           405:        const char *d,                  /* Destination */
        !           406:        unsigned int t,                 /* Type */
        !           407:        unsigned int s,                 /* size */
        !           408:        const char *p)                  /* Packet */
        !           409: {
        !           410: #if defined(INCLUDE_3C503) || (defined(INCLUDE_WD) && ! defined(WD_790_PIO))
        !           411:        Address         eth_vmem = bus_to_virt(eth_bmem);
        !           412: #endif
        !           413: #ifdef INCLUDE_3C503
        !           414:         if (!(eth_flags & FLAG_PIO)) {
        !           415:                 memcpy((char *)eth_vmem, d, ETH_ALEN); /* dst */
        !           416:                 memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
        !           417:                 *((char *)eth_vmem+12) = t>>8;         /* type */
        !           418:                 *((char *)eth_vmem+13) = t;
        !           419:                 memcpy((char *)eth_vmem+ETH_HLEN, p, s);
        !           420:                 s += ETH_HLEN;
        !           421:                 while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
        !           422:         }
        !           423: #endif
        !           424: 
        !           425: #ifdef INCLUDE_WD
        !           426:        if (eth_flags & FLAG_16BIT) {
        !           427:                outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
        !           428:                inb(0x84);
        !           429:        }
        !           430: #ifndef        WD_790_PIO
        !           431:        /* Memory interface */
        !           432:        if (eth_flags & FLAG_790) {
        !           433:                outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
        !           434:                inb(0x84);
        !           435:        }
        !           436:        inb(0x84);
        !           437:        memcpy((char *)eth_vmem, d, ETH_ALEN);  /* dst */
        !           438:        memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
        !           439:        *((char *)eth_vmem+12) = t>>8;          /* type */
        !           440:        *((char *)eth_vmem+13) = t;
        !           441:        memcpy((char *)eth_vmem+ETH_HLEN, p, s);
        !           442:        s += ETH_HLEN;
        !           443:        while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
        !           444:        if (eth_flags & FLAG_790) {
        !           445:                outb(0, eth_asic_base + WD_MSR);
        !           446:                inb(0x84);
        !           447:        }
        !           448: #else
        !           449:        inb(0x84);
        !           450: #endif
        !           451: #endif
        !           452: 
        !           453: #if    defined(INCLUDE_3C503)
        !           454:        if (eth_flags & FLAG_PIO)
        !           455: #endif
        !           456: #if    defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
        !           457:        {
        !           458:                /* Programmed I/O */
        !           459:                unsigned short type;
        !           460:                type = (t >> 8) | (t << 8);
        !           461:                eth_pio_write( (unsigned char *) d, eth_tx_start<<8, ETH_ALEN);
        !           462:                eth_pio_write(nic->node_addr, (eth_tx_start<<8)+ETH_ALEN, ETH_ALEN);
        !           463:                /* bcc generates worse code without (const+const) below */
        !           464:                eth_pio_write((unsigned char *)&type, (eth_tx_start<<8)+(ETH_ALEN+ETH_ALEN), 2);
        !           465:                eth_pio_write( (unsigned char *) p, (eth_tx_start<<8)+ETH_HLEN, s);
        !           466:                s += ETH_HLEN;
        !           467:                if (s < ETH_ZLEN) s = ETH_ZLEN;
        !           468:        }
        !           469: #endif
        !           470: #if    defined(INCLUDE_3C503)
        !           471: #endif
        !           472: 
        !           473: #ifdef INCLUDE_WD
        !           474:        if (eth_flags & FLAG_16BIT) {
        !           475:                outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
        !           476:                inb(0x84);
        !           477:        }
        !           478:        if (eth_flags & FLAG_790)
        !           479:                outb(D8390_COMMAND_PS0 |
        !           480:                        D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
        !           481:        else
        !           482: #endif
        !           483:                outb(D8390_COMMAND_PS0 |
        !           484:                        D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
        !           485:        outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
        !           486:        outb(s, eth_nic_base+D8390_P0_TBCR0);
        !           487:        outb(s>>8, eth_nic_base+D8390_P0_TBCR1);
        !           488: #ifdef INCLUDE_WD
        !           489:        if (eth_flags & FLAG_790)
        !           490:                outb(D8390_COMMAND_PS0 |
        !           491:                        D8390_COMMAND_TXP | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
        !           492:        else
        !           493: #endif
        !           494:                outb(D8390_COMMAND_PS0 |
        !           495:                        D8390_COMMAND_TXP | D8390_COMMAND_RD2 |
        !           496:                        D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
        !           497: }
        !           498: 
        !           499: /**************************************************************************
        !           500: NS8390_POLL - Wait for a frame
        !           501: **************************************************************************/
        !           502: static int ns8390_poll(struct nic *nic, int retrieve)
        !           503: {
        !           504:        int ret = 0;
        !           505:        unsigned char rstat, curr, next;
        !           506:        unsigned short len, frag;
        !           507:        unsigned short pktoff;
        !           508:        unsigned char *p;
        !           509:        struct ringbuffer pkthdr;
        !           510: 
        !           511: #ifndef        INCLUDE_3C503
        !           512:        /* avoid infinite recursion: see eth_rx_overrun() */
        !           513:        if (!eth_drain_receiver && (inb(eth_nic_base+D8390_P0_ISR) & D8390_ISR_OVW)) {
        !           514:                eth_rx_overrun(nic);
        !           515:                return(0);
        !           516:        }
        !           517: #endif /* INCLUDE_3C503 */
        !           518:        rstat = inb(eth_nic_base+D8390_P0_RSR);
        !           519:        if (!(rstat & D8390_RSTAT_PRX)) return(0);
        !           520:        next = inb(eth_nic_base+D8390_P0_BOUND)+1;
        !           521:        if (next >= eth_memsize) next = eth_rx_start;
        !           522:        outb(D8390_COMMAND_PS1, eth_nic_base+D8390_P0_COMMAND);
        !           523:        curr = inb(eth_nic_base+D8390_P1_CURR);
        !           524:        outb(D8390_COMMAND_PS0, eth_nic_base+D8390_P0_COMMAND);
        !           525:        if (curr >= eth_memsize) curr=eth_rx_start;
        !           526:        if (curr == next) return(0);
        !           527: 
        !           528:        if ( ! retrieve ) return 1;
        !           529: 
        !           530: #ifdef INCLUDE_WD
        !           531:        if (eth_flags & FLAG_16BIT) {
        !           532:                outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
        !           533:                inb(0x84);
        !           534:        }
        !           535: #ifndef        WD_790_PIO
        !           536:        if (eth_flags & FLAG_790) {
        !           537:                outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
        !           538:                inb(0x84);
        !           539:        }
        !           540: #endif
        !           541:        inb(0x84);
        !           542: #endif
        !           543:        pktoff = next << 8;
        !           544:        if (eth_flags & FLAG_PIO)
        !           545:                eth_pio_read(pktoff, (unsigned char *)&pkthdr, 4);
        !           546:        else
        !           547:                memcpy(&pkthdr, bus_to_virt(eth_rmem + pktoff), 4);
        !           548:        pktoff += sizeof(pkthdr);
        !           549:        /* incoming length includes FCS so must sub 4 */
        !           550:        len = pkthdr.len - 4;
        !           551:        if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN
        !           552:                || len > ETH_FRAME_LEN) {
        !           553:                printf("Bogus packet, ignoring\n");
        !           554:                return (0);
        !           555:        }
        !           556:        else {
        !           557:                p = nic->packet;
        !           558:                nic->packetlen = len;           /* available to caller */
        !           559:                frag = (eth_memsize << 8) - pktoff;
        !           560:                if (len > frag) {               /* We have a wrap-around */
        !           561:                        /* read first part */
        !           562:                        if (eth_flags & FLAG_PIO)
        !           563:                                eth_pio_read(pktoff, p, frag);
        !           564:                        else
        !           565:                                memcpy(p, bus_to_virt(eth_rmem + pktoff), frag);
        !           566:                        pktoff = eth_rx_start << 8;
        !           567:                        p += frag;
        !           568:                        len -= frag;
        !           569:                }
        !           570:                /* read second part */
        !           571:                if (eth_flags & FLAG_PIO)
        !           572:                        eth_pio_read(pktoff, p, len);
        !           573:                else
        !           574:                        memcpy(p, bus_to_virt(eth_rmem + pktoff), len);
        !           575:                ret = 1;
        !           576:        }
        !           577: #ifdef INCLUDE_WD
        !           578: #ifndef        WD_790_PIO
        !           579:        if (eth_flags & FLAG_790) {
        !           580:                outb(0, eth_asic_base + WD_MSR);
        !           581:                inb(0x84);
        !           582:        }
        !           583: #endif
        !           584:        if (eth_flags & FLAG_16BIT) {
        !           585:                outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
        !           586:                inb(0x84);
        !           587:        }
        !           588:        inb(0x84);
        !           589: #endif
        !           590:        next = pkthdr.next;             /* frame number of next packet */
        !           591:        if (next == eth_rx_start)
        !           592:                next = eth_memsize;
        !           593:        outb(next-1, eth_nic_base+D8390_P0_BOUND);
        !           594:        return(ret);
        !           595: }
        !           596: 
        !           597: /**************************************************************************
        !           598: NS8390_DISABLE - Turn off adapter
        !           599: **************************************************************************/
        !           600: static void ns8390_disable ( struct nic *nic ) {
        !           601:        ns8390_reset(nic);
        !           602: }
        !           603: 
        !           604: /**************************************************************************
        !           605: NS8390_IRQ - Enable, Disable, or Force interrupts
        !           606: **************************************************************************/
        !           607: static void ns8390_irq(struct nic *nic __unused, irq_action_t action __unused)
        !           608: {
        !           609:   switch ( action ) {
        !           610:   case DISABLE :
        !           611:     break;
        !           612:   case ENABLE :
        !           613:     break;
        !           614:   case FORCE :
        !           615:     break;
        !           616:   }
        !           617: }
        !           618: 
        !           619: static struct nic_operations ns8390_operations;
        !           620: static struct nic_operations ns8390_operations = {
        !           621:        .connect        = dummy_connect,
        !           622:        .poll           = ns8390_poll,
        !           623:        .transmit       = ns8390_transmit,
        !           624:        .irq            = ns8390_irq,
        !           625: };
        !           626: 
        !           627: /**************************************************************************
        !           628: ETH_PROBE - Look for an adapter
        !           629: **************************************************************************/
        !           630: #ifdef INCLUDE_NS8390
        !           631: static int eth_probe (struct nic *nic, struct pci_device *pci)
        !           632: #else
        !           633: static int eth_probe (struct dev *dev, unsigned short *probe_addrs __unused)
        !           634: #endif
        !           635: {
        !           636:        int i;
        !           637: #ifdef INCLUDE_NS8390
        !           638:        unsigned short pci_probe_addrs[] = { pci->ioaddr, 0 };
        !           639:        unsigned short *probe_addrs = pci_probe_addrs;
        !           640: #endif
        !           641:        eth_vendor = VENDOR_NONE;
        !           642:        eth_drain_receiver = 0;
        !           643: 
        !           644:        nic->irqno  = 0;
        !           645: 
        !           646: #ifdef INCLUDE_WD
        !           647: {
        !           648:        /******************************************************************
        !           649:        Search for WD/SMC cards
        !           650:        ******************************************************************/
        !           651:        struct wd_board *brd;
        !           652:        unsigned short chksum;
        !           653:        unsigned char c;
        !           654:        for (eth_asic_base = WD_LOW_BASE; eth_asic_base <= WD_HIGH_BASE;
        !           655:                eth_asic_base += 0x20) {
        !           656:                chksum = 0;
        !           657:                for (i=8; i<16; i++)
        !           658:                        chksum += inb(eth_asic_base+i);
        !           659:                /* Extra checks to avoid soundcard */
        !           660:                if ((chksum & 0xFF) == 0xFF &&
        !           661:                        inb(eth_asic_base+8) != 0xFF &&
        !           662:                        inb(eth_asic_base+9) != 0xFF)
        !           663:                        break;
        !           664:        }
        !           665:        if (eth_asic_base > WD_HIGH_BASE)
        !           666:                return (0);
        !           667:        /* We've found a board */
        !           668:        eth_vendor = VENDOR_WD;
        !           669:        eth_nic_base = eth_asic_base + WD_NIC_ADDR;
        !           670: 
        !           671:        nic->ioaddr = eth_nic_base;
        !           672: 
        !           673:        c = inb(eth_asic_base+WD_BID);  /* Get board id */
        !           674:        for (brd = wd_boards; brd->name; brd++)
        !           675:                if (brd->id == c) break;
        !           676:        if (!brd->name) {
        !           677:                printf("Unknown WD/SMC NIC type %hhX\n", c);
        !           678:                return (0);     /* Unknown type */
        !           679:        }
        !           680:        eth_flags = brd->flags;
        !           681:        eth_memsize = brd->memsize;
        !           682:        eth_tx_start = 0;
        !           683:        eth_rx_start = D8390_TXBUF_SIZE;
        !           684:        if ((c == TYPE_WD8013EP) &&
        !           685:                (inb(eth_asic_base + WD_ICR) & WD_ICR_16BIT)) {
        !           686:                        eth_flags = FLAG_16BIT;
        !           687:                        eth_memsize = MEM_16384;
        !           688:        }
        !           689:        if ((c & WD_SOFTCONFIG) && (!(eth_flags & FLAG_790))) {
        !           690:                eth_bmem = (0x80000 |
        !           691:                 ((inb(eth_asic_base + WD_MSR) & 0x3F) << 13));
        !           692:        } else
        !           693:                eth_bmem = WD_DEFAULT_MEM;
        !           694:        if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) {
        !           695:                /* from Linux driver, 8416BT detects as 8216 sometimes */
        !           696:                unsigned int addr = inb(eth_asic_base + 0xb);
        !           697:                if (((addr >> 4) & 3) == 0) {
        !           698:                        brd += 2;
        !           699:                        eth_memsize = brd->memsize;
        !           700:                }
        !           701:        }
        !           702:        outb(0x80, eth_asic_base + WD_MSR);     /* Reset */
        !           703:        for (i=0; i<ETH_ALEN; i++) {
        !           704:                nic->node_addr[i] = inb(i+eth_asic_base+WD_LAR);
        !           705:        }
        !           706:        DBG ( "\n%s base %4.4x", brd->name, eth_asic_base );
        !           707:        if (eth_flags & FLAG_790) {
        !           708: #ifdef WD_790_PIO
        !           709:                DBG ( ", PIO mode, addr %s\n", eth_ntoa ( nic->node_addr ) );
        !           710:                eth_bmem = 0;
        !           711:                eth_flags |= FLAG_PIO;          /* force PIO mode */
        !           712:                outb(0, eth_asic_base+WD_MSR);
        !           713: #else
        !           714:                DBG ( ", Memory %x, MAC Addr %s\n", eth_bmem, eth_ntoa ( nic->node_addr) );
        !           715: 
        !           716:                outb(WD_MSR_MENB, eth_asic_base+WD_MSR);
        !           717:                outb((inb(eth_asic_base+0x04) |
        !           718:                        0x80), eth_asic_base+0x04);
        !           719:                outb(((unsigned)(eth_bmem >> 13) & 0x0F) |
        !           720:                        ((unsigned)(eth_bmem >> 11) & 0x40) |
        !           721:                        (inb(eth_asic_base+0x0B) & 0xB0), eth_asic_base+0x0B);
        !           722:                outb((inb(eth_asic_base+0x04) &
        !           723:                        ~0x80), eth_asic_base+0x04);
        !           724: #endif
        !           725:        } else {
        !           726: 
        !           727:                DBG (", Memory %x, MAC Addr %s\n", eth_bmem, eth_ntoa ( nic->node_addr) );
        !           728: 
        !           729:                outb(((unsigned)(eth_bmem >> 13) & 0x3F) | 0x40, eth_asic_base+WD_MSR);
        !           730:        }
        !           731:        if (eth_flags & FLAG_16BIT) {
        !           732:                if (eth_flags & FLAG_790) {
        !           733:                        eth_laar = inb(eth_asic_base + WD_LAAR);
        !           734:                        outb(WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
        !           735:                } else {
        !           736:                        outb((eth_laar =
        !           737:                                WD_LAAR_L16EN | 1), eth_asic_base + WD_LAAR);
        !           738: /*
        !           739:        The previous line used to be
        !           740:                                WD_LAAR_M16EN | WD_LAAR_L16EN | 1));
        !           741:        [email protected] reported that removing WD_LAAR_M16EN made
        !           742:        it work for WD8013s.  This seems to work for my 8013 boards. I
        !           743:        don't know what is really happening.  I wish I had data sheets
        !           744:        or more time to decode the Linux driver. - Ken
        !           745: */
        !           746:                }
        !           747:                inb(0x84);
        !           748:        }
        !           749: }
        !           750: #endif
        !           751: #ifdef INCLUDE_3C503
        !           752: #ifdef T503_AUI
        !           753:        nic->flags = 1;         /* aui */
        !           754: #else
        !           755:        nic->flags = 0;         /* no aui */
        !           756: #endif
        !           757:         /******************************************************************
        !           758:         Search for 3Com 3c503 if no WD/SMC cards
        !           759:         ******************************************************************/
        !           760:        if (eth_vendor == VENDOR_NONE) {
        !           761:                int     idx;
        !           762:                int     iobase_reg, membase_reg;
        !           763:                static unsigned short   base[] = {
        !           764:                        0x300, 0x310, 0x330, 0x350,
        !           765:                        0x250, 0x280, 0x2A0, 0x2E0, 0 };
        !           766: 
        !           767:                /* Loop through possible addresses checking each one */
        !           768: 
        !           769:                for (idx = 0; (eth_nic_base = base[idx]) != 0; ++idx) {
        !           770: 
        !           771:                        eth_asic_base = eth_nic_base + _3COM_ASIC_OFFSET;
        !           772: /*
        !           773:  * Note that we use the same settings for both 8 and 16 bit cards:
        !           774:  * both have an 8K bank of memory at page 1 while only the 16 bit
        !           775:  * cards have a bank at page 0.
        !           776:  */
        !           777:                        eth_memsize = MEM_16384;
        !           778:                        eth_tx_start = 32;
        !           779:                        eth_rx_start = 32 + D8390_TXBUF_SIZE;
        !           780: 
        !           781:                /* Check our base address. iobase and membase should */
        !           782:                /* both have a maximum of 1 bit set or be 0. */
        !           783: 
        !           784:                        iobase_reg = inb(eth_asic_base + _3COM_BCFR);
        !           785:                        membase_reg = inb(eth_asic_base + _3COM_PCFR);
        !           786: 
        !           787:                        if ((iobase_reg & (iobase_reg - 1)) ||
        !           788:                                (membase_reg & (membase_reg - 1)))
        !           789:                                continue;               /* nope */
        !           790: 
        !           791:                /* Now get the shared memory address */
        !           792: 
        !           793:                        eth_flags = 0;
        !           794: 
        !           795:                        switch (membase_reg) {
        !           796:                                case _3COM_PCFR_DC000:
        !           797:                                        eth_bmem = 0xdc000;
        !           798:                                        break;
        !           799:                                case _3COM_PCFR_D8000:
        !           800:                                        eth_bmem = 0xd8000;
        !           801:                                        break;
        !           802:                                case _3COM_PCFR_CC000:
        !           803:                                        eth_bmem = 0xcc000;
        !           804:                                        break;
        !           805:                                case _3COM_PCFR_C8000:
        !           806:                                        eth_bmem = 0xc8000;
        !           807:                                        break;
        !           808:                                case _3COM_PCFR_PIO:
        !           809:                                        eth_flags |= FLAG_PIO;
        !           810:                                        eth_bmem = 0;
        !           811:                                        break;
        !           812:                                default:
        !           813:                                        continue;       /* nope */
        !           814:                                }
        !           815:                        break;
        !           816:                }
        !           817: 
        !           818:                if (base[idx] == 0)             /* not found */
        !           819:                        return (0);
        !           820: #ifndef        T503_SHMEM
        !           821:                eth_flags |= FLAG_PIO;          /* force PIO mode */
        !           822:                eth_bmem = 0;
        !           823: #endif
        !           824:                eth_vendor = VENDOR_3COM;
        !           825: 
        !           826: 
        !           827:         /* Need this to make ns8390_poll() happy. */
        !           828: 
        !           829:                 eth_rmem = eth_bmem - 0x2000;
        !           830: 
        !           831:         /* Reset NIC and ASIC */
        !           832: 
        !           833:                 outb(_3COM_CR_RST | _3COM_CR_XSEL, eth_asic_base + _3COM_CR );
        !           834:                 outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR );
        !           835: 
        !           836:         /* Get our ethernet address */
        !           837: 
        !           838:                 outb(_3COM_CR_EALO | _3COM_CR_XSEL, eth_asic_base + _3COM_CR);
        !           839:                nic->ioaddr = eth_nic_base;
        !           840:                 DBG ( "\n3Com 3c503 base %4.4x, ", eth_nic_base );
        !           841:                 if (eth_flags & FLAG_PIO)
        !           842:                        DBG ( "PIO mode" );
        !           843:                 else
        !           844:                        DBG ( "memory %4.4x", eth_bmem );
        !           845:                 for (i=0; i<ETH_ALEN; i++) {
        !           846:                         nic->node_addr[i] = inb(eth_nic_base+i);
        !           847:                 }
        !           848:                 DBG ( ", %s, MAC Addr %s\n", nic->flags ? "AUI" : "internal xcvr",
        !           849:                      eth_ntoa ( nic->node_addr ) );
        !           850: 
        !           851:                 outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR);
        !           852:         /*
        !           853:          * Initialize GA configuration register. Set bank and enable shared
        !           854:          * mem. We always use bank 1. Disable interrupts.
        !           855:          */
        !           856:                 outb(_3COM_GACFR_RSEL |
        !           857:                        _3COM_GACFR_MBS0 | _3COM_GACFR_TCM | _3COM_GACFR_NIM, eth_asic_base + _3COM_GACFR);
        !           858: 
        !           859:                 outb(0xff, eth_asic_base + _3COM_VPTR2);
        !           860:                 outb(0xff, eth_asic_base + _3COM_VPTR1);
        !           861:                 outb(0x00, eth_asic_base + _3COM_VPTR0);
        !           862:         /*
        !           863:          * Clear memory and verify that it worked (we use only 8K)
        !           864:          */
        !           865: 
        !           866:                if (!(eth_flags & FLAG_PIO)) {
        !           867:                        memset(bus_to_virt(eth_bmem), 0, 0x2000);
        !           868:                        for(i = 0; i < 0x2000; ++i)
        !           869:                                if (*((char *)(bus_to_virt(eth_bmem+i)))) {
        !           870:                                        printf ("Failed to clear 3c503 shared mem.\n");
        !           871:                                        return (0);
        !           872:                                }
        !           873:                }
        !           874:         /*
        !           875:          * Initialize GA page/start/stop registers.
        !           876:          */
        !           877:                 outb(eth_tx_start, eth_asic_base + _3COM_PSTR);
        !           878:                 outb(eth_memsize, eth_asic_base + _3COM_PSPR);
        !           879:         }
        !           880: #endif
        !           881: #if    defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
        !           882: {
        !           883:        /******************************************************************
        !           884:        Search for NE1000/2000 if no WD/SMC or 3com cards
        !           885:        ******************************************************************/
        !           886:        unsigned char c;
        !           887:        if (eth_vendor == VENDOR_NONE) {
        !           888:                unsigned char romdata[16];
        !           889:                unsigned char testbuf[32];
        !           890:                int idx;
        !           891:                static unsigned char test[] = "NE*000 memory";
        !           892:                static unsigned short base[] = {
        !           893: #ifdef NE_SCAN
        !           894:                        NE_SCAN,
        !           895: #endif
        !           896:                        0 };
        !           897:                /* if no addresses supplied, fall back on defaults */
        !           898:                if (probe_addrs == 0 || probe_addrs[0] == 0)
        !           899:                        probe_addrs = base;
        !           900:                eth_bmem = 0;           /* No shared memory */
        !           901:                for (idx = 0; (eth_nic_base = probe_addrs[idx]) != 0; ++idx) {
        !           902:                        eth_flags = FLAG_PIO;
        !           903:                        eth_asic_base = eth_nic_base + NE_ASIC_OFFSET;
        !           904:                        eth_memsize = MEM_16384;
        !           905:                        eth_tx_start = 32;
        !           906:                        eth_rx_start = 32 + D8390_TXBUF_SIZE;
        !           907:                        c = inb(eth_asic_base + NE_RESET);
        !           908:                        outb(c, eth_asic_base + NE_RESET);
        !           909:                        (void) inb(0x84);
        !           910:                        outb(D8390_COMMAND_STP |
        !           911:                                D8390_COMMAND_RD2, eth_nic_base + D8390_P0_COMMAND);
        !           912:                        outb(D8390_RCR_MON, eth_nic_base + D8390_P0_RCR);
        !           913:                        outb(D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
        !           914:                        outb(MEM_8192, eth_nic_base + D8390_P0_PSTART);
        !           915:                        outb(MEM_16384, eth_nic_base + D8390_P0_PSTOP);
        !           916: #ifdef NS8390_FORCE_16BIT
        !           917:                        eth_flags |= FLAG_16BIT;        /* force 16-bit mode */
        !           918: #endif
        !           919: 
        !           920:                        eth_pio_write( (unsigned char *) test, 8192, sizeof(test));
        !           921:                        eth_pio_read(8192, testbuf, sizeof(test));
        !           922:                        if (!memcmp(test, testbuf, sizeof(test)))
        !           923:                                break;
        !           924:                        eth_flags |= FLAG_16BIT;
        !           925:                        eth_memsize = MEM_32768;
        !           926:                        eth_tx_start = 64;
        !           927:                        eth_rx_start = 64 + D8390_TXBUF_SIZE;
        !           928:                        outb(D8390_DCR_WTS |
        !           929:                                D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
        !           930:                        outb(MEM_16384, eth_nic_base + D8390_P0_PSTART);
        !           931:                        outb(MEM_32768, eth_nic_base + D8390_P0_PSTOP);
        !           932:                        eth_pio_write( (unsigned char *) test, 16384, sizeof(test));
        !           933:                        eth_pio_read(16384, testbuf, sizeof(test));
        !           934:                        if (!memcmp(testbuf, test, sizeof(test)))
        !           935:                                break;
        !           936:                }
        !           937:                if (eth_nic_base == 0)
        !           938:                        return (0);
        !           939:                if (eth_nic_base > ISA_MAX_ADDR)        /* PCI probably */
        !           940:                        eth_flags |= FLAG_16BIT;
        !           941:                eth_vendor = VENDOR_NOVELL;
        !           942:                eth_pio_read(0, romdata, sizeof(romdata));
        !           943:                for (i=0; i<ETH_ALEN; i++) {
        !           944:                        nic->node_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)];
        !           945:                }
        !           946:                nic->ioaddr = eth_nic_base;
        !           947:                DBG ( "\nNE%c000 base %4.4x, MAC Addr %s\n",
        !           948:                      (eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base,
        !           949:                      eth_ntoa ( nic->node_addr ) );
        !           950:        }
        !           951: }
        !           952: #endif
        !           953:        if (eth_vendor == VENDOR_NONE)
        !           954:                return(0);
        !           955:         if (eth_vendor != VENDOR_3COM)
        !           956:                eth_rmem = eth_bmem;
        !           957:        ns8390_reset(nic);
        !           958:        nic->nic_op     = &ns8390_operations;
        !           959: 
        !           960:         /* Based on PnP ISA map */
        !           961: #ifdef INCLUDE_WD
        !           962:         dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
        !           963:         dev->devid.device_id = htons(0x812a);
        !           964: #endif
        !           965: #ifdef INCLUDE_3C503
        !           966:         dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
        !           967:         dev->devid.device_id = htons(0x80f3);
        !           968: #endif
        !           969: #ifdef INCLUDE_NE
        !           970:         dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
        !           971:         dev->devid.device_id = htons(0x80d6);
        !           972: #endif
        !           973:        return 1;
        !           974: }
        !           975: 
        !           976: #ifdef INCLUDE_WD
        !           977: struct isa_driver wd_driver __isa_driver = {
        !           978:        .type    = NIC_DRIVER,
        !           979:        .name    = "WD",
        !           980:        .probe   = wd_probe,
        !           981:        .ioaddrs = 0, 
        !           982: };
        !           983: ISA_ROM("wd","WD8003/8013, SMC8216/8416, SMC 83c790 (EtherEZ)");
        !           984: #endif
        !           985: 
        !           986: #ifdef INCLUDE_3C503
        !           987: struct isa_driver t503_driver __isa_driver = {
        !           988:        .type    = NIC_DRIVER,
        !           989:        .name    = "3C503",
        !           990:        .probe   = t503_probe,
        !           991:        .ioaddrs = 0, 
        !           992: };
        !           993: ISA_ROM("3c503","3Com503, Etherlink II[/16]");
        !           994: #endif
        !           995: 
        !           996: #ifdef INCLUDE_NE
        !           997: struct isa_driver ne_driver __isa_driver = {
        !           998:        .type    = NIC_DRIVER,
        !           999:        .name    = "NE*000",
        !          1000:        .probe   = ne_probe,
        !          1001:        .ioaddrs = 0, 
        !          1002: };
        !          1003: ISA_ROM("ne","NE1000/2000 and clones");
        !          1004: #endif
        !          1005: 
        !          1006: #ifdef INCLUDE_NS8390
        !          1007: static struct pci_device_id nepci_nics[] = {
        !          1008: /* A few NE2000 PCI clones, list not exhaustive */
        !          1009: PCI_ROM(0x10ec, 0x8029, "rtl8029",      "Realtek 8029", 0),
        !          1010: PCI_ROM(0x1186, 0x0300, "dlink-528",    "D-Link DE-528", 0),
        !          1011: PCI_ROM(0x1050, 0x0940, "winbond940",   "Winbond NE2000-PCI", 0),              /* Winbond 86C940 / 89C940 */
        !          1012: PCI_ROM(0x1050, 0x5a5a, "winbond940f",  "Winbond W89c940F", 0),                /* Winbond 89C940F */
        !          1013: PCI_ROM(0x11f6, 0x1401, "compexrl2000", "Compex ReadyLink 2000", 0),
        !          1014: PCI_ROM(0x8e2e, 0x3000, "ktiet32p2",    "KTI ET32P2", 0),
        !          1015: PCI_ROM(0x4a14, 0x5000, "nv5000sc",     "NetVin NV5000SC", 0),
        !          1016: PCI_ROM(0x12c3, 0x0058, "holtek80232",  "Holtek HT80232", 0),
        !          1017: PCI_ROM(0x12c3, 0x5598, "holtek80229",  "Holtek HT80229", 0),
        !          1018: PCI_ROM(0x10bd, 0x0e34, "surecom-ne34", "Surecom NE34", 0),
        !          1019: PCI_ROM(0x1106, 0x0926, "via86c926",    "Via 86c926", 0),
        !          1020: };
        !          1021: 
        !          1022: PCI_DRIVER ( nepci_driver, nepci_nics, PCI_NO_CLASS );
        !          1023: 
        !          1024: DRIVER ( "NE2000/PCI", nic_driver, pci_driver, nepci_driver,
        !          1025:         nepci_probe, ns8390_disable );
        !          1026: 
        !          1027: #endif /* INCLUDE_NS8390 */
        !          1028: 
        !          1029: #endif
        !          1030: 
        !          1031: /*
        !          1032:  * Local variables:
        !          1033:  *  c-basic-offset: 8
        !          1034:  *  c-indent-level: 8
        !          1035:  *  tab-width: 8
        !          1036:  * End:
        !          1037:  */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.