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

1.1     ! root        1: /* apricot.c: An Apricot 82596 ethernet driver for linux. */
        !             2: /*
        !             3:     Apricot
        !             4:        Written 1994 by Mark Evans.
        !             5:        This driver is for the Apricot 82596 bus-master interface
        !             6: 
        !             7:         Modularised 12/94 Mark Evans
        !             8:     
        !             9:     Driver skeleton 
        !            10:        Written 1993 by Donald Becker.
        !            11:        Copyright 1993 United States Government as represented by the Director,
        !            12:        National Security Agency.  This software may only be used and distributed
        !            13:        according to the terms of the GNU Public License as modified by SRC,
        !            14:        incorporated herein by reference.
        !            15: 
        !            16:        The author may be reached as [email protected] or
        !            17:        C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
        !            18:     
        !            19: 
        !            20: */
        !            21: 
        !            22: static const char *version = "apricot.c:v0.2 05/12/94\n";
        !            23: 
        !            24: #include <linux/module.h>
        !            25: 
        !            26: #include <linux/kernel.h>
        !            27: #include <linux/sched.h>
        !            28: #include <linux/string.h>
        !            29: #include <linux/ptrace.h>
        !            30: #include <linux/errno.h>
        !            31: #include <linux/ioport.h>
        !            32: #include <linux/malloc.h>
        !            33: #include <linux/interrupt.h>
        !            34: #include <linux/netdevice.h>
        !            35: #include <linux/etherdevice.h>
        !            36: #include <linux/skbuff.h>
        !            37: 
        !            38: #include <asm/bitops.h>
        !            39: #include <asm/io.h>
        !            40: #include <asm/dma.h>
        !            41: 
        !            42: #ifndef HAVE_PORTRESERVE
        !            43: #define check_region(addr, size)       0
        !            44: #define request_region(addr, size,name)        do ; while(0)
        !            45: #endif
        !            46: 
        !            47: #ifndef HAVE_ALLOC_SKB
        !            48: #define alloc_skb(size, priority) (struct sk_buff *) kmalloc(size,priority)
        !            49: #define kfree_skbmem(buff, size) kfree_s(buff,size)
        !            50: #endif
        !            51: 
        !            52: #define APRICOT_DEBUG 1
        !            53: 
        !            54: #ifdef APRICOT_DEBUG
        !            55: int i596_debug = APRICOT_DEBUG;
        !            56: #else
        !            57: int i596_debug = 1;
        !            58: #endif
        !            59: 
        !            60: #define APRICOT_TOTAL_SIZE 17
        !            61: 
        !            62: #define I596_NULL -1
        !            63: 
        !            64: #define CMD_EOL                0x8000  /* The last command of the list, stop. */
        !            65: #define CMD_SUSP       0x4000  /* Suspend after doing cmd. */
        !            66: #define CMD_INTR       0x2000  /* Interrupt after doing cmd. */
        !            67: 
        !            68: #define CMD_FLEX       0x0008  /* Enable flexible memory model */
        !            69: 
        !            70: enum commands {
        !            71:        CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
        !            72:        CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7};
        !            73: 
        !            74: #define STAT_C         0x8000  /* Set to 0 after execution */
        !            75: #define STAT_B         0x4000  /* Command being executed */
        !            76: #define STAT_OK                0x2000  /* Command executed ok */
        !            77: #define STAT_A         0x1000  /* Command aborted */
        !            78: 
        !            79: #define         CUC_START      0x0100
        !            80: #define         CUC_RESUME     0x0200
        !            81: #define         CUC_SUSPEND    0x0300
        !            82: #define         CUC_ABORT      0x0400
        !            83: #define         RX_START       0x0010
        !            84: #define         RX_RESUME      0x0020
        !            85: #define         RX_SUSPEND     0x0030
        !            86: #define         RX_ABORT       0x0040
        !            87: 
        !            88: struct i596_cmd {
        !            89:     unsigned short status;
        !            90:     unsigned short command;
        !            91:     struct i596_cmd *next;
        !            92: };
        !            93: 
        !            94: #define EOF            0x8000
        !            95: #define SIZE_MASK      0x3fff
        !            96: 
        !            97: struct i596_tbd {
        !            98:     unsigned short size;
        !            99:     unsigned short pad;
        !           100:     struct i596_tbd *next;
        !           101:     char *data;
        !           102: };
        !           103: 
        !           104: struct tx_cmd {
        !           105:     struct i596_cmd cmd;
        !           106:     struct i596_tbd *tbd;
        !           107:     unsigned short size;
        !           108:     unsigned short pad;
        !           109: };
        !           110: 
        !           111: struct i596_rfd {
        !           112:     unsigned short stat;
        !           113:     unsigned short cmd;
        !           114:     struct i596_rfd *next;
        !           115:     long rbd; 
        !           116:     unsigned short count;
        !           117:     unsigned short size;
        !           118:     char data[1532];
        !           119: };
        !           120: 
        !           121: #define RX_RING_SIZE 8
        !           122: 
        !           123: struct i596_scb {
        !           124:     unsigned short status;
        !           125:     unsigned short command;
        !           126:     struct i596_cmd *cmd;
        !           127:     struct i596_rfd *rfd;
        !           128:     unsigned long crc_err;
        !           129:     unsigned long align_err;
        !           130:     unsigned long resource_err;
        !           131:     unsigned long over_err;
        !           132:     unsigned long rcvdt_err;
        !           133:     unsigned long short_err;
        !           134:     unsigned short t_on;
        !           135:     unsigned short t_off;
        !           136: };
        !           137: 
        !           138: struct i596_iscp {
        !           139:     unsigned long stat;
        !           140:     struct i596_scb *scb;
        !           141: };
        !           142: 
        !           143: struct i596_scp {
        !           144:     unsigned long sysbus;
        !           145:     unsigned long pad;
        !           146:     struct i596_iscp *iscp;
        !           147: };
        !           148: 
        !           149: struct i596_private {
        !           150:     volatile struct i596_scp scp;
        !           151:     volatile struct i596_iscp iscp;
        !           152:     volatile struct i596_scb scb;
        !           153:     volatile struct i596_cmd set_add;
        !           154:     char eth_addr[8];
        !           155:     volatile struct i596_cmd set_conf;
        !           156:     char i596_config[16];
        !           157:     volatile struct i596_cmd tdr;
        !           158:     unsigned long stat;
        !           159:     int last_restart;
        !           160:     struct i596_rfd *rx_tail;
        !           161:     struct i596_cmd *cmd_tail;
        !           162:     struct i596_cmd *cmd_head;
        !           163:     int cmd_backlog;
        !           164:     unsigned long last_cmd;
        !           165:     struct enet_statistics stats;
        !           166: };
        !           167: 
        !           168: char init_setup[] = {
        !           169:        0x8E,   /* length, prefetch on */
        !           170:        0xC8,   /* fifo to 8, monitor off */
        !           171:        0x80,   /* don't save bad frames */
        !           172:        0x2E,   /* No source address insertion, 8 byte preamble */
        !           173:        0x00,   /* priority and backoff defaults */
        !           174:        0x60,   /* interframe spacing */
        !           175:        0x00,   /* slot time LSB */
        !           176:        0xf2,   /* slot time and retries */
        !           177:        0x00,   /* promiscuous mode */
        !           178:        0x00,   /* collision detect */
        !           179:        0x40,   /* minimum frame length */
        !           180:        0xff,   
        !           181:        0x00,
        !           182:        0x7f    /*  *multi IA */ };
        !           183: 
        !           184: static int i596_open(struct device *dev);
        !           185: static int i596_start_xmit(struct sk_buff *skb, struct device *dev);
        !           186: static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs);
        !           187: static int i596_close(struct device *dev);
        !           188: static struct enet_statistics *i596_get_stats(struct device *dev);
        !           189: static void i596_add_cmd(struct device *dev, struct i596_cmd *cmd);
        !           190: static void print_eth(char *);
        !           191: static void set_multicast_list(struct device *dev);
        !           192: 
        !           193: 
        !           194: static inline int
        !           195: init_rx_bufs(struct device *dev, int num)
        !           196: {
        !           197:     struct i596_private *lp = (struct i596_private *)dev->priv;
        !           198:     int i;
        !           199:     struct i596_rfd *rfd;
        !           200: 
        !           201:     lp->scb.rfd = (struct i596_rfd *)I596_NULL;
        !           202: 
        !           203:     if (i596_debug > 1) printk ("%s: init_rx_bufs %d.\n", dev->name, num);
        !           204: 
        !           205:     for (i = 0; i < num; i++)
        !           206:     {
        !           207:        if (!(rfd = (struct i596_rfd *)kmalloc(sizeof(struct i596_rfd), GFP_KERNEL)))
        !           208:             break;
        !           209: 
        !           210:        rfd->stat = 0x0000;
        !           211:        rfd->rbd = I596_NULL;
        !           212:        rfd->count = 0;
        !           213:        rfd->size = 1532;
        !           214:         if (i == 0)
        !           215:         {
        !           216:            rfd->cmd = CMD_EOL;
        !           217:             lp->rx_tail = rfd;
        !           218:         }
        !           219:         else
        !           220:            rfd->cmd = 0x0000;
        !           221: 
        !           222:         rfd->next = lp->scb.rfd;
        !           223:         lp->scb.rfd = rfd;
        !           224:     }
        !           225: 
        !           226:     if (i != 0)
        !           227:       lp->rx_tail->next = lp->scb.rfd;
        !           228: 
        !           229:     return (i);
        !           230: }
        !           231: 
        !           232: static inline void
        !           233: remove_rx_bufs(struct device *dev)
        !           234: {
        !           235:     struct i596_private *lp = (struct i596_private *)dev->priv;
        !           236:     struct i596_rfd *rfd = lp->scb.rfd;
        !           237: 
        !           238:     lp->rx_tail->next = (struct i596_rfd *)I596_NULL;
        !           239: 
        !           240:     do
        !           241:     {
        !           242:         lp->scb.rfd = rfd->next;
        !           243:         kfree_s(rfd, sizeof(struct i596_rfd));
        !           244:         rfd = lp->scb.rfd;
        !           245:     }
        !           246:     while (rfd != lp->rx_tail);
        !           247: }
        !           248: 
        !           249: static inline void
        !           250: init_i596_mem(struct device *dev)
        !           251: {
        !           252:     struct i596_private *lp = (struct i596_private *)dev->priv;
        !           253:     short ioaddr = dev->base_addr;
        !           254:     int boguscnt = 100;
        !           255: 
        !           256:     /* change the scp address */
        !           257:     outw(0, ioaddr);
        !           258:     outw(0, ioaddr);
        !           259:     outb(4, ioaddr+0xf);
        !           260:     outw(((((int)&lp->scp) & 0xffff) | 2), ioaddr);
        !           261:     outw((((int)&lp->scp)>>16) & 0xffff, ioaddr);
        !           262: 
        !           263:     lp->last_cmd = jiffies;
        !           264: 
        !           265:     lp->scp.sysbus = 0x00440000;
        !           266:     lp->scp.iscp = &(lp->iscp);
        !           267:     lp->iscp.scb = &(lp->scb);
        !           268:     lp->iscp.stat = 0x0001;
        !           269:     lp->cmd_backlog = 0;
        !           270: 
        !           271:     lp->cmd_head = lp->scb.cmd = (struct i596_cmd *) I596_NULL;
        !           272: 
        !           273:     if (i596_debug > 2) printk("%s: starting i82596.\n", dev->name);
        !           274: 
        !           275:     (void) inb (ioaddr+0x10);
        !           276:     outb(4, ioaddr+0xf);
        !           277:     outw(0, ioaddr+4);
        !           278: 
        !           279:     while (lp->iscp.stat)
        !           280:        if (--boguscnt == 0)
        !           281:        {
        !           282:            printk("%s: i82596 initialization timed out with status %4.4x, cmd %4.4x.\n",
        !           283:                   dev->name, lp->scb.status, lp->scb.command);
        !           284:            break;
        !           285:        }
        !           286: 
        !           287:     lp->scb.command = 0;
        !           288: 
        !           289:     memcpy (lp->i596_config, init_setup, 14);
        !           290:     lp->set_conf.command = CmdConfigure;
        !           291:     i596_add_cmd(dev, &lp->set_conf);
        !           292: 
        !           293:     memcpy (lp->eth_addr, dev->dev_addr, 6);
        !           294:     lp->set_add.command = CmdSASetup;
        !           295:     i596_add_cmd(dev, &lp->set_add);
        !           296: 
        !           297:     lp->tdr.command = CmdTDR;
        !           298:     i596_add_cmd(dev, &lp->tdr);
        !           299: 
        !           300:     boguscnt = 200;
        !           301:     while (lp->scb.status, lp->scb.command)
        !           302:        if (--boguscnt == 0)
        !           303:        {
        !           304:            printk("%s: receive unit start timed out with status %4.4x, cmd %4.4x.\n",
        !           305:                   dev->name, lp->scb.status, lp->scb.command);
        !           306:            break;
        !           307:        }
        !           308: 
        !           309:     lp->scb.command = RX_START;
        !           310:     outw(0, ioaddr+4);
        !           311: 
        !           312:     boguscnt = 200;
        !           313:     while (lp->scb.status, lp->scb.command)
        !           314:         if (--boguscnt == 0)
        !           315:        {
        !           316:            printk("i82596 init timed out with status %4.4x, cmd %4.4x.\n",
        !           317:                lp->scb.status, lp->scb.command);
        !           318:            break;
        !           319:        }
        !           320: 
        !           321:     return;
        !           322: }
        !           323: 
        !           324: static inline int
        !           325: i596_rx(struct device *dev)
        !           326: {
        !           327:     struct i596_private *lp = (struct i596_private *)dev->priv;
        !           328:     int frames = 0;
        !           329: 
        !           330:     if (i596_debug > 3) printk ("i596_rx()\n");
        !           331: 
        !           332:     while ((lp->scb.rfd->stat) & STAT_C)
        !           333:     {
        !           334:         if (i596_debug >2) print_eth(lp->scb.rfd->data);
        !           335: 
        !           336:        if ((lp->scb.rfd->stat) & STAT_OK)
        !           337:        {
        !           338:            /* a good frame */
        !           339:            int pkt_len = lp->scb.rfd->count & 0x3fff;
        !           340:            struct sk_buff *skb = dev_alloc_skb(pkt_len);
        !           341: 
        !           342:            frames++;
        !           343: 
        !           344:            if (skb == NULL)
        !           345:            {
        !           346:                printk ("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name);
        !           347:                lp->stats.rx_dropped++;
        !           348:                break;
        !           349:            }
        !           350: 
        !           351:            skb->dev = dev;             
        !           352:            memcpy(skb_put(skb,pkt_len), lp->scb.rfd->data, pkt_len);
        !           353: 
        !           354:            skb->protocol=eth_type_trans(skb,dev);
        !           355:            netif_rx(skb);
        !           356:            lp->stats.rx_packets++;
        !           357: 
        !           358:            if (i596_debug > 4) print_eth(skb->data);
        !           359:        }
        !           360:        else
        !           361:        {
        !           362:            lp->stats.rx_errors++;
        !           363:            if ((lp->scb.rfd->stat) & 0x0001) lp->stats.collisions++;
        !           364:            if ((lp->scb.rfd->stat) & 0x0080) lp->stats.rx_length_errors++;
        !           365:            if ((lp->scb.rfd->stat) & 0x0100) lp->stats.rx_over_errors++;
        !           366:            if ((lp->scb.rfd->stat) & 0x0200) lp->stats.rx_fifo_errors++;
        !           367:            if ((lp->scb.rfd->stat) & 0x0400) lp->stats.rx_frame_errors++;
        !           368:            if ((lp->scb.rfd->stat) & 0x0800) lp->stats.rx_crc_errors++;
        !           369:            if ((lp->scb.rfd->stat) & 0x1000) lp->stats.rx_length_errors++;
        !           370:        }
        !           371: 
        !           372:        lp->scb.rfd->stat = 0;
        !           373:        lp->rx_tail->cmd = 0;
        !           374:        lp->rx_tail = lp->scb.rfd;
        !           375:        lp->scb.rfd = lp->scb.rfd->next;
        !           376:        lp->rx_tail->count = 0;
        !           377:        lp->rx_tail->cmd = CMD_EOL;
        !           378: 
        !           379:     }
        !           380: 
        !           381:     if (i596_debug > 3) printk ("frames %d\n", frames);
        !           382: 
        !           383:     return 0;
        !           384: }
        !           385: 
        !           386: static inline void
        !           387: i596_cleanup_cmd(struct i596_private *lp)
        !           388: {
        !           389:     struct i596_cmd *ptr;
        !           390:     int boguscnt = 100;
        !           391: 
        !           392:     if (i596_debug > 4) printk ("i596_cleanup_cmd\n");
        !           393: 
        !           394:     while (lp->cmd_head != (struct i596_cmd *) I596_NULL)
        !           395:     {
        !           396:        ptr = lp->cmd_head;
        !           397: 
        !           398:        lp->cmd_head = lp->cmd_head->next;
        !           399:        lp->cmd_backlog--;
        !           400: 
        !           401:        switch ((ptr->command) & 0x7)
        !           402:        {
        !           403:            case CmdTx:
        !           404:            {
        !           405:                struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
        !           406:                struct sk_buff *skb = ((struct sk_buff *)(tx_cmd->tbd->data)) -1;
        !           407: 
        !           408:                dev_kfree_skb(skb, FREE_WRITE);
        !           409: 
        !           410:                lp->stats.tx_errors++;
        !           411:                lp->stats.tx_aborted_errors++;
        !           412: 
        !           413:                ptr->next = (struct i596_cmd * ) I596_NULL;
        !           414:                kfree_s((unsigned char *)tx_cmd, (sizeof (struct tx_cmd) + sizeof (struct i596_tbd)));
        !           415:                break;
        !           416:            }
        !           417:            case CmdMulticastList:
        !           418:            {
        !           419:                unsigned short count = *((unsigned short *) (ptr + 1));
        !           420: 
        !           421:                ptr->next = (struct i596_cmd * ) I596_NULL;
        !           422:                kfree_s((unsigned char *)ptr, (sizeof (struct i596_cmd) + count + 2));
        !           423:                break;
        !           424:            }
        !           425:            default:
        !           426:                ptr->next = (struct i596_cmd * ) I596_NULL;
        !           427:        }
        !           428:     }
        !           429: 
        !           430:     while (lp->scb.status, lp->scb.command)
        !           431:        if (--boguscnt == 0)
        !           432:        {
        !           433:            printk("i596_cleanup_cmd timed out with status %4.4x, cmd %4.4x.\n",
        !           434:                lp->scb.status, lp->scb.command);
        !           435:            break;
        !           436:        }
        !           437: 
        !           438:     lp->scb.cmd = lp->cmd_head;
        !           439: }
        !           440: 
        !           441: static inline void
        !           442: i596_reset(struct device *dev, struct i596_private *lp, int ioaddr)
        !           443: {
        !           444:     int boguscnt = 100;
        !           445: 
        !           446:     if (i596_debug > 4) printk ("i596_reset\n");
        !           447: 
        !           448:     while (lp->scb.status, lp->scb.command)
        !           449:         if (--boguscnt == 0)
        !           450:        {
        !           451:            printk("i596_reset timed out with status %4.4x, cmd %4.4x.\n",
        !           452:                lp->scb.status, lp->scb.command);
        !           453:            break;
        !           454:        }
        !           455: 
        !           456:     dev->start = 0;
        !           457:     dev->tbusy = 1;
        !           458: 
        !           459:     lp->scb.command = CUC_ABORT|RX_ABORT;
        !           460:     outw(0, ioaddr+4);
        !           461: 
        !           462:     /* wait for shutdown */
        !           463:     boguscnt = 400;
        !           464: 
        !           465:     while ((lp->scb.status, lp->scb.command) || lp->scb.command)
        !           466:         if (--boguscnt == 0)
        !           467:        {
        !           468:            printk("i596_reset 2 timed out with status %4.4x, cmd %4.4x.\n",
        !           469:                lp->scb.status, lp->scb.command);
        !           470:            break;
        !           471:        }
        !           472: 
        !           473:     i596_cleanup_cmd(lp);
        !           474:     i596_rx(dev);
        !           475: 
        !           476:     dev->start = 1;
        !           477:     dev->tbusy = 0;
        !           478:     dev->interrupt = 0;
        !           479:     init_i596_mem(dev);
        !           480: }
        !           481: 
        !           482: static void i596_add_cmd(struct device *dev, struct i596_cmd *cmd)
        !           483: {
        !           484:     struct i596_private *lp = (struct i596_private *)dev->priv;
        !           485:     int ioaddr = dev->base_addr;
        !           486:     unsigned long flags;
        !           487:     int boguscnt = 100;
        !           488: 
        !           489:     if (i596_debug > 4) printk ("i596_add_cmd\n");
        !           490: 
        !           491:     cmd->status = 0;
        !           492:     cmd->command |= (CMD_EOL|CMD_INTR);
        !           493:     cmd->next = (struct i596_cmd *) I596_NULL;
        !           494: 
        !           495:     save_flags(flags);
        !           496:     cli();
        !           497:     if (lp->cmd_head != (struct i596_cmd *) I596_NULL)
        !           498:        lp->cmd_tail->next = cmd;
        !           499:     else 
        !           500:     {
        !           501:        lp->cmd_head = cmd;
        !           502:        while (lp->scb.status, lp->scb.command)
        !           503:            if (--boguscnt == 0)
        !           504:            {
        !           505:                printk("i596_add_cmd timed out with status %4.4x, cmd %4.4x.\n",
        !           506:                   lp->scb.status, lp->scb.command);
        !           507:                break;
        !           508:            }
        !           509: 
        !           510:        lp->scb.cmd = cmd;
        !           511:        lp->scb.command = CUC_START;
        !           512:         outw (0, ioaddr+4);
        !           513:     }
        !           514:     lp->cmd_tail = cmd;
        !           515:     lp->cmd_backlog++;
        !           516: 
        !           517:     lp->cmd_head = lp->scb.cmd;
        !           518:     restore_flags(flags);
        !           519: 
        !           520:     if (lp->cmd_backlog > 16) 
        !           521:     {
        !           522:        int tickssofar = jiffies - lp->last_cmd;
        !           523: 
        !           524:        if (tickssofar < 25) return;
        !           525: 
        !           526:        printk("%s: command unit timed out, status resetting.\n", dev->name);
        !           527: 
        !           528:        i596_reset(dev, lp, ioaddr);
        !           529:     }
        !           530: }
        !           531: 
        !           532: static int
        !           533: i596_open(struct device *dev)
        !           534: {
        !           535:     int i;
        !           536: 
        !           537:     if (i596_debug > 1)
        !           538:        printk("%s: i596_open() irq %d.\n", dev->name, dev->irq);
        !           539: 
        !           540:     if (request_irq(dev->irq, &i596_interrupt, 0, "apricot", NULL))
        !           541:        return -EAGAIN;
        !           542: 
        !           543:     irq2dev_map[dev->irq] = dev;
        !           544: 
        !           545:     i = init_rx_bufs(dev, RX_RING_SIZE);
        !           546: 
        !           547:     if ((i = init_rx_bufs(dev, RX_RING_SIZE)) < RX_RING_SIZE)
        !           548:         printk("%s: only able to allocate %d receive buffers\n", dev->name, i);
        !           549: 
        !           550:     if (i < 4)
        !           551:     {
        !           552:         free_irq(dev->irq, NULL);
        !           553:         irq2dev_map[dev->irq] = 0;
        !           554:         return -EAGAIN;
        !           555:     }
        !           556: 
        !           557:     dev->tbusy = 0;
        !           558:     dev->interrupt = 0;
        !           559:     dev->start = 1;
        !           560:     MOD_INC_USE_COUNT;
        !           561: 
        !           562:     /* Initialize the 82596 memory */
        !           563:     init_i596_mem(dev);
        !           564: 
        !           565:     return 0;                  /* Always succeed */
        !           566: }
        !           567: 
        !           568: static int
        !           569: i596_start_xmit(struct sk_buff *skb, struct device *dev)
        !           570: {
        !           571:     struct i596_private *lp = (struct i596_private *)dev->priv;
        !           572:     int ioaddr = dev->base_addr;
        !           573:     struct tx_cmd *tx_cmd;
        !           574: 
        !           575:     if (i596_debug > 2) printk ("%s: Apricot start xmit\n", dev->name);
        !           576: 
        !           577:     /* Transmitter timeout, serious problems. */
        !           578:     if (dev->tbusy) {
        !           579:        int tickssofar = jiffies - dev->trans_start;
        !           580:        if (tickssofar < 5)
        !           581:            return 1;
        !           582:        printk("%s: transmit timed out, status resetting.\n",
        !           583:               dev->name);
        !           584:        lp->stats.tx_errors++;
        !           585:        /* Try to restart the adaptor */
        !           586:        if (lp->last_restart == lp->stats.tx_packets) {
        !           587:            if (i596_debug > 1) printk ("Resetting board.\n");
        !           588: 
        !           589:            /* Shutdown and restart */
        !           590:             i596_reset(dev,lp, ioaddr);
        !           591:        } else {
        !           592:            /* Issue a channel attention signal */
        !           593:            if (i596_debug > 1) printk ("Kicking board.\n");
        !           594: 
        !           595:            lp->scb.command = CUC_START|RX_START;
        !           596:            outw(0, ioaddr+4);
        !           597: 
        !           598:            lp->last_restart = lp->stats.tx_packets;
        !           599:        }
        !           600:        dev->tbusy = 0;
        !           601:        dev->trans_start = jiffies;
        !           602:     }
        !           603: 
        !           604:     /* If some higher level thinks we've misses a tx-done interrupt
        !           605:        we are passed NULL. n.b. dev_tint handles the cli()/sti()
        !           606:        itself. */
        !           607:     if (skb == NULL) {
        !           608:        dev_tint(dev);
        !           609:        return 0;
        !           610:     }
        !           611: 
        !           612:     /* shouldn't happen */
        !           613:     if (skb->len <= 0) return 0;
        !           614: 
        !           615:     if (i596_debug > 3) printk("%s: i596_start_xmit() called\n", dev->name);
        !           616: 
        !           617:     /* Block a timer-based transmit from overlapping.  This could better be
        !           618:        done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
        !           619:     if (set_bit(0, (void*)&dev->tbusy) != 0)
        !           620:        printk("%s: Transmitter access conflict.\n", dev->name);
        !           621:     else
        !           622:     {
        !           623:        short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
        !           624:        dev->trans_start = jiffies;
        !           625: 
        !           626:        tx_cmd = (struct tx_cmd *) kmalloc ((sizeof (struct tx_cmd) + sizeof (struct i596_tbd)), GFP_ATOMIC);
        !           627:        if (tx_cmd == NULL)
        !           628:        {
        !           629:            printk ("%s: i596_xmit Memory squeeze, dropping packet.\n", dev->name);
        !           630:            lp->stats.tx_dropped++;
        !           631: 
        !           632:            dev_kfree_skb(skb, FREE_WRITE);
        !           633:        }
        !           634:        else
        !           635:        {
        !           636:            tx_cmd->tbd = (struct i596_tbd *) (tx_cmd + 1);
        !           637:            tx_cmd->tbd->next = (struct i596_tbd *) I596_NULL;
        !           638: 
        !           639:            tx_cmd->cmd.command = CMD_FLEX|CmdTx;
        !           640: 
        !           641:            tx_cmd->pad = 0;
        !           642:            tx_cmd->size = 0;
        !           643:            tx_cmd->tbd->pad = 0;
        !           644:            tx_cmd->tbd->size = EOF | length;
        !           645: 
        !           646:            tx_cmd->tbd->data = skb->data;
        !           647: 
        !           648:            if (i596_debug > 3) print_eth(skb->data);
        !           649: 
        !           650:            i596_add_cmd(dev, (struct i596_cmd *)tx_cmd);
        !           651: 
        !           652:            lp->stats.tx_packets++;
        !           653:        }
        !           654:     }
        !           655: 
        !           656:     dev->tbusy = 0;
        !           657: 
        !           658:     return 0;
        !           659: }
        !           660: 
        !           661: 
        !           662: static void print_eth(char *add)
        !           663: {
        !           664:     int i;
        !           665: 
        !           666:     printk ("Dest  ");
        !           667:     for (i = 0; i < 6; i++)
        !           668:        printk(" %2.2X", (unsigned char)add[i]);
        !           669:     printk ("\n");
        !           670: 
        !           671:     printk ("Source");
        !           672:     for (i = 0; i < 6; i++)
        !           673:        printk(" %2.2X", (unsigned char)add[i+6]);
        !           674:     printk ("\n");
        !           675:     printk ("type %2.2X%2.2X\n", (unsigned char)add[12], (unsigned char)add[13]);
        !           676: }
        !           677: 
        !           678: int apricot_probe(struct device *dev)
        !           679: {
        !           680:     int i;
        !           681:     struct i596_private *lp;
        !           682:     int checksum = 0;
        !           683:     int ioaddr = 0x300;
        !           684:     char eth_addr[6];
        !           685:     
        !           686:     /* this is easy the ethernet interface can only be at 0x300 */
        !           687:     /* first check nothing is already registered here */
        !           688: 
        !           689:     if (check_region(ioaddr, APRICOT_TOTAL_SIZE))
        !           690:        return ENODEV;
        !           691: 
        !           692:     for (i = 0; i < 8; i++)
        !           693:     {
        !           694:        eth_addr[i] = inb(ioaddr+8+i);
        !           695:        checksum += eth_addr[i];
        !           696:      }
        !           697: 
        !           698:     /* checksum is a multiple of 0x100, got this wrong first time
        !           699:        some machines have 0x100, some 0x200. The DOS driver doesn't
        !           700:        even bother with the checksum */
        !           701: 
        !           702:     if (checksum % 0x100) return ENODEV;
        !           703: 
        !           704:     /* Some other boards trip the checksum.. but then appear as ether
        !           705:        address 0. Trap these - AC */
        !           706:        
        !           707:     if(memcmp(eth_addr,"\x00\x00\x49",3)!= 0)
        !           708:        return ENODEV;
        !           709: 
        !           710:     request_region(ioaddr, APRICOT_TOTAL_SIZE, "apricot");
        !           711: 
        !           712:     dev->base_addr = ioaddr;
        !           713:     ether_setup(dev);
        !           714:     printk("%s: Apricot 82596 at %#3x,", dev->name, ioaddr);
        !           715: 
        !           716:     for (i = 0; i < 6; i++)
        !           717:        printk(" %2.2X", dev->dev_addr[i] = eth_addr[i]);
        !           718: 
        !           719:     dev->base_addr = ioaddr;
        !           720:     dev->irq = 10;
        !           721:     printk(" IRQ %d.\n", dev->irq);
        !           722: 
        !           723:     if (i596_debug > 0) printk(version);
        !           724: 
        !           725:     /* The APRICOT-specific entries in the device structure. */
        !           726:     dev->open = &i596_open;
        !           727:     dev->stop = &i596_close;
        !           728:     dev->hard_start_xmit = &i596_start_xmit;
        !           729:     dev->get_stats = &i596_get_stats;
        !           730:     dev->set_multicast_list = &set_multicast_list;
        !           731: 
        !           732:     dev->mem_start = (int)kmalloc(sizeof(struct i596_private)+ 0x0f, GFP_KERNEL);
        !           733:     /* align for scp */
        !           734:     dev->priv = (void *)((dev->mem_start + 0xf) & 0xfffffff0);
        !           735: 
        !           736:     lp = (struct i596_private *)dev->priv;
        !           737:     memset((void *)lp, 0, sizeof(struct i596_private));
        !           738:     lp->scb.command = 0;
        !           739:     lp->scb.cmd = (struct i596_cmd *) I596_NULL;
        !           740:     lp->scb.rfd = (struct i596_rfd *)I596_NULL;
        !           741: 
        !           742:     return 0;
        !           743: }
        !           744: 
        !           745: static void
        !           746: i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        !           747: {
        !           748:     struct device *dev = (struct device *)(irq2dev_map[irq]);
        !           749:     struct i596_private *lp;
        !           750:     short ioaddr;
        !           751:     int boguscnt = 200;
        !           752:     unsigned short status, ack_cmd = 0;
        !           753: 
        !           754:     if (dev == NULL) {
        !           755:        printk ("i596_interrupt(): irq %d for unknown device.\n", irq);
        !           756:        return;
        !           757:     }
        !           758: 
        !           759:     if (i596_debug > 3) printk ("%s: i596_interrupt(): irq %d\n",dev->name, irq);
        !           760: 
        !           761:     if (dev->interrupt)
        !           762:        printk("%s: Re-entering the interrupt handler.\n", dev->name);
        !           763: 
        !           764:     dev->interrupt = 1;
        !           765: 
        !           766:     ioaddr = dev->base_addr;
        !           767: 
        !           768:     lp = (struct i596_private *)dev->priv;
        !           769: 
        !           770:     while (lp->scb.status, lp->scb.command)
        !           771:        if (--boguscnt == 0)
        !           772:            {
        !           773:                printk("%s: i596 interrupt, timeout status %4.4x command %4.4x.\n", dev->name, lp->scb.status, lp->scb.command);
        !           774:                break;
        !           775:            }
        !           776:     status = lp->scb.status;
        !           777: 
        !           778:     if (i596_debug > 4)
        !           779:        printk("%s: i596 interrupt, status %4.4x.\n", dev->name, status);
        !           780: 
        !           781:     ack_cmd = status & 0xf000;
        !           782: 
        !           783:     if ((status & 0x8000) || (status & 0x2000))
        !           784:     {
        !           785:        struct i596_cmd *ptr;
        !           786: 
        !           787:        if ((i596_debug > 4) && (status & 0x8000))
        !           788:            printk("%s: i596 interrupt completed command.\n", dev->name);
        !           789:        if ((i596_debug > 4) && (status & 0x2000))
        !           790:            printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700);
        !           791: 
        !           792:        while ((lp->cmd_head != (struct i596_cmd *) I596_NULL) && (lp->cmd_head->status & STAT_C))
        !           793:        {
        !           794:            ptr = lp->cmd_head;
        !           795: 
        !           796:            lp->cmd_head = lp->cmd_head->next;
        !           797:            lp->cmd_backlog--;
        !           798: 
        !           799:            switch ((ptr->command) & 0x7)
        !           800:            {
        !           801:                case CmdTx:
        !           802:                {
        !           803:                    struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
        !           804:                    struct sk_buff *skb = ((struct sk_buff *)(tx_cmd->tbd->data)) -1;
        !           805: 
        !           806:                    dev_kfree_skb(skb, FREE_WRITE);
        !           807: 
        !           808:                    if ((ptr->status) & STAT_OK)
        !           809:                    {
        !           810:                        if (i596_debug >2) print_eth(skb->data);
        !           811:                    }
        !           812:                    else
        !           813:                    {
        !           814:                        lp->stats.tx_errors++;
        !           815:                        if ((ptr->status) & 0x0020) lp->stats.collisions++;
        !           816:                        if (!((ptr->status) & 0x0040)) lp->stats.tx_heartbeat_errors++;
        !           817:                        if ((ptr->status) & 0x0400) lp->stats.tx_carrier_errors++;
        !           818:                        if ((ptr->status) & 0x0800) lp->stats.collisions++;
        !           819:                        if ((ptr->status) & 0x1000) lp->stats.tx_aborted_errors++;
        !           820:                    }
        !           821: 
        !           822: 
        !           823:                    ptr->next = (struct i596_cmd * ) I596_NULL;
        !           824:                    kfree_s((unsigned char *)tx_cmd, (sizeof (struct tx_cmd) + sizeof (struct i596_tbd)));
        !           825:                    break;
        !           826:                }
        !           827:                case CmdMulticastList:
        !           828:                {
        !           829:                    unsigned short count = *((unsigned short *) (ptr + 1));
        !           830: 
        !           831:                    ptr->next = (struct i596_cmd * ) I596_NULL;
        !           832:                    kfree_s((unsigned char *)ptr, (sizeof (struct i596_cmd) + count + 2));
        !           833:                    break;
        !           834:                }
        !           835:                case CmdTDR:
        !           836:                {
        !           837:                    unsigned long status = *((unsigned long *) (ptr + 1));
        !           838: 
        !           839:                    if (status & 0x8000)
        !           840:                    {
        !           841:                        if (i596_debug > 3)
        !           842:                            printk("%s: link ok.\n", dev->name);
        !           843:                    }
        !           844:                    else
        !           845:                    {
        !           846:                        if (status & 0x4000)
        !           847:                            printk("%s: Transceiver problem.\n", dev->name);
        !           848:                        if (status & 0x2000)
        !           849:                            printk("%s: Termination problem.\n", dev->name);
        !           850:                        if (status & 0x1000)
        !           851:                            printk("%s: Short circuit.\n", dev->name);
        !           852: 
        !           853:                        printk("%s: Time %ld.\n", dev->name, status & 0x07ff);
        !           854:                    }
        !           855:                }
        !           856:                default:
        !           857:                    ptr->next = (struct i596_cmd * ) I596_NULL;
        !           858: 
        !           859:                lp->last_cmd = jiffies;
        !           860:            }
        !           861:        }
        !           862: 
        !           863:        ptr = lp->cmd_head;
        !           864:        while ((ptr != (struct i596_cmd *) I596_NULL) && (ptr != lp->cmd_tail))
        !           865:        {
        !           866:            ptr->command &= 0x1fff;
        !           867:            ptr = ptr->next;
        !           868:        }
        !           869: 
        !           870:        if ((lp->cmd_head != (struct i596_cmd *) I596_NULL) && (dev->start)) ack_cmd |= CUC_START;
        !           871:        lp->scb.cmd = lp->cmd_head;
        !           872:     }
        !           873: 
        !           874:     if ((status & 0x1000) || (status & 0x4000))
        !           875:     {
        !           876:        if ((i596_debug > 4) && (status & 0x4000))
        !           877:            printk("%s: i596 interrupt received a frame.\n", dev->name);
        !           878:        if ((i596_debug > 4) && (status & 0x1000))
        !           879:            printk("%s: i596 interrupt receive unit inactive %x.\n", dev->name, status & 0x0070);
        !           880: 
        !           881:        i596_rx(dev);
        !           882: 
        !           883:        if (dev->start) ack_cmd |= RX_START;
        !           884:     }
        !           885: 
        !           886:     /* acknowledge the interrupt */
        !           887: 
        !           888: /*
        !           889:     if ((lp->scb.cmd != (struct i596_cmd *) I596_NULL) && (dev->start)) ack_cmd | = CUC_START;
        !           890: */
        !           891:     boguscnt = 100;
        !           892:     while (lp->scb.status, lp->scb.command)
        !           893:        if (--boguscnt == 0)
        !           894:            {
        !           895:                printk("%s: i596 interrupt, timeout status %4.4x command %4.4x.\n", dev->name, lp->scb.status, lp->scb.command);
        !           896:                break;
        !           897:            }
        !           898:     lp->scb.command = ack_cmd;
        !           899: 
        !           900:     (void) inb (ioaddr+0x10);
        !           901:     outb (4, ioaddr+0xf);
        !           902:     outw (0, ioaddr+4);
        !           903: 
        !           904:     if (i596_debug > 4)
        !           905:        printk("%s: exiting interrupt.\n", dev->name);
        !           906: 
        !           907:     dev->interrupt = 0;
        !           908:     return;
        !           909: }
        !           910: 
        !           911: static int
        !           912: i596_close(struct device *dev)
        !           913: {
        !           914:     int ioaddr = dev->base_addr;
        !           915:     struct i596_private *lp = (struct i596_private *)dev->priv;
        !           916:     int boguscnt = 200;
        !           917: 
        !           918:     dev->start = 0;
        !           919:     dev->tbusy = 1;
        !           920: 
        !           921:     if (i596_debug > 1)
        !           922:        printk("%s: Shutting down ethercard, status was %4.4x.\n",
        !           923:               dev->name, lp->scb.status);
        !           924: 
        !           925:     lp->scb.command = CUC_ABORT|RX_ABORT;
        !           926:     outw(0, ioaddr+4);
        !           927: 
        !           928:     i596_cleanup_cmd(lp);
        !           929: 
        !           930:     while (lp->scb.status, lp->scb.command)
        !           931:        if (--boguscnt == 0)
        !           932:        {
        !           933:            printk("%s: close timed out with status %4.4x, cmd %4.4x.\n",
        !           934:                   dev->name, lp->scb.status, lp->scb.command);
        !           935:            break;
        !           936:        }
        !           937:     free_irq(dev->irq, NULL);
        !           938:     irq2dev_map[dev->irq] = 0;
        !           939:     remove_rx_bufs(dev);
        !           940:     MOD_DEC_USE_COUNT;
        !           941: 
        !           942:     return 0;
        !           943: }
        !           944: 
        !           945: static struct enet_statistics *
        !           946: i596_get_stats(struct device *dev)
        !           947: {
        !           948:     struct i596_private *lp = (struct i596_private *)dev->priv;
        !           949: 
        !           950:     return &lp->stats;
        !           951: }
        !           952: 
        !           953: /*
        !           954:  *     Set or clear the multicast filter for this adaptor.
        !           955:  */
        !           956:  
        !           957: static void set_multicast_list(struct device *dev)
        !           958: {
        !           959:        struct i596_private *lp = (struct i596_private *)dev->priv;
        !           960:        struct i596_cmd *cmd;
        !           961: 
        !           962:        if (i596_debug > 1)
        !           963:                printk ("%s: set multicast list %d\n", dev->name, dev->mc_count);
        !           964: 
        !           965:        if (dev->mc_count > 0) 
        !           966:        {
        !           967:                struct dev_mc_list *dmi;
        !           968:                char *cp;
        !           969:                cmd = (struct i596_cmd *) kmalloc(sizeof(struct i596_cmd)+2+dev->mc_count*6, GFP_ATOMIC);
        !           970:                if (cmd == NULL)
        !           971:                {
        !           972:                        printk ("%s: set_multicast Memory squeeze.\n", dev->name);
        !           973:                        return;
        !           974:                }
        !           975:                cmd->command = CmdMulticastList;
        !           976:                *((unsigned short *) (cmd + 1)) = dev->mc_count * 6;
        !           977:                cp=((char *)(cmd + 1))+2;
        !           978:                for(dmi=dev->mc_list;dmi!=NULL;dmi=dmi->next)
        !           979:                {
        !           980:                        memcpy(cp, dmi,6);
        !           981:                        cp+=6;
        !           982:                }
        !           983:                print_eth (((char *)(cmd + 1)) + 2);
        !           984:                i596_add_cmd(dev, cmd);
        !           985:        }
        !           986:        else
        !           987:        {
        !           988:                if (lp->set_conf.next != (struct i596_cmd * ) I596_NULL) 
        !           989:                        return;
        !           990:                if (dev->mc_count == 0 && !(dev->flags&(IFF_PROMISC|IFF_ALLMULTI)))
        !           991:                {
        !           992:                        if(dev->flags&IFF_ALLMULTI)
        !           993:                                dev->flags|=IFF_PROMISC;
        !           994:                        lp->i596_config[8] &= ~0x01;
        !           995:                }
        !           996:                else
        !           997:                        lp->i596_config[8] |= 0x01;
        !           998: 
        !           999:                i596_add_cmd(dev, &lp->set_conf);
        !          1000:        }
        !          1001: }
        !          1002: 
        !          1003: #ifdef HAVE_DEVLIST
        !          1004: static unsigned int apricot_portlist[] = {0x300, 0};
        !          1005: struct netdev_entry apricot_drv = 
        !          1006: {"apricot", apricot_probe, APRICOT_TOTAL_SIZE, apricot_portlist};
        !          1007: #endif
        !          1008: 
        !          1009: #ifdef MODULE
        !          1010: static char devicename[9] = { 0, };
        !          1011: static struct device dev_apricot = {
        !          1012:   devicename, /* device name inserted by /linux/drivers/net/net_init.c */
        !          1013:   0, 0, 0, 0,
        !          1014:   0x300, 10,
        !          1015:   0, 0, 0, NULL, apricot_probe };
        !          1016: 
        !          1017: static int io = 0x300;
        !          1018: static int irq = 10;
        !          1019: 
        !          1020: int
        !          1021: init_module(void)
        !          1022: {
        !          1023:   dev_apricot.base_addr = io;
        !          1024:   dev_apricot.irq       = irq;
        !          1025:   if (register_netdev(&dev_apricot) != 0)
        !          1026:     return -EIO;
        !          1027:   return 0;
        !          1028: }
        !          1029: 
        !          1030: void
        !          1031: cleanup_module(void)
        !          1032: {
        !          1033:     unregister_netdev(&dev_apricot);
        !          1034:     kfree_s((void *)dev_apricot.mem_start, sizeof(struct i596_private) + 0xf);
        !          1035:     dev_apricot.priv = NULL;
        !          1036: 
        !          1037:     /* If we don't do this, we can't re-insmod it later. */
        !          1038:     release_region(dev_apricot.base_addr, APRICOT_TOTAL_SIZE);
        !          1039: }
        !          1040: #endif /* MODULE */
        !          1041: 
        !          1042: /*
        !          1043:  * Local variables:
        !          1044:  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c apricot.c"
        !          1045:  * End:
        !          1046:  */

unix.superglobalmegacorp.com

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