Annotation of qemu/roms/ipxe/src/drivers/net/ne2k_isa.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:  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.