Annotation of Gnu-Mach/linux/src/drivers/net/znet.c, revision 1.1

1.1     ! root        1: /* znet.c: An Zenith Z-Note ethernet driver for linux. */
        !             2: 
        !             3: static const char *version = "znet.c:v1.02 9/23/94 [email protected]\n";
        !             4: 
        !             5: /*
        !             6:        Written by Donald Becker.
        !             7: 
        !             8:        The author may be reached as [email protected].
        !             9:        This driver is based on the Linux skeleton driver.  The copyright of the
        !            10:        skeleton driver is held by the United States Government, as represented
        !            11:        by DIRNSA, and it is released under the GPL.
        !            12: 
        !            13:        Thanks to Mike Hollick for alpha testing and suggestions.
        !            14: 
        !            15:   References:
        !            16:           The Crynwr packet driver.
        !            17: 
        !            18:          "82593 CSMA/CD Core LAN Controller" Intel datasheet, 1992
        !            19:          Intel Microcommunications Databook, Vol. 1, 1990.
        !            20:     As usual with Intel, the documentation is incomplete and inaccurate.
        !            21:        I had to read the Crynwr packet driver to figure out how to actually
        !            22:        use the i82593, and guess at what register bits matched the loosely
        !            23:        related i82586.
        !            24: 
        !            25:                                        Theory of Operation
        !            26: 
        !            27:        The i82593 used in the Zenith Z-Note series operates using two(!) slave
        !            28:        DMA     channels, one interrupt, and one 8-bit I/O port.
        !            29: 
        !            30:        While there     several ways to configure '593 DMA system, I chose the one
        !            31:        that seemed commensurate with the highest system performance in the face
        !            32:        of moderate interrupt latency: Both DMA channels are configured as
        !            33:        recirculating ring buffers, with one channel (#0) dedicated to Rx and
        !            34:        the other channel (#1) to Tx and configuration.  (Note that this is
        !            35:        different than the Crynwr driver, where the Tx DMA channel is initialized
        !            36:        before each operation.  That approach simplifies operation and Tx error
        !            37:        recovery, but requires additional I/O in normal operation and precludes
        !            38:        transmit buffer chaining.)
        !            39: 
        !            40:        Both rings are set to 8192 bytes using {TX,RX}_RING_SIZE.  This provides
        !            41:        a reasonable ring size for Rx, while simplifying DMA buffer allocation --
        !            42:        DMA buffers must not cross a 128K boundary.  (In truth the size selection
        !            43:        was influenced by my lack of '593 documentation.  I thus was constrained
        !            44:        to use the Crynwr '593 initialization table, which sets the Rx ring size
        !            45:        to 8K.)
        !            46: 
        !            47:        Despite my usual low opinion about Intel-designed parts, I must admit
        !            48:        that the bulk data handling of the i82593 is a good design for
        !            49:        an integrated system, like a laptop, where using two slave DMA channels
        !            50:        doesn't pose a problem.  I still take issue with using only a single I/O
        !            51:        port.  In the same controlled environment there are essentially no
        !            52:        limitations on I/O space, and using multiple locations would eliminate
        !            53:        the     need for multiple operations when looking at status registers,
        !            54:        setting the Rx ring boundary, or switching to promiscuous mode.
        !            55: 
        !            56:        I also question Zenith's selection of the '593: one of the advertised
        !            57:        advantages of earlier Intel parts was that if you figured out the magic
        !            58:        initialization incantation you could use the same part on many different
        !            59:        network types.  Zenith's use of the "FriendlyNet" (sic) connector rather
        !            60:        than an on-board transceiver leads me to believe that they were planning
        !            61:        to take advantage of this.  But, uhmmm, the '593 omits all but ethernet
        !            62:        functionality from the serial subsystem.
        !            63:  */
        !            64: 
        !            65: #include <linux/kernel.h>
        !            66: #include <linux/sched.h>
        !            67: #include <linux/string.h>
        !            68: #include <linux/ptrace.h>
        !            69: #include <linux/errno.h>
        !            70: #include <linux/interrupt.h>
        !            71: #include <linux/ioport.h>
        !            72: #include <asm/system.h>
        !            73: #include <asm/bitops.h>
        !            74: #include <asm/io.h>
        !            75: #include <asm/dma.h>
        !            76: 
        !            77: #include <linux/netdevice.h>
        !            78: #include <linux/etherdevice.h>
        !            79: #include <linux/skbuff.h>
        !            80: #include <linux/if_arp.h>
        !            81: 
        !            82: #ifndef ZNET_DEBUG
        !            83: #define ZNET_DEBUG 1
        !            84: #endif
        !            85: static unsigned int znet_debug = ZNET_DEBUG;
        !            86: 
        !            87: /* The DMA modes we need aren't in <dma.h>. */
        !            88: #define DMA_RX_MODE            0x14    /* Auto init, I/O to mem, ++, demand. */
        !            89: #define DMA_TX_MODE            0x18    /* Auto init, Mem to I/O, ++, demand. */
        !            90: #define dma_page_eq(ptr1, ptr2) ((long)(ptr1)>>17 == (long)(ptr2)>>17)
        !            91: #define DMA_BUF_SIZE 8192
        !            92: #define RX_BUF_SIZE 8192
        !            93: #define TX_BUF_SIZE 8192
        !            94: 
        !            95: /* Commands to the i82593 channel 0. */
        !            96: #define CMD0_CHNL_0                    0x00
        !            97: #define CMD0_CHNL_1                    0x10            /* Switch to channel 1. */
        !            98: #define CMD0_NOP (CMD0_CHNL_0)
        !            99: #define CMD0_PORT_1    CMD0_CHNL_1
        !           100: #define CMD1_PORT_0    1
        !           101: #define CMD0_IA_SETUP          1
        !           102: #define CMD0_CONFIGURE         2
        !           103: #define CMD0_MULTICAST_LIST 3
        !           104: #define CMD0_TRANSMIT          4
        !           105: #define CMD0_DUMP                      6
        !           106: #define CMD0_DIAGNOSE          7
        !           107: #define CMD0_Rx_ENABLE         8
        !           108: #define CMD0_Rx_DISABLE                10
        !           109: #define CMD0_Rx_STOP           11
        !           110: #define CMD0_RETRANSMIT                12
        !           111: #define CMD0_ABORT                     13
        !           112: #define CMD0_RESET                     14
        !           113: 
        !           114: #define CMD0_ACK 0x80
        !           115: 
        !           116: #define CMD0_STAT0 (0 << 5)
        !           117: #define CMD0_STAT1 (1 << 5)
        !           118: #define CMD0_STAT2 (2 << 5)
        !           119: #define CMD0_STAT3 (3 << 5)
        !           120: 
        !           121: #define net_local znet_private
        !           122: struct znet_private {
        !           123:        int rx_dma, tx_dma;
        !           124:        struct enet_statistics stats;
        !           125:        /* The starting, current, and end pointers for the packet buffers. */
        !           126:        ushort *rx_start, *rx_cur, *rx_end;
        !           127:        ushort *tx_start, *tx_cur, *tx_end;
        !           128:        ushort tx_buf_len;                      /* Tx buffer length, in words. */
        !           129: };
        !           130: 
        !           131: /* Only one can be built-in;-> */
        !           132: static struct znet_private zn;
        !           133: static ushort dma_buffer1[DMA_BUF_SIZE/2];
        !           134: static ushort dma_buffer2[DMA_BUF_SIZE/2];
        !           135: static ushort dma_buffer3[DMA_BUF_SIZE/2 + 8];
        !           136: 
        !           137: /* The configuration block.  What an undocumented nightmare.  The first
        !           138:    set of values are those suggested (without explanation) for ethernet
        !           139:    in the Intel 82586 databook.         The rest appear to be completely undocumented,
        !           140:    except for cryptic notes in the Crynwr packet driver.  This driver uses
        !           141:    the Crynwr values verbatim. */
        !           142: 
        !           143: static unsigned char i593_init[] = {
        !           144:   0xAA,                                        /* 0: 16-byte input & 80-byte output FIFO. */
        !           145:                                                /*        threshold, 96-byte FIFO, 82593 mode. */
        !           146:   0x88,                                        /* 1: Continuous w/interrupts, 128-clock DMA.*/
        !           147:   0x2E,                                        /* 2: 8-byte preamble, NO address insertion, */
        !           148:                                                /*        6-byte Ethernet address, loopback off.*/
        !           149:   0x00,                                        /* 3: Default priorities & backoff methods. */
        !           150:   0x60,                                        /* 4: 96-bit interframe spacing. */
        !           151:   0x00,                                        /* 5: 512-bit slot time (low-order). */
        !           152:   0xF2,                                        /* 6: Slot time (high-order), 15 COLL retries. */
        !           153:   0x00,                                        /* 7: Promisc-off, broadcast-on, default CRC. */
        !           154:   0x00,                                        /* 8: Default carrier-sense, collision-detect. */
        !           155:   0x40,                                        /* 9: 64-byte minimum frame length. */
        !           156:   0x5F,                                        /* A: Type/length checks OFF, no CRC input,
        !           157:                                                   "jabber" termination, etc. */
        !           158:   0x00,                                        /* B: Full-duplex disabled. */
        !           159:   0x3F,                                        /* C: Default multicast addresses & backoff. */
        !           160:   0x07,                                        /* D: Default IFS retriggering. */
        !           161:   0x31,                                        /* E: Internal retransmit, drop "runt" packets,
        !           162:                                                   synchr. DRQ deassertion, 6 status bytes. */
        !           163:   0x22,                                        /* F: Receive ring-buffer size (8K), 
        !           164:                                                   receive-stop register enable. */
        !           165: };
        !           166: 
        !           167: struct netidblk {
        !           168:        char magic[8];          /* The magic number (string) "NETIDBLK" */
        !           169:        unsigned char netid[8]; /* The physical station address */
        !           170:        char nettype, globalopt;
        !           171:        char vendor[8];         /* The machine vendor and product name. */
        !           172:        char product[8];
        !           173:        char irq1, irq2;                /* Interrupts, only one is currently used.      */
        !           174:        char dma1, dma2;
        !           175:        short dma_mem_misc[8];          /* DMA buffer locations (unused in Linux). */
        !           176:        short iobase1, iosize1;
        !           177:        short iobase2, iosize2;         /* Second iobase unused. */
        !           178:        char driver_options;                    /* Misc. bits */
        !           179:        char pad;
        !           180: };
        !           181: 
        !           182: int znet_probe(struct device *dev);
        !           183: static int     znet_open(struct device *dev);
        !           184: static int     znet_send_packet(struct sk_buff *skb, struct device *dev);
        !           185: static void    znet_interrupt(int irq, void *dev_id, struct pt_regs *regs);
        !           186: static void    znet_rx(struct device *dev);
        !           187: static int     znet_close(struct device *dev);
        !           188: static struct enet_statistics *net_get_stats(struct device *dev);
        !           189: static void set_multicast_list(struct device *dev);
        !           190: static void hardware_init(struct device *dev);
        !           191: static void update_stop_hit(short ioaddr, unsigned short rx_stop_offset);
        !           192: 
        !           193: #ifdef notdef
        !           194: static struct sigaction znet_sigaction = { &znet_interrupt, 0, 0, NULL, };
        !           195: #endif
        !           196: 
        !           197: 
        !           198: /* The Z-Note probe is pretty easy.  The NETIDBLK exists in the safe-to-probe
        !           199:    BIOS area.  We just scan for the signature, and pull the vital parameters
        !           200:    out of the structure. */
        !           201: 
        !           202: int znet_probe(struct device *dev)
        !           203: {
        !           204:        int i;
        !           205:        struct netidblk *netinfo;
        !           206:        char *p;
        !           207: 
        !           208:        /* This code scans the region 0xf0000 to 0xfffff for a "NETIDBLK". */
        !           209:        for(p = (char *)0xf0000; p < (char *)0x100000; p++)
        !           210:                if (*p == 'N'  &&  strncmp(p, "NETIDBLK", 8) == 0)
        !           211:                        break;
        !           212: 
        !           213:        if (p >= (char *)0x100000) {
        !           214:                if (znet_debug > 1)
        !           215:                        printk(KERN_INFO "No Z-Note ethernet adaptor found.\n");
        !           216:                return ENODEV;
        !           217:        }
        !           218:        netinfo = (struct netidblk *)p;
        !           219:        dev->base_addr = netinfo->iobase1;
        !           220:        dev->irq = netinfo->irq1;
        !           221: 
        !           222:        printk(KERN_INFO "%s: ZNET at %#3lx,", dev->name, dev->base_addr);
        !           223: 
        !           224:        /* The station address is in the "netidblk" at 0x0f0000. */
        !           225:        for (i = 0; i < 6; i++)
        !           226:                printk(" %2.2x", dev->dev_addr[i] = netinfo->netid[i]);
        !           227: 
        !           228:        printk(", using IRQ %d DMA %d and %d.\n", dev->irq, netinfo->dma1,
        !           229:                netinfo->dma2);
        !           230: 
        !           231:        if (znet_debug > 1) {
        !           232:                printk(KERN_INFO "%s: vendor '%16.16s' IRQ1 %d IRQ2 %d DMA1 %d DMA2 %d.\n",
        !           233:                           dev->name, netinfo->vendor,
        !           234:                           netinfo->irq1, netinfo->irq2,
        !           235:                           netinfo->dma1, netinfo->dma2);
        !           236:                printk(KERN_INFO "%s: iobase1 %#x size %d iobase2 %#x size %d net type %2.2x.\n",
        !           237:                           dev->name, netinfo->iobase1, netinfo->iosize1,
        !           238:                           netinfo->iobase2, netinfo->iosize2, netinfo->nettype);
        !           239:        }
        !           240: 
        !           241:        if (znet_debug > 0)
        !           242:                printk("%s%s", KERN_INFO, version);
        !           243: 
        !           244:        dev->priv = (void *) &zn;
        !           245:        zn.rx_dma = netinfo->dma1;
        !           246:        zn.tx_dma = netinfo->dma2;
        !           247: 
        !           248:        /* These should never fail.  You can't add devices to a sealed box! */
        !           249:        if (request_irq(dev->irq, &znet_interrupt, 0, "ZNet", NULL)
        !           250:                || request_dma(zn.rx_dma,"ZNet rx")
        !           251:                || request_dma(zn.tx_dma,"ZNet tx")) {
        !           252:                printk(KERN_WARNING "%s: Not opened -- resource busy?!?\n", dev->name);
        !           253:                return EBUSY;
        !           254:        }
        !           255:        irq2dev_map[dev->irq] = dev;
        !           256: 
        !           257:        /* Allocate buffer memory.      We can cross a 128K boundary, so we
        !           258:           must be careful about the allocation.  It's easiest to waste 8K. */
        !           259:        if (dma_page_eq(dma_buffer1, &dma_buffer1[RX_BUF_SIZE/2-1]))
        !           260:          zn.rx_start = dma_buffer1;
        !           261:        else 
        !           262:          zn.rx_start = dma_buffer2;
        !           263: 
        !           264:        if (dma_page_eq(dma_buffer3, &dma_buffer3[RX_BUF_SIZE/2-1]))
        !           265:          zn.tx_start = dma_buffer3;
        !           266:        else
        !           267:          zn.tx_start = dma_buffer2;
        !           268:        zn.rx_end = zn.rx_start + RX_BUF_SIZE/2;
        !           269:        zn.tx_buf_len = TX_BUF_SIZE/2;
        !           270:        zn.tx_end = zn.tx_start + zn.tx_buf_len;
        !           271: 
        !           272:        /* The ZNET-specific entries in the device structure. */
        !           273:        dev->open = &znet_open;
        !           274:        dev->hard_start_xmit = &znet_send_packet;
        !           275:        dev->stop = &znet_close;
        !           276:        dev->get_stats  = net_get_stats;
        !           277:        dev->set_multicast_list = &set_multicast_list;
        !           278: 
        !           279:        /* Fill in the 'dev' with ethernet-generic values. */
        !           280:        ether_setup(dev);
        !           281: 
        !           282:        return 0;
        !           283: }
        !           284: 
        !           285: 
        !           286: static int znet_open(struct device *dev)
        !           287: {
        !           288:        int ioaddr = dev->base_addr;
        !           289: 
        !           290:        if (znet_debug > 2)
        !           291:                printk(KERN_DEBUG "%s: znet_open() called.\n", dev->name);
        !           292: 
        !           293:        /* Turn on the 82501 SIA, using zenith-specific magic. */
        !           294:        outb(0x10, 0xe6);                                       /* Select LAN control register */
        !           295:        outb(inb(0xe7) | 0x84, 0xe7);           /* Turn on LAN power (bit 2). */
        !           296:        /* According to the Crynwr driver we should wait 50 msec. for the
        !           297:           LAN clock to stabilize.  My experiments indicates that the '593 can
        !           298:           be initialized immediately.  The delay is probably needed for the
        !           299:           DC-to-DC converter to come up to full voltage, and for the oscillator
        !           300:           to be spot-on at 20Mhz before transmitting.
        !           301:           Until this proves to be a problem we rely on the higher layers for the
        !           302:           delay and save allocating a timer entry. */
        !           303: 
        !           304:        /* This follows the packet driver's lead, and checks for success. */
        !           305:        if (inb(ioaddr) != 0x10 && inb(ioaddr) != 0x00)
        !           306:                printk(KERN_WARNING "%s: Problem turning on the transceiver power.\n",
        !           307:                           dev->name);
        !           308: 
        !           309:        dev->tbusy = 0;
        !           310:        dev->interrupt = 0;
        !           311:        hardware_init(dev);
        !           312:        dev->start = 1;
        !           313: 
        !           314:        return 0;
        !           315: }
        !           316: 
        !           317: static int znet_send_packet(struct sk_buff *skb, struct device *dev)
        !           318: {
        !           319:        int ioaddr = dev->base_addr;
        !           320: 
        !           321:        if (znet_debug > 4)
        !           322:                printk(KERN_DEBUG "%s: ZNet_send_packet(%ld).\n", dev->name, dev->tbusy);
        !           323: 
        !           324:        /* Transmitter timeout, likely just recovery after suspending the machine. */
        !           325:        if (dev->tbusy) {
        !           326:                ushort event, tx_status, rx_offset, state;
        !           327:                int tickssofar = jiffies - dev->trans_start;
        !           328:                if (tickssofar < 10)
        !           329:                        return 1;
        !           330:                outb(CMD0_STAT0, ioaddr); event = inb(ioaddr);
        !           331:                outb(CMD0_STAT1, ioaddr); tx_status = inw(ioaddr);
        !           332:                outb(CMD0_STAT2, ioaddr); rx_offset = inw(ioaddr);
        !           333:                outb(CMD0_STAT3, ioaddr); state = inb(ioaddr);
        !           334:                printk(KERN_WARNING "%s: transmit timed out, status %02x %04x %04x %02x,"
        !           335:                           " resetting.\n", dev->name, event, tx_status, rx_offset, state);
        !           336:                if (tx_status == 0x0400)
        !           337:                  printk(KERN_WARNING "%s: Tx carrier error, check transceiver cable.\n",
        !           338:                                 dev->name);
        !           339:                outb(CMD0_RESET, ioaddr);
        !           340:                hardware_init(dev);
        !           341:        }
        !           342: 
        !           343:        if (skb == NULL) {
        !           344:                dev_tint(dev);
        !           345:                return 0;
        !           346:        }
        !           347: 
        !           348:        /* Check that the part hasn't reset itself, probably from suspend. */
        !           349:        outb(CMD0_STAT0, ioaddr);
        !           350:        if (inw(ioaddr) == 0x0010
        !           351:                && inw(ioaddr) == 0x0000
        !           352:                && inw(ioaddr) == 0x0010)
        !           353:          hardware_init(dev);
        !           354: 
        !           355:        /* Block a timer-based transmit from overlapping.  This could better be
        !           356:           done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
        !           357:        if (set_bit(0, (void*)&dev->tbusy) != 0)
        !           358:                printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
        !           359:        else {
        !           360:                short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
        !           361:                unsigned char *buf = (void *)skb->data;
        !           362:                ushort *tx_link = zn.tx_cur - 1;
        !           363:                ushort rnd_len = (length + 1)>>1;
        !           364: 
        !           365:                {
        !           366:                        short dma_port = ((zn.tx_dma&3)<<2) + IO_DMA2_BASE;
        !           367:                        unsigned addr = inb(dma_port);
        !           368:                        addr |= inb(dma_port) << 8;
        !           369:                        addr <<= 1;
        !           370:                        if (((int)zn.tx_cur & 0x1ffff) != addr)
        !           371:                          printk(KERN_WARNING "Address mismatch at Tx: %#x vs %#x.\n",
        !           372:                                         (int)zn.tx_cur & 0xffff, addr);
        !           373:                        zn.tx_cur = (ushort *)(((int)zn.tx_cur & 0xfe0000) | addr);
        !           374:                }
        !           375: 
        !           376:                if (zn.tx_cur >= zn.tx_end)
        !           377:                  zn.tx_cur = zn.tx_start;
        !           378:                *zn.tx_cur++ = length;
        !           379:                if (zn.tx_cur + rnd_len + 1 > zn.tx_end) {
        !           380:                        int semi_cnt = (zn.tx_end - zn.tx_cur)<<1; /* Cvrt to byte cnt. */
        !           381:                        memcpy(zn.tx_cur, buf, semi_cnt);
        !           382:                        rnd_len -= semi_cnt>>1;
        !           383:                        memcpy(zn.tx_start, buf + semi_cnt, length - semi_cnt);
        !           384:                        zn.tx_cur = zn.tx_start + rnd_len;
        !           385:                } else {
        !           386:                        memcpy(zn.tx_cur, buf, skb->len);
        !           387:                        zn.tx_cur += rnd_len;
        !           388:                }
        !           389:                *zn.tx_cur++ = 0;
        !           390:                cli(); {
        !           391:                        *tx_link = CMD0_TRANSMIT + CMD0_CHNL_1;
        !           392:                        /* Is this always safe to do? */
        !           393:                        outb(CMD0_TRANSMIT + CMD0_CHNL_1,ioaddr);
        !           394:                } sti();
        !           395: 
        !           396:                dev->trans_start = jiffies;
        !           397:                if (znet_debug > 4)
        !           398:                  printk(KERN_DEBUG "%s: Transmitter queued, length %d.\n", dev->name, length);
        !           399:        }
        !           400:        dev_kfree_skb(skb, FREE_WRITE); 
        !           401:        return 0;
        !           402: }
        !           403: 
        !           404: /* The ZNET interrupt handler. */
        !           405: static void    znet_interrupt(int irq, void *dev_id, struct pt_regs * regs)
        !           406: {
        !           407:        struct device *dev = irq2dev_map[irq];
        !           408:        int ioaddr;
        !           409:        int boguscnt = 20;
        !           410: 
        !           411:        if (dev == NULL) {
        !           412:                printk(KERN_WARNING "znet_interrupt(): IRQ %d for unknown device.\n", irq);
        !           413:                return;
        !           414:        }
        !           415: 
        !           416:        dev->interrupt = 1;
        !           417:        ioaddr = dev->base_addr;
        !           418: 
        !           419:        outb(CMD0_STAT0, ioaddr);
        !           420:        do {
        !           421:                ushort status = inb(ioaddr);
        !           422:                if (znet_debug > 5) {
        !           423:                        ushort result, rx_ptr, running;
        !           424:                        outb(CMD0_STAT1, ioaddr);
        !           425:                        result = inw(ioaddr);
        !           426:                        outb(CMD0_STAT2, ioaddr);
        !           427:                        rx_ptr = inw(ioaddr);
        !           428:                        outb(CMD0_STAT3, ioaddr);
        !           429:                        running = inb(ioaddr);
        !           430:                        printk(KERN_DEBUG "%s: interrupt, status %02x, %04x %04x %02x serial %d.\n",
        !           431:                                 dev->name, status, result, rx_ptr, running, boguscnt);
        !           432:                }
        !           433:                if ((status & 0x80) == 0)
        !           434:                        break;
        !           435: 
        !           436:                if ((status & 0x0F) == 4) {     /* Transmit done. */
        !           437:                        struct net_local *lp = (struct net_local *)dev->priv;
        !           438:                        int tx_status;
        !           439:                        outb(CMD0_STAT1, ioaddr);
        !           440:                        tx_status = inw(ioaddr);
        !           441:                        /* It's undocumented, but tx_status seems to match the i82586. */
        !           442:                        if (tx_status & 0x2000) {
        !           443:                                lp->stats.tx_packets++;
        !           444:                                lp->stats.collisions += tx_status & 0xf;
        !           445:                        } else {
        !           446:                                if (tx_status & 0x0600)  lp->stats.tx_carrier_errors++;
        !           447:                                if (tx_status & 0x0100)  lp->stats.tx_fifo_errors++;
        !           448:                                if (!(tx_status & 0x0040)) lp->stats.tx_heartbeat_errors++;
        !           449:                                if (tx_status & 0x0020)  lp->stats.tx_aborted_errors++;
        !           450:                                /* ...and the catch-all. */
        !           451:                                if ((tx_status | 0x0760) != 0x0760)
        !           452:                                  lp->stats.tx_errors++;
        !           453:                        }
        !           454:                        dev->tbusy = 0;
        !           455:                        mark_bh(NET_BH);        /* Inform upper layers. */
        !           456:                }
        !           457: 
        !           458:                if ((status & 0x40)
        !           459:                        || (status & 0x0f) == 11) {
        !           460:                        znet_rx(dev);
        !           461:                }
        !           462:                /* Clear the interrupts we've handled. */
        !           463:                outb(CMD0_ACK,ioaddr);
        !           464:        } while (boguscnt--);
        !           465: 
        !           466:        dev->interrupt = 0;
        !           467:        return;
        !           468: }
        !           469: 
        !           470: static void znet_rx(struct device *dev)
        !           471: {
        !           472:        struct net_local *lp = (struct net_local *)dev->priv;
        !           473:        int ioaddr = dev->base_addr;
        !           474:        int boguscount = 1;
        !           475:        short next_frame_end_offset = 0;                /* Offset of next frame start. */
        !           476:        short *cur_frame_end;
        !           477:        short cur_frame_end_offset;
        !           478: 
        !           479:        outb(CMD0_STAT2, ioaddr);
        !           480:        cur_frame_end_offset = inw(ioaddr);
        !           481: 
        !           482:        if (cur_frame_end_offset == zn.rx_cur - zn.rx_start) {
        !           483:                printk(KERN_WARNING "%s: Interrupted, but nothing to receive, offset %03x.\n",
        !           484:                           dev->name, cur_frame_end_offset);
        !           485:                return;
        !           486:        }
        !           487: 
        !           488:        /* Use same method as the Crynwr driver: construct a forward list in
        !           489:           the same area of the backwards links we now have.  This allows us to
        !           490:           pass packets to the upper layers in the order they were received --
        !           491:           important for fast-path sequential operations. */
        !           492:         while (zn.rx_start + cur_frame_end_offset != zn.rx_cur
        !           493:                        && ++boguscount < 5) {
        !           494:                unsigned short hi_cnt, lo_cnt, hi_status, lo_status;
        !           495:                int count, status;
        !           496: 
        !           497:                if (cur_frame_end_offset < 4) {
        !           498:                        /* Oh no, we have a special case: the frame trailer wraps around
        !           499:                           the end of the ring buffer.  We've saved space at the end of
        !           500:                           the ring buffer for just this problem. */
        !           501:                        memcpy(zn.rx_end, zn.rx_start, 8);
        !           502:                        cur_frame_end_offset += (RX_BUF_SIZE/2);
        !           503:                }
        !           504:                cur_frame_end = zn.rx_start + cur_frame_end_offset - 4;
        !           505: 
        !           506:                lo_status = *cur_frame_end++;
        !           507:                hi_status = *cur_frame_end++;
        !           508:                status = ((hi_status & 0xff) << 8) + (lo_status & 0xff);
        !           509:                lo_cnt = *cur_frame_end++;
        !           510:                hi_cnt = *cur_frame_end++;
        !           511:                count = ((hi_cnt & 0xff) << 8) + (lo_cnt & 0xff);
        !           512: 
        !           513:                if (znet_debug > 5)
        !           514:                  printk(KERN_DEBUG "Constructing trailer at location %03x, %04x %04x %04x %04x"
        !           515:                                 " count %#x status %04x.\n",
        !           516:                                 cur_frame_end_offset<<1, lo_status, hi_status, lo_cnt, hi_cnt,
        !           517:                                 count, status);
        !           518:                cur_frame_end[-4] = status;
        !           519:                cur_frame_end[-3] = next_frame_end_offset;
        !           520:                cur_frame_end[-2] = count;
        !           521:                next_frame_end_offset = cur_frame_end_offset;
        !           522:                cur_frame_end_offset -= ((count + 1)>>1) + 3;
        !           523:                if (cur_frame_end_offset < 0)
        !           524:                  cur_frame_end_offset += RX_BUF_SIZE/2;
        !           525:        };
        !           526: 
        !           527:        /* Now step  forward through the list. */
        !           528:        do {
        !           529:                ushort *this_rfp_ptr = zn.rx_start + next_frame_end_offset;
        !           530:                int status = this_rfp_ptr[-4];
        !           531:                int pkt_len = this_rfp_ptr[-2];
        !           532:          
        !           533:                if (znet_debug > 5)
        !           534:                  printk(KERN_DEBUG "Looking at trailer ending at %04x status %04x length %03x"
        !           535:                                 " next %04x.\n", next_frame_end_offset<<1, status, pkt_len,
        !           536:                                 this_rfp_ptr[-3]<<1);
        !           537:                /* Once again we must assume that the i82586 docs apply. */
        !           538:                if ( ! (status & 0x2000)) {                             /* There was an error. */
        !           539:                        lp->stats.rx_errors++;
        !           540:                        if (status & 0x0800) lp->stats.rx_crc_errors++;
        !           541:                        if (status & 0x0400) lp->stats.rx_frame_errors++;
        !           542:                        if (status & 0x0200) lp->stats.rx_over_errors++; /* Wrong. */
        !           543:                        if (status & 0x0100) lp->stats.rx_fifo_errors++;
        !           544:                        if (status & 0x0080) lp->stats.rx_length_errors++;
        !           545:                } else if (pkt_len > 1536) {
        !           546:                        lp->stats.rx_length_errors++;
        !           547:                } else {
        !           548:                        /* Malloc up new buffer. */
        !           549:                        struct sk_buff *skb;
        !           550: 
        !           551:                        skb = dev_alloc_skb(pkt_len);
        !           552:                        if (skb == NULL) {
        !           553:                                if (znet_debug)
        !           554:                                  printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
        !           555:                                lp->stats.rx_dropped++;
        !           556:                                break;
        !           557:                        }
        !           558:                        skb->dev = dev;
        !           559: 
        !           560:                        if (&zn.rx_cur[(pkt_len+1)>>1] > zn.rx_end) {
        !           561:                                int semi_cnt = (zn.rx_end - zn.rx_cur)<<1;
        !           562:                                memcpy(skb_put(skb,semi_cnt), zn.rx_cur, semi_cnt);
        !           563:                                memcpy(skb_put(skb,pkt_len-semi_cnt), zn.rx_start,
        !           564:                                           pkt_len - semi_cnt);
        !           565:                        } else {
        !           566:                                memcpy(skb_put(skb,pkt_len), zn.rx_cur, pkt_len);
        !           567:                                if (znet_debug > 6) {
        !           568:                                        unsigned int *packet = (unsigned int *) skb->data;
        !           569:                                        printk(KERN_DEBUG "Packet data is %08x %08x %08x %08x.\n", packet[0],
        !           570:                                                   packet[1], packet[2], packet[3]);
        !           571:                                }
        !           572:                  }
        !           573:                  skb->protocol=eth_type_trans(skb,dev);
        !           574:                  netif_rx(skb);
        !           575:                  lp->stats.rx_packets++;
        !           576:                }
        !           577:                zn.rx_cur = this_rfp_ptr;
        !           578:                if (zn.rx_cur >= zn.rx_end)
        !           579:                        zn.rx_cur -= RX_BUF_SIZE/2;
        !           580:                update_stop_hit(ioaddr, (zn.rx_cur - zn.rx_start)<<1);
        !           581:                next_frame_end_offset = this_rfp_ptr[-3];
        !           582:                if (next_frame_end_offset == 0)         /* Read all the frames? */
        !           583:                        break;                  /* Done for now */
        !           584:                this_rfp_ptr = zn.rx_start + next_frame_end_offset;
        !           585:        } while (--boguscount);
        !           586: 
        !           587:        /* If any worth-while packets have been received, dev_rint()
        !           588:           has done a mark_bh(INET_BH) for us and will work on them
        !           589:           when we get to the bottom-half routine. */
        !           590:        return;
        !           591: }
        !           592: 
        !           593: /* The inverse routine to znet_open(). */
        !           594: static int znet_close(struct device *dev)
        !           595: {
        !           596:        int ioaddr = dev->base_addr;
        !           597: 
        !           598:        dev->tbusy = 1;
        !           599:        dev->start = 0;
        !           600: 
        !           601:        outb(CMD0_RESET, ioaddr);                       /* CMD0_RESET */
        !           602: 
        !           603:        disable_dma(zn.rx_dma);
        !           604:        disable_dma(zn.tx_dma);
        !           605: 
        !           606:        free_irq(dev->irq, NULL);
        !           607: 
        !           608:        if (znet_debug > 1)
        !           609:                printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
        !           610:        /* Turn off transceiver power. */
        !           611:        outb(0x10, 0xe6);                                       /* Select LAN control register */
        !           612:        outb(inb(0xe7) & ~0x84, 0xe7);          /* Turn on LAN power (bit 2). */
        !           613: 
        !           614:        return 0;
        !           615: }
        !           616: 
        !           617: /* Get the current statistics. This may be called with the card open or
        !           618:    closed. */
        !           619: static struct enet_statistics *net_get_stats(struct device *dev)
        !           620: {
        !           621:                struct net_local *lp = (struct net_local *)dev->priv;
        !           622: 
        !           623:                return &lp->stats;
        !           624: }
        !           625: 
        !           626: /* Set or clear the multicast filter for this adaptor.
        !           627:    As a side effect this routine must also initialize the device parameters.
        !           628:    This is taken advantage of in open().
        !           629: 
        !           630:    N.B. that we change i593_init[] in place.  This (properly) makes the
        !           631:    mode change persistent, but must be changed if this code is moved to
        !           632:    a multiple adaptor environment.
        !           633:  */
        !           634: static void set_multicast_list(struct device *dev)
        !           635: {
        !           636:        short ioaddr = dev->base_addr;
        !           637: 
        !           638:        if (dev->flags&IFF_PROMISC) {
        !           639:                /* Enable promiscuous mode */
        !           640:                i593_init[7] &= ~3;             i593_init[7] |= 1;
        !           641:                i593_init[13] &= ~8;    i593_init[13] |= 8;
        !           642:        } else if (dev->mc_list || (dev->flags&IFF_ALLMULTI)) {
        !           643:                /* Enable accept-all-multicast mode */
        !           644:                i593_init[7] &= ~3;             i593_init[7] |= 0;
        !           645:                i593_init[13] &= ~8;    i593_init[13] |= 8;
        !           646:        } else {                                        /* Enable normal mode. */
        !           647:                i593_init[7] &= ~3;             i593_init[7] |= 0;
        !           648:                i593_init[13] &= ~8;    i593_init[13] |= 0;
        !           649:        }
        !           650:        *zn.tx_cur++ = sizeof(i593_init);
        !           651:        memcpy(zn.tx_cur, i593_init, sizeof(i593_init));
        !           652:        zn.tx_cur += sizeof(i593_init)/2;
        !           653:        outb(CMD0_CONFIGURE+CMD0_CHNL_1, ioaddr);
        !           654: #ifdef not_tested
        !           655:        if (num_addrs > 0) {
        !           656:                int addrs_len = 6*num_addrs;
        !           657:                *zn.tx_cur++ = addrs_len;
        !           658:                memcpy(zn.tx_cur, addrs, addrs_len);
        !           659:                outb(CMD0_MULTICAST_LIST+CMD0_CHNL_1, ioaddr);
        !           660:                zn.tx_cur += addrs_len>>1;
        !           661:        }
        !           662: #endif
        !           663: }
        !           664: 
        !           665: void show_dma(void)
        !           666: {
        !           667:        short dma_port = ((zn.tx_dma&3)<<2) + IO_DMA2_BASE;
        !           668:        unsigned addr = inb(dma_port);
        !           669:        addr |= inb(dma_port) << 8;
        !           670:        printk("Addr: %04x cnt:%3x...", addr<<1, get_dma_residue(zn.tx_dma));
        !           671: }
        !           672: 
        !           673: /* Initialize the hardware.  We have to do this when the board is open()ed
        !           674:    or when we come out of suspend mode. */
        !           675: static void hardware_init(struct device *dev)
        !           676: {
        !           677:        short ioaddr = dev->base_addr;
        !           678: 
        !           679:        zn.rx_cur = zn.rx_start;
        !           680:        zn.tx_cur = zn.tx_start;
        !           681: 
        !           682:        /* Reset the chip, and start it up. */
        !           683:        outb(CMD0_RESET, ioaddr);
        !           684: 
        !           685:        cli(); {                                                        /* Protect against a DMA flip-flop */
        !           686:                disable_dma(zn.rx_dma);                 /* reset by an interrupting task. */
        !           687:                clear_dma_ff(zn.rx_dma);
        !           688:                set_dma_mode(zn.rx_dma, DMA_RX_MODE);
        !           689:                set_dma_addr(zn.rx_dma, (unsigned int) zn.rx_start);
        !           690:                set_dma_count(zn.rx_dma, RX_BUF_SIZE);
        !           691:                enable_dma(zn.rx_dma);
        !           692:                /* Now set up the Tx channel. */
        !           693:                disable_dma(zn.tx_dma);
        !           694:                clear_dma_ff(zn.tx_dma);
        !           695:                set_dma_mode(zn.tx_dma, DMA_TX_MODE);
        !           696:                set_dma_addr(zn.tx_dma, (unsigned int) zn.tx_start);
        !           697:                set_dma_count(zn.tx_dma, zn.tx_buf_len<<1);
        !           698:                enable_dma(zn.tx_dma);
        !           699:        } sti();
        !           700: 
        !           701:        if (znet_debug > 1)
        !           702:          printk(KERN_DEBUG "%s: Initializing the i82593, tx buf %p... ", dev->name,
        !           703:                         zn.tx_start);
        !           704:        /* Do an empty configure command, just like the Crynwr driver.  This
        !           705:           resets to chip to its default values. */
        !           706:        *zn.tx_cur++ = 0;
        !           707:        *zn.tx_cur++ = 0;
        !           708:        printk("stat:%02x ", inb(ioaddr)); show_dma();
        !           709:        outb(CMD0_CONFIGURE+CMD0_CHNL_1, ioaddr);
        !           710:        *zn.tx_cur++ = sizeof(i593_init);
        !           711:        memcpy(zn.tx_cur, i593_init, sizeof(i593_init));
        !           712:        zn.tx_cur += sizeof(i593_init)/2;
        !           713:        printk("stat:%02x ", inb(ioaddr)); show_dma();
        !           714:        outb(CMD0_CONFIGURE+CMD0_CHNL_1, ioaddr);
        !           715:        *zn.tx_cur++ = 6;
        !           716:        memcpy(zn.tx_cur, dev->dev_addr, 6);
        !           717:        zn.tx_cur += 3;
        !           718:        printk("stat:%02x ", inb(ioaddr)); show_dma();
        !           719:        outb(CMD0_IA_SETUP + CMD0_CHNL_1, ioaddr);
        !           720:        printk("stat:%02x ", inb(ioaddr)); show_dma();
        !           721: 
        !           722:        update_stop_hit(ioaddr, 8192);
        !           723:        if (znet_debug > 1)  printk("enabling Rx.\n");
        !           724:        outb(CMD0_Rx_ENABLE+CMD0_CHNL_0, ioaddr);
        !           725:        dev->tbusy = 0;
        !           726: }
        !           727: 
        !           728: static void update_stop_hit(short ioaddr, unsigned short rx_stop_offset)
        !           729: {
        !           730:        outb(CMD0_PORT_1, ioaddr);
        !           731:        if (znet_debug > 5)
        !           732:          printk(KERN_DEBUG "Updating stop hit with value %02x.\n",
        !           733:                         (rx_stop_offset >> 6) | 0x80);
        !           734:        outb((rx_stop_offset >> 6) | 0x80, ioaddr);
        !           735:        outb(CMD1_PORT_0, ioaddr);
        !           736: }
        !           737: 
        !           738: /*
        !           739:  * Local variables:
        !           740:  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c znet.c"
        !           741:  *  version-control: t
        !           742:  *  kept-new-versions: 5
        !           743:  *  c-indent-level: 4
        !           744:  *  tab-width: 4
        !           745:  * End:
        !           746:  */

unix.superglobalmegacorp.com

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