Annotation of qemu/roms/ipxe/src/drivers/net/ne2k_isa.c, revision 1.1.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:  Card Detect support adapted from the eCos driver (Christian Plessl <[email protected]>)
                     19:  Extracted from ns8390.c and adapted by Pantelis Koukousoulas <[email protected]>
                     20:  **************************************************************************/
                     21: 
                     22: FILE_LICENCE ( BSD2 );
                     23: 
                     24: #include "ns8390.h"
                     25: #include "etherboot.h"
                     26: #include "nic.h"
                     27: #include <ipxe/ethernet.h>
                     28: #include <ipxe/isa.h>
                     29: #include <errno.h>
                     30: 
                     31: #define ASIC_PIO NE_DATA
                     32: 
                     33: static unsigned char eth_vendor, eth_flags;
                     34: static unsigned short eth_nic_base, eth_asic_base;
                     35: static unsigned char eth_memsize, eth_rx_start, eth_tx_start;
                     36: static Address eth_bmem, eth_rmem;
                     37: static unsigned char eth_drain_receiver;
                     38: 
                     39: static struct nic_operations ne_operations;
                     40: static void ne_reset(struct nic *nic, struct isa_device *isa);
                     41: 
                     42: static isa_probe_addr_t ne_probe_addrs[] = { 0x300, 0x280, 0x320, 0x340, 0x380, 0x220, };
                     43: 
                     44: /**************************************************************************
                     45:  ETH_PIO_READ - Read a frame via Programmed I/O
                     46:  **************************************************************************/
                     47: static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt) {
                     48:        outb(D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
                     49:        outb(cnt, eth_nic_base + D8390_P0_RBCR0);
                     50:        outb(cnt >> 8, eth_nic_base + D8390_P0_RBCR1);
                     51:        outb(src, eth_nic_base + D8390_P0_RSAR0);
                     52:        outb(src >> 8, eth_nic_base + D8390_P0_RSAR1);
                     53:        outb(D8390_COMMAND_RD0 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
                     54:        if (eth_flags & FLAG_16BIT)
                     55:                cnt = (cnt + 1) >> 1;
                     56: 
                     57:        while (cnt--) {
                     58:                if (eth_flags & FLAG_16BIT) {
                     59:                        *((unsigned short *) dst) = inw(eth_asic_base + ASIC_PIO);
                     60:                        dst += 2;
                     61:                } else
                     62:                        *(dst++) = inb(eth_asic_base + ASIC_PIO);
                     63:        }
                     64: }
                     65: 
                     66: /**************************************************************************
                     67:  ETH_PIO_WRITE - Write a frame via Programmed I/O
                     68:  **************************************************************************/
                     69: static void eth_pio_write(const unsigned char *src, unsigned int dst,
                     70:                unsigned int cnt) {
                     71:        outb(D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
                     72:        outb(D8390_ISR_RDC, eth_nic_base + D8390_P0_ISR);
                     73:        outb(cnt, eth_nic_base + D8390_P0_RBCR0);
                     74:        outb(cnt >> 8, eth_nic_base + D8390_P0_RBCR1);
                     75:        outb(dst, eth_nic_base + D8390_P0_RSAR0);
                     76:        outb(dst >> 8, eth_nic_base + D8390_P0_RSAR1);
                     77:        outb(D8390_COMMAND_RD1 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
                     78:        if (eth_flags & FLAG_16BIT)
                     79:                cnt = (cnt + 1) >> 1;
                     80: 
                     81:        while (cnt--) {
                     82: 
                     83:                if (eth_flags & FLAG_16BIT) {
                     84:                        outw(*((unsigned short *) src), eth_asic_base + ASIC_PIO);
                     85:                        src += 2;
                     86:                } else
                     87:                        outb(*(src++), eth_asic_base + ASIC_PIO);
                     88:        }
                     89: }
                     90: 
                     91: /**************************************************************************
                     92:  enable_multicast - Enable Multicast
                     93:  **************************************************************************/
                     94: static void enable_multicast(unsigned short eth_nic_base) {
                     95:        unsigned char mcfilter[8];
                     96:        int i;
                     97: 
                     98:        memset(mcfilter, 0xFF, 8);
                     99:        outb(4, eth_nic_base + D8390_P0_RCR);
                    100:        outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS1, eth_nic_base + D8390_P0_COMMAND);
                    101:        for (i = 0; i < 8; i++) {
                    102:                outb(mcfilter[i], eth_nic_base + 8 + i);
                    103:                if (inb(eth_nic_base + 8 + i) != mcfilter[i])
                    104:                        DBG("Error SMC 83C690 Multicast filter read/write mishap %d\n",
                    105:                                        i);
                    106:        }
                    107:        outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS0, eth_nic_base + D8390_P0_COMMAND);
                    108:        outb(4 | 0x08, eth_nic_base + D8390_P0_RCR);
                    109: }
                    110: 
                    111: /**************************************************************************
                    112:  NE_PROBE1 - Look for an adapter on the ISA bus
                    113:  **************************************************************************/
                    114: static int ne_probe1(isa_probe_addr_t ioaddr) {
                    115:        //From the eCos driver
                    116:        unsigned int regd;
                    117:        unsigned int state;
                    118: 
                    119:        state = inb(ioaddr);
                    120:        outb(ioaddr, D8390_COMMAND_RD2 | D8390_COMMAND_PS1 | D8390_COMMAND_STP);
                    121:        regd = inb(ioaddr + D8390_P0_TCR);
                    122: 
                    123:        if (inb(ioaddr + D8390_P0_TCR)) {
                    124:                outb(ioaddr, state);
                    125:                outb(ioaddr + 0x0d, regd);
                    126:                return 0;
                    127:        }
                    128: 
                    129:        return 1;
                    130: }
                    131: 
                    132: /**************************************************************************
                    133:  NE_PROBE - Initialize an adapter ???
                    134:  **************************************************************************/
                    135: static int ne_probe(struct nic *nic, struct isa_device *isa) {
                    136:        int i;
                    137:        unsigned char c;
                    138:        unsigned char romdata[16];
                    139:        unsigned char testbuf[32];
                    140: 
                    141:        eth_vendor = VENDOR_NONE;
                    142:        eth_drain_receiver = 0;
                    143: 
                    144:        nic->irqno = 0;
                    145:        nic->ioaddr = isa->ioaddr;
                    146:        eth_nic_base = isa->ioaddr;
                    147: 
                    148:        /******************************************************************
                    149:         Search for NE1000/2000 if no WD/SMC or 3com cards
                    150:         ******************************************************************/
                    151:        if (eth_vendor == VENDOR_NONE) {
                    152: 
                    153:                static unsigned char test[] = "NE*000 memory";
                    154: 
                    155:                eth_bmem = 0; /* No shared memory */
                    156: 
                    157:                eth_flags = FLAG_PIO;
                    158:                eth_asic_base = eth_nic_base + NE_ASIC_OFFSET;
                    159:                eth_memsize = MEM_16384;
                    160:                eth_tx_start = 32;
                    161:                eth_rx_start = 32 + D8390_TXBUF_SIZE;
                    162:                c = inb(eth_asic_base + NE_RESET);
                    163:                outb(c, eth_asic_base + NE_RESET);
                    164:                (void) inb(0x84);
                    165:                outb(D8390_COMMAND_STP | D8390_COMMAND_RD2, eth_nic_base
                    166:                                + D8390_P0_COMMAND);
                    167:                outb(D8390_RCR_MON, eth_nic_base + D8390_P0_RCR);
                    168:                outb(D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
                    169:                outb(MEM_8192, eth_nic_base + D8390_P0_PSTART);
                    170:                outb(MEM_16384, eth_nic_base + D8390_P0_PSTOP);
                    171:                eth_pio_write((unsigned char *) test, 8192, sizeof(test));
                    172:                eth_pio_read(8192, testbuf, sizeof(test));
                    173:                if (!memcmp(test, testbuf, sizeof(test)))
                    174:                        goto out;
                    175:                eth_flags |= FLAG_16BIT;
                    176:                eth_memsize = MEM_32768;
                    177:                eth_tx_start = 64;
                    178:                eth_rx_start = 64 + D8390_TXBUF_SIZE;
                    179:                outb(D8390_DCR_WTS | D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base
                    180:                                + D8390_P0_DCR);
                    181:                outb(MEM_16384, eth_nic_base + D8390_P0_PSTART);
                    182:                outb(MEM_32768, eth_nic_base + D8390_P0_PSTOP);
                    183:                eth_pio_write((unsigned char *) test, 16384, sizeof(test));
                    184:                eth_pio_read(16384, testbuf, sizeof(test));
                    185:                if (!memcmp(testbuf, test, sizeof(test)))
                    186:                        goto out;
                    187: 
                    188: 
                    189: out:
                    190:                if (eth_nic_base == 0)
                    191:                        return (0);
                    192:                if (eth_nic_base > ISA_MAX_ADDR) /* PCI probably */
                    193:                        eth_flags |= FLAG_16BIT;
                    194:                eth_vendor = VENDOR_NOVELL;
                    195:                eth_pio_read(0, romdata, sizeof(romdata));
                    196:                for (i = 0; i < ETH_ALEN; i++) {
                    197:                        nic->node_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)];
                    198:                }
                    199:                nic->ioaddr = eth_nic_base;
                    200:                DBG("\nNE%c000 base %4.4x, MAC Addr %s\n",
                    201:                                (eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base, eth_ntoa(
                    202:                                                nic->node_addr));
                    203:        }
                    204: 
                    205:        if (eth_vendor == VENDOR_NONE)
                    206:                return (0);
                    207: 
                    208:        if (eth_vendor != VENDOR_3COM)
                    209:                eth_rmem = eth_bmem;
                    210: 
                    211:        ne_reset(nic, isa);
                    212:        nic->nic_op = &ne_operations;
                    213:        return 1;
                    214: }
                    215: 
                    216: 
                    217: /**************************************************************************
                    218:  NE_DISABLE - Turn off adapter
                    219:  **************************************************************************/
                    220: static void ne_disable(struct nic *nic, struct isa_device *isa) {
                    221:        ne_reset(nic, isa);
                    222: }
                    223: 
                    224: 
                    225: /**************************************************************************
                    226:  NE_RESET - Reset adapter
                    227:  **************************************************************************/
                    228: static void ne_reset(struct nic *nic, struct isa_device *isa __unused)
                    229: {
                    230:        int i;
                    231: 
                    232:        eth_drain_receiver = 0;
                    233:        outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
                    234:                        D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
                    235:        if (eth_flags & FLAG_16BIT)
                    236:        outb(0x49, eth_nic_base+D8390_P0_DCR);
                    237:        else
                    238:        outb(0x48, eth_nic_base+D8390_P0_DCR);
                    239:        outb(0, eth_nic_base+D8390_P0_RBCR0);
                    240:        outb(0, eth_nic_base+D8390_P0_RBCR1);
                    241:        outb(0x20, eth_nic_base+D8390_P0_RCR); /* monitor mode */
                    242:        outb(2, eth_nic_base+D8390_P0_TCR);
                    243:        outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
                    244:        outb(eth_rx_start, eth_nic_base+D8390_P0_PSTART);
                    245: 
                    246:        outb(eth_memsize, eth_nic_base+D8390_P0_PSTOP);
                    247:        outb(eth_memsize - 1, eth_nic_base+D8390_P0_BOUND);
                    248:        outb(0xFF, eth_nic_base+D8390_P0_ISR);
                    249:        outb(0, eth_nic_base+D8390_P0_IMR);
                    250:        outb(D8390_COMMAND_PS1 |
                    251:                        D8390_COMMAND_RD2 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
                    252: 
                    253:        for (i=0; i<ETH_ALEN; i++)
                    254:        outb(nic->node_addr[i], eth_nic_base+D8390_P1_PAR0+i);
                    255:        for (i=0; i<ETH_ALEN; i++)
                    256:        outb(0xFF, eth_nic_base+D8390_P1_MAR0+i);
                    257:        outb(eth_rx_start, eth_nic_base+D8390_P1_CURR);
                    258:        outb(D8390_COMMAND_PS0 |
                    259:                        D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
                    260:        outb(0xFF, eth_nic_base+D8390_P0_ISR);
                    261:        outb(0, eth_nic_base+D8390_P0_TCR); /* transmitter on */
                    262:        outb(4, eth_nic_base+D8390_P0_RCR); /* allow rx broadcast frames */
                    263: 
                    264:        enable_multicast(eth_nic_base);
                    265: }
                    266: 
                    267: 
                    268: /**************************************************************************
                    269:  NE_POLL - Wait for a frame
                    270:  **************************************************************************/
                    271: static int ne_poll(struct nic *nic __unused, int retrieve __unused)
                    272: {
                    273:        int ret = 0;
                    274:        unsigned char rstat, curr, next;
                    275:        unsigned short len, frag;
                    276:        unsigned short pktoff;
                    277:        unsigned char *p;
                    278:        struct ringbuffer pkthdr;
                    279: 
                    280:        rstat = inb(eth_nic_base+D8390_P0_RSR);
                    281:        if (!(rstat & D8390_RSTAT_PRX)) return(0);
                    282:        next = inb(eth_nic_base+D8390_P0_BOUND)+1;
                    283:        if (next >= eth_memsize) next = eth_rx_start;
                    284:        outb(D8390_COMMAND_PS1, eth_nic_base+D8390_P0_COMMAND);
                    285:        curr = inb(eth_nic_base+D8390_P1_CURR);
                    286:        outb(D8390_COMMAND_PS0, eth_nic_base+D8390_P0_COMMAND);
                    287:        if (curr >= eth_memsize) curr=eth_rx_start;
                    288:        if (curr == next) return(0);
                    289: 
                    290:        if ( ! retrieve ) return 1;
                    291: 
                    292:        pktoff = next << 8;
                    293:        if (eth_flags & FLAG_PIO)
                    294:        eth_pio_read(pktoff, (unsigned char *)&pkthdr, 4);
                    295:        else
                    296:        memcpy(&pkthdr, bus_to_virt(eth_rmem + pktoff), 4);
                    297:        pktoff += sizeof(pkthdr);
                    298:        /* incoming length includes FCS so must sub 4 */
                    299:        len = pkthdr.len - 4;
                    300:        if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN
                    301:                        || len> ETH_FRAME_LEN) {
                    302:                DBG("Bogus packet, ignoring\n");
                    303:                return (0);
                    304:        }
                    305:        else {
                    306:                p = nic->packet;
                    307:                nic->packetlen = len; /* available to caller */
                    308:                frag = (eth_memsize << 8) - pktoff;
                    309:                if (len> frag) { /* We have a wrap-around */
                    310:                        /* read first part */
                    311:                        if (eth_flags & FLAG_PIO)
                    312:                        eth_pio_read(pktoff, p, frag);
                    313:                        else
                    314:                        memcpy(p, bus_to_virt(eth_rmem + pktoff), frag);
                    315:                        pktoff = eth_rx_start << 8;
                    316:                        p += frag;
                    317:                        len -= frag;
                    318:                }
                    319:                /* read second part */
                    320:                if (eth_flags & FLAG_PIO)
                    321:                eth_pio_read(pktoff, p, len);
                    322:                else
                    323:                memcpy(p, bus_to_virt(eth_rmem + pktoff), len);
                    324:                ret = 1;
                    325:        }
                    326:        next = pkthdr.next; /* frame number of next packet */
                    327:        if (next == eth_rx_start)
                    328:        next = eth_memsize;
                    329:        outb(next-1, eth_nic_base+D8390_P0_BOUND);
                    330:        return(ret);
                    331: }
                    332: 
                    333: 
                    334: /**************************************************************************
                    335:  NE_TRANSMIT - Transmit a frame
                    336:  **************************************************************************/
                    337: static void ne_transmit(struct nic *nic, const char *d, /* Destination */
                    338: unsigned int t, /* Type */
                    339: unsigned int s, /* size */
                    340: const char *p) { /* Packet */
                    341: 
                    342:        /* Programmed I/O */
                    343:        unsigned short type;
                    344:        type = (t >> 8) | (t << 8);
                    345:        eth_pio_write((unsigned char *) d, eth_tx_start << 8, ETH_ALEN);
                    346:        eth_pio_write(nic->node_addr, (eth_tx_start << 8) + ETH_ALEN, ETH_ALEN);
                    347:        /* bcc generates worse code without (const+const) below */
                    348:        eth_pio_write((unsigned char *) &type, (eth_tx_start << 8) + (ETH_ALEN
                    349:                        + ETH_ALEN), 2);
                    350:        eth_pio_write((unsigned char *) p, (eth_tx_start << 8) + ETH_HLEN, s);
                    351:        s += ETH_HLEN;
                    352:        if (s < ETH_ZLEN)
                    353:                s = ETH_ZLEN;
                    354: 
                    355:        outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 | D8390_COMMAND_STA,
                    356:                        eth_nic_base + D8390_P0_COMMAND);
                    357:        outb(eth_tx_start, eth_nic_base + D8390_P0_TPSR);
                    358:        outb(s, eth_nic_base + D8390_P0_TBCR0);
                    359:        outb(s >> 8, eth_nic_base + D8390_P0_TBCR1);
                    360: 
                    361:        outb(D8390_COMMAND_PS0 | D8390_COMMAND_TXP | D8390_COMMAND_RD2
                    362:                        | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
                    363: }
                    364: 
                    365: static struct nic_operations ne_operations = { .connect = dummy_connect,
                    366:                .poll = ne_poll, .transmit = ne_transmit, .irq = dummy_irq,
                    367: };
                    368: 
                    369: ISA_DRIVER ( ne_driver, ne_probe_addrs, ne_probe1,
                    370:                GENERIC_ISAPNP_VENDOR, 0x0600 );
                    371: 
                    372: DRIVER ( "ne", nic_driver, isapnp_driver, ne_driver,
                    373:                ne_probe, ne_disable );
                    374: 
                    375: ISA_ROM("ne","NE1000/2000 and clones");

unix.superglobalmegacorp.com

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