Annotation of Gnu-Mach/linux/src/drivers/net/hp.c, revision 1.1.1.2

1.1       root        1: /* hp.c: A HP LAN ethernet driver for linux. */
                      2: /*
                      3:        Written 1993-94 by Donald Becker.
                      4: 
                      5:        Copyright 1993 United States Government as represented by the
                      6:        Director, National Security Agency.
                      7: 
                      8:        This software may be used and distributed according to the terms
                      9:        of the GNU Public License, incorporated herein by reference.
                     10: 
                     11:        The author may be reached as [email protected], or C/O
                     12:        Center of Excellence in Space Data and Information Sciences
                     13:           Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
                     14: 
                     15:        This is a driver for the HP PC-LAN adaptors.
                     16: 
                     17:        Sources:
                     18:          The Crynwr packet driver.
                     19: */
                     20: 
                     21: static const char *version =
                     22:        "hp.c:v1.10 9/23/94 Donald Becker ([email protected])\n";
                     23: 
                     24: 
                     25: #include <linux/module.h>
                     26: 
                     27: #include <linux/kernel.h>
                     28: #include <linux/sched.h>
                     29: #include <linux/errno.h>
                     30: #include <linux/ioport.h>
                     31: #include <linux/netdevice.h>
                     32: #include <linux/etherdevice.h>
                     33: 
                     34: #include <asm/system.h>
                     35: #include <asm/io.h>
                     36: 
                     37: #include "8390.h"
                     38: 
                     39: /* A zero-terminated list of I/O addresses to be probed. */
                     40: static unsigned int hppclan_portlist[] =
                     41: { 0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240, 0};
                     42: 
                     43: #define HP_IO_EXTENT   32
                     44: 
                     45: #define HP_DATAPORT            0x0c    /* "Remote DMA" data port. */
                     46: #define HP_ID                  0x07
                     47: #define HP_CONFIGURE   0x08    /* Configuration register. */
                     48: #define         HP_RUN                 0x01    /* 1 == Run, 0 == reset. */
                     49: #define         HP_IRQ                 0x0E    /* Mask for software-configured IRQ line. */
                     50: #define         HP_DATAON              0x10    /* Turn on dataport */
                     51: #define NIC_OFFSET             0x10    /* Offset the 8390 registers. */
                     52: 
                     53: #define HP_START_PG            0x00    /* First page of TX buffer */
                     54: #define HP_8BSTOP_PG   0x80    /* Last page +1 of RX ring */
                     55: #define HP_16BSTOP_PG  0xFF    /* Same, for 16 bit cards. */
                     56: 
                     57: int hp_probe(struct device *dev);
                     58: int hp_probe1(struct device *dev, int ioaddr);
                     59: 
                     60: static int hp_open(struct device *dev);
                     61: static int hp_close(struct device *dev);
                     62: static void hp_reset_8390(struct device *dev);
                     63: static void hp_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
                     64:                                        int ring_page);
                     65: static void hp_block_input(struct device *dev, int count,
                     66:                                        struct sk_buff *skb , int ring_offset);
                     67: static void hp_block_output(struct device *dev, int count,
                     68:                                                        const unsigned char *buf, const int start_page);
                     69: 
                     70: static void hp_init_card(struct device *dev);
                     71: 
                     72: /* The map from IRQ number to HP_CONFIGURE register setting. */
                     73: /* My default is IRQ5     0  1  2  3  4  5  6  7  8  9 10 11 */
                     74: static char irqmap[16] = { 0, 0, 4, 6, 8,10, 0,14, 0, 4, 2,12,0,0,0,0};
                     75: 
                     76: 
                     77: /*     Probe for an HP LAN adaptor.
                     78:        Also initialize the card and fill in STATION_ADDR with the station
                     79:        address. */
                     80: #ifdef HAVE_DEVLIST
                     81: struct netdev_entry netcard_drv =
                     82: {"hp", hp_probe1, HP_IO_EXTENT, hppclan_portlist};
                     83: #else
                     84: 
                     85: int hp_probe(struct device *dev)
                     86: {
                     87:        int i;
                     88:        int base_addr = dev ? dev->base_addr : 0;
                     89: 
                     90:        if (base_addr > 0x1ff)          /* Check a single specified location. */
                     91:                return hp_probe1(dev, base_addr);
                     92:        else if (base_addr != 0)        /* Don't probe at all. */
                     93:                return ENXIO;
                     94: 
                     95:        for (i = 0; hppclan_portlist[i]; i++) {
                     96:                int ioaddr = hppclan_portlist[i];
                     97:                if (check_region(ioaddr, HP_IO_EXTENT))
                     98:                        continue;
                     99:                if (hp_probe1(dev, ioaddr) == 0)
                    100:                        return 0;
                    101:        }
                    102: 
                    103:        return ENODEV;
                    104: }
                    105: #endif
                    106: 
                    107: int hp_probe1(struct device *dev, int ioaddr)
                    108: {
                    109:        int i, board_id, wordmode;
                    110:        const char *name;
                    111:        static unsigned version_printed = 0;
                    112: 
                    113:        /* Check for the HP physical address, 08 00 09 xx xx xx. */
                    114:        /* This really isn't good enough: we may pick up HP LANCE boards
                    115:           also!  Avoid the lance 0x5757 signature. */
                    116:        if (inb(ioaddr) != 0x08
                    117:                || inb(ioaddr+1) != 0x00
                    118:                || inb(ioaddr+2) != 0x09
                    119:                || inb(ioaddr+14) == 0x57)
                    120:                return ENODEV;
                    121: 
                    122:        /* Set up the parameters based on the board ID.
                    123:           If you have additional mappings, please mail them to me -djb. */
                    124:        if ((board_id = inb(ioaddr + HP_ID)) & 0x80) {
                    125:                name = "HP27247";
                    126:                wordmode = 1;
                    127:        } else {
                    128:                name = "HP27250";
                    129:                wordmode = 0;
                    130:        }
                    131: 
                    132:        /* We should have a "dev" from Space.c or the static module table. */
                    133:        if (dev == NULL) {
                    134:                printk("hp.c: Passed a NULL device.\n");
                    135:                dev = init_etherdev(0, 0);
                    136:        }
                    137: 
                    138:        if (ei_debug  &&  version_printed++ == 0)
1.1.1.2 ! root      139:                printk("%s", version);
1.1       root      140:  
                    141:        printk("%s: %s (ID %02x) at %#3x,", dev->name, name, board_id, ioaddr);
                    142: 
                    143:        for(i = 0; i < ETHER_ADDR_LEN; i++)
                    144:                printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i));
                    145: 
                    146:        /* Snarf the interrupt now.  Someday this could be moved to open(). */
                    147:        if (dev->irq < 2) {
                    148:                int irq_16list[] = { 11, 10, 5, 3, 4, 7, 9, 0};
                    149:                int irq_8list[] = { 7, 5, 3, 4, 9, 0};
                    150:                int *irqp = wordmode ? irq_16list : irq_8list;
                    151:                do {
                    152:                        int irq = *irqp;
                    153:                        if (request_irq (irq, NULL, 0, "bogus", NULL) != -EBUSY) {
                    154:                                autoirq_setup(0);
                    155:                                /* Twinkle the interrupt, and check if it's seen. */
                    156:                                outb_p(irqmap[irq] | HP_RUN, ioaddr + HP_CONFIGURE);
                    157:                                outb_p( 0x00 | HP_RUN, ioaddr + HP_CONFIGURE);
                    158:                                if (irq == autoirq_report(0)             /* It's a good IRQ line! */
                    159:                                        && request_irq (irq, &ei_interrupt, 0, "hp", NULL) == 0) {
                    160:                                        printk(" selecting IRQ %d.\n", irq);
                    161:                                        dev->irq = *irqp;
                    162:                                        break;
                    163:                                }
                    164:                        }
                    165:                } while (*++irqp);
                    166:                if (*irqp == 0) {
                    167:                        printk(" no free IRQ lines.\n");
                    168:                        return EBUSY;
                    169:                }
                    170:        } else {
                    171:                if (dev->irq == 2)
                    172:                        dev->irq = 9;
                    173:                if (request_irq(dev->irq, ei_interrupt, 0, "hp", NULL)) {
                    174:                        printk (" unable to get IRQ %d.\n", dev->irq);
                    175:                        return EBUSY;
                    176:                }
                    177:        }
                    178: 
                    179:        /* Allocate dev->priv and fill in 8390 specific dev fields. */
                    180:        if (ethdev_init(dev)) {
                    181:                printk (" unable to get memory for dev->priv.\n");
                    182:                free_irq(dev->irq, NULL);
                    183:                return -ENOMEM;
                    184:        }
                    185: 
                    186:        /* Grab the region so we can find another board if something fails. */
                    187:        request_region(ioaddr, HP_IO_EXTENT,"hp");
                    188: 
                    189:        /* Set the base address to point to the NIC, not the "real" base! */
                    190:        dev->base_addr = ioaddr + NIC_OFFSET;
                    191:        dev->open = &hp_open;
                    192:        dev->stop = &hp_close;
                    193: 
                    194:        ei_status.name = name;
                    195:        ei_status.word16 = wordmode;
                    196:        ei_status.tx_start_page = HP_START_PG;
                    197:        ei_status.rx_start_page = HP_START_PG + TX_PAGES;
                    198:        ei_status.stop_page = wordmode ? HP_16BSTOP_PG : HP_8BSTOP_PG;
                    199: 
                    200:        ei_status.reset_8390 = &hp_reset_8390;
                    201:        ei_status.get_8390_hdr = &hp_get_8390_hdr;
                    202:        ei_status.block_input = &hp_block_input;
                    203:        ei_status.block_output = &hp_block_output;
                    204:        hp_init_card(dev);
                    205: 
                    206:        return 0;
                    207: }
                    208: 
                    209: static int
                    210: hp_open(struct device *dev)
                    211: {
                    212:        ei_open(dev);
                    213:        MOD_INC_USE_COUNT;
                    214:        return 0;
                    215: }
                    216: 
                    217: static int
                    218: hp_close(struct device *dev)
                    219: {
                    220:        ei_close(dev);
                    221:        MOD_DEC_USE_COUNT;
                    222:        return 0;
                    223: }
                    224: 
                    225: static void
                    226: hp_reset_8390(struct device *dev)
                    227: {
                    228:        int hp_base = dev->base_addr - NIC_OFFSET;
                    229:        int saved_config = inb_p(hp_base + HP_CONFIGURE);
                    230: 
                    231:        if (ei_debug > 1) printk("resetting the 8390 time=%ld...", jiffies);
                    232:        outb_p(0x00, hp_base + HP_CONFIGURE);
                    233:        ei_status.txing = 0;
                    234:        /* Pause just a few cycles for the hardware reset to take place. */
                    235:        SLOW_DOWN_IO;
                    236:        SLOW_DOWN_IO;
                    237: 
                    238:        outb_p(saved_config, hp_base + HP_CONFIGURE);
                    239:        SLOW_DOWN_IO; SLOW_DOWN_IO;
                    240:        
                    241:        if ((inb_p(hp_base+NIC_OFFSET+EN0_ISR) & ENISR_RESET) == 0)
                    242:                printk("%s: hp_reset_8390() did not complete.\n", dev->name);
                    243: 
                    244:        if (ei_debug > 1) printk("8390 reset done (%ld).", jiffies);
                    245:        return;
                    246: }
                    247: 
                    248: static void
                    249: hp_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
                    250: {
                    251:        int nic_base = dev->base_addr;
                    252:        int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
                    253: 
                    254:        outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE);
                    255:        outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base);
                    256:        outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
                    257:        outb_p(0, nic_base + EN0_RCNTHI);
                    258:        outb_p(0, nic_base + EN0_RSARLO);       /* On page boundary */
                    259:        outb_p(ring_page, nic_base + EN0_RSARHI);
                    260:        outb_p(E8390_RREAD+E8390_START, nic_base);
                    261: 
                    262:        if (ei_status.word16) 
                    263:          insw(nic_base - NIC_OFFSET + HP_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
                    264:        else 
                    265:          insb(nic_base - NIC_OFFSET + HP_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
                    266: 
                    267:        outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE);
                    268: }
                    269:        
                    270: /* Block input and output, similar to the Crynwr packet driver. If you are
                    271:    porting to a new ethercard look at the packet driver source for hints.
                    272:    The HP LAN doesn't use shared memory -- we put the packet
                    273:    out through the "remote DMA" dataport. */
                    274: 
                    275: static void
                    276: hp_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
                    277: {
                    278:        int nic_base = dev->base_addr;
                    279:        int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
                    280:        int xfer_count = count;
                    281:        char *buf = skb->data;
                    282: 
                    283:        outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE);
                    284:        outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base);
                    285:        outb_p(count & 0xff, nic_base + EN0_RCNTLO);
                    286:        outb_p(count >> 8, nic_base + EN0_RCNTHI);
                    287:        outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
                    288:        outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
                    289:        outb_p(E8390_RREAD+E8390_START, nic_base);
                    290:        if (ei_status.word16) {
                    291:          insw(nic_base - NIC_OFFSET + HP_DATAPORT,buf,count>>1);
                    292:          if (count & 0x01)
                    293:                buf[count-1] = inb(nic_base - NIC_OFFSET + HP_DATAPORT), xfer_count++;
                    294:        } else {
                    295:                insb(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count);
                    296:        }
                    297:        /* This is for the ALPHA version only, remove for later releases. */
                    298:        if (ei_debug > 0) {                     /* DMA termination address check... */
                    299:          int high = inb_p(nic_base + EN0_RSARHI);
                    300:          int low = inb_p(nic_base + EN0_RSARLO);
                    301:          int addr = (high << 8) + low;
                    302:          /* Check only the lower 8 bits so we can ignore ring wrap. */
                    303:          if (((ring_offset + xfer_count) & 0xff) != (addr & 0xff))
                    304:                printk("%s: RX transfer address mismatch, %#4.4x vs. %#4.4x (actual).\n",
                    305:                           dev->name, ring_offset + xfer_count, addr);
                    306:        }
                    307:        outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE);
                    308: }
                    309: 
                    310: static void
                    311: hp_block_output(struct device *dev, int count,
                    312:                                const unsigned char *buf, const int start_page)
                    313: {
                    314:        int nic_base = dev->base_addr;
                    315:        int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
                    316: 
                    317:        outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE);
                    318:        /* Round the count up for word writes.  Do we need to do this?
                    319:           What effect will an odd byte count have on the 8390?
                    320:           I should check someday. */
                    321:        if (ei_status.word16 && (count & 0x01))
                    322:          count++;
                    323:        /* We should already be in page 0, but to be safe... */
                    324:        outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base);
                    325: 
                    326: #ifdef NE8390_RW_BUGFIX
                    327:        /* Handle the read-before-write bug the same way as the
                    328:           Crynwr packet driver -- the NatSemi method doesn't work. */
                    329:        outb_p(0x42, nic_base + EN0_RCNTLO);
                    330:        outb_p(0,       nic_base + EN0_RCNTHI);
                    331:        outb_p(0xff, nic_base + EN0_RSARLO);
                    332:        outb_p(0x00, nic_base + EN0_RSARHI);
                    333: #define NE_CMD         0x00
                    334:        outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
                    335:        /* Make certain that the dummy read has occurred. */
                    336:        inb_p(0x61);
                    337:        inb_p(0x61);
                    338: #endif
                    339: 
                    340:        outb_p(count & 0xff, nic_base + EN0_RCNTLO);
                    341:        outb_p(count >> 8,       nic_base + EN0_RCNTHI);
                    342:        outb_p(0x00, nic_base + EN0_RSARLO);
                    343:        outb_p(start_page, nic_base + EN0_RSARHI);
                    344: 
                    345:        outb_p(E8390_RWRITE+E8390_START, nic_base);
                    346:        if (ei_status.word16) {
                    347:                /* Use the 'rep' sequence for 16 bit boards. */
                    348:                outsw(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count>>1);
                    349:        } else {
                    350:                outsb(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count);
                    351:        }
                    352: 
                    353:        /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here -- it's broken! */
                    354: 
                    355:        /* This is for the ALPHA version only, remove for later releases. */
                    356:        if (ei_debug > 0) {                     /* DMA termination address check... */
                    357:          int high = inb_p(nic_base + EN0_RSARHI);
                    358:          int low  = inb_p(nic_base + EN0_RSARLO);
                    359:          int addr = (high << 8) + low;
                    360:          if ((start_page << 8) + count != addr)
                    361:                printk("%s: TX Transfer address mismatch, %#4.4x vs. %#4.4x.\n",
                    362:                           dev->name, (start_page << 8) + count, addr);
                    363:        }
                    364:        outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE);
                    365:        return;
                    366: }
                    367: 
                    368: /* This function resets the ethercard if something screws up. */
                    369: static void
                    370: hp_init_card(struct device *dev)
                    371: {
                    372:        int irq = dev->irq;
                    373:        NS8390_init(dev, 0);
                    374:        outb_p(irqmap[irq&0x0f] | HP_RUN,
                    375:                   dev->base_addr - NIC_OFFSET + HP_CONFIGURE);
                    376:        return;
                    377: }
                    378: 
                    379: #ifdef MODULE
                    380: #define MAX_HP_CARDS   4       /* Max number of HP cards per module */
                    381: #define NAMELEN                8       /* # of chars for storing dev->name */
                    382: static char namelist[NAMELEN * MAX_HP_CARDS] = { 0, };
                    383: static struct device dev_hp[MAX_HP_CARDS] = {
                    384:        {
                    385:                NULL,           /* assign a chunk of namelist[] below */
                    386:                0, 0, 0, 0,
                    387:                0, 0,
                    388:                0, 0, 0, NULL, NULL
                    389:        },
                    390: };
                    391: 
                    392: static int io[MAX_HP_CARDS] = { 0, };
                    393: static int irq[MAX_HP_CARDS]  = { 0, };
                    394: 
                    395: /* This is set up so that only a single autoprobe takes place per call.
                    396: ISA device autoprobes on a running machine are not recommended. */
                    397: int
                    398: init_module(void)
                    399: {
                    400:        int this_dev, found = 0;
                    401: 
                    402:        for (this_dev = 0; this_dev < MAX_HP_CARDS; this_dev++) {
                    403:                struct device *dev = &dev_hp[this_dev];
                    404:                dev->name = namelist+(NAMELEN*this_dev);
                    405:                dev->irq = irq[this_dev];
                    406:                dev->base_addr = io[this_dev];
                    407:                dev->init = hp_probe;
                    408:                if (io[this_dev] == 0)  {
                    409:                        if (this_dev != 0) break; /* only autoprobe 1st one */
                    410:                        printk(KERN_NOTICE "hp.c: Presently autoprobing (not recommended) for a single card.\n");
                    411:                }
                    412:                if (register_netdev(dev) != 0) {
                    413:                        printk(KERN_WARNING "hp.c: No HP card found (i/o = 0x%x).\n", io[this_dev]);
                    414:                        if (found != 0) return 0;       /* Got at least one. */
                    415:                        return -ENXIO;
                    416:                }
                    417:                found++;
                    418:        }
                    419: 
                    420:        return 0;
                    421: }
                    422: 
                    423: void
                    424: cleanup_module(void)
                    425: {
                    426:        int this_dev;
                    427: 
                    428:        for (this_dev = 0; this_dev < MAX_HP_CARDS; this_dev++) {
                    429:                struct device *dev = &dev_hp[this_dev];
                    430:                if (dev->priv != NULL) {
                    431:                        int ioaddr = dev->base_addr - NIC_OFFSET;
                    432:                        kfree(dev->priv);
                    433:                        dev->priv = NULL;
                    434:                        free_irq(dev->irq, NULL);
                    435:                        irq2dev_map[dev->irq] = NULL;
                    436:                        release_region(ioaddr, HP_IO_EXTENT);
                    437:                        unregister_netdev(dev);
                    438:                }
                    439:        }
                    440: }
                    441: #endif /* MODULE */
                    442: 
                    443: /*
                    444:  * Local variables:
                    445:  * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c hp.c"
                    446:  * version-control: t
                    447:  * kept-new-versions: 5
                    448:  * tab-width: 4
                    449:  * c-indent-level: 4
                    450:  * End:
                    451:  */

unix.superglobalmegacorp.com

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