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

1.1     ! root        1: /* seeq8005.c: A network driver for linux. */
        !             2: /*
        !             3:        Based on skeleton.c,
        !             4:        Written 1993-94 by Donald Becker.
        !             5:        See the skeleton.c file for further copyright information.
        !             6: 
        !             7:        This software may be used and distributed according to the terms
        !             8:        of the GNU Public License, incorporated herein by reference.
        !             9: 
        !            10:        The author may be reached as [email protected]
        !            11: 
        !            12:        This file is a network device driver for the SEEQ 8005 chipset and
        !            13:        the Linux operating system.
        !            14: 
        !            15: */
        !            16: 
        !            17: static const char *version =
        !            18:        "seeq8005.c:v1.00 8/07/95 Hamish Coleman ([email protected])\n";
        !            19: 
        !            20: /*
        !            21:   Sources:
        !            22:        SEEQ 8005 databook
        !            23:        
        !            24:   Version history:
        !            25:        1.00    Public release. cosmetic changes (no warnings now)
        !            26:        0.68    Turning per- packet,interrupt debug messages off - testing for release.
        !            27:        0.67    timing problems/bad buffer reads seem to be fixed now
        !            28:        0.63    *!@$ protocol=eth_type_trans -- now packets flow
        !            29:        0.56    Send working
        !            30:        0.48    Receive working
        !            31: */
        !            32: 
        !            33: #include <linux/kernel.h>
        !            34: #include <linux/sched.h>
        !            35: #include <linux/types.h>
        !            36: #include <linux/fcntl.h>
        !            37: #include <linux/interrupt.h>
        !            38: #include <linux/ptrace.h>
        !            39: #include <linux/ioport.h>
        !            40: #include <linux/in.h>
        !            41: #include <linux/malloc.h>
        !            42: #include <linux/string.h>
        !            43: #include <asm/system.h>
        !            44: #include <asm/bitops.h>
        !            45: #include <asm/io.h>
        !            46: #include <asm/dma.h>
        !            47: #include <linux/errno.h>
        !            48: 
        !            49: #include <linux/netdevice.h>
        !            50: #include <linux/etherdevice.h>
        !            51: #include <linux/skbuff.h>
        !            52: #include "seeq8005.h"
        !            53: 
        !            54: /* First, a few definitions that the brave might change. */
        !            55: /* A zero-terminated list of I/O addresses to be probed. */
        !            56: static unsigned int seeq8005_portlist[] =
        !            57:    { 0x300, 0x320, 0x340, 0x360, 0};
        !            58: 
        !            59: /* use 0 for production, 1 for verification, >2 for debug */
        !            60: #ifndef NET_DEBUG
        !            61: #define NET_DEBUG 1
        !            62: #endif
        !            63: static unsigned int net_debug = NET_DEBUG;
        !            64: 
        !            65: /* Information that need to be kept for each board. */
        !            66: struct net_local {
        !            67:        struct enet_statistics stats;
        !            68:        unsigned short receive_ptr;             /* What address in packet memory do we expect a recv_pkt_header? */
        !            69:        long open_time;                         /* Useless example local info. */
        !            70: };
        !            71: 
        !            72: /* The station (ethernet) address prefix, used for IDing the board. */
        !            73: #define SA_ADDR0 0x00
        !            74: #define SA_ADDR1 0x80
        !            75: #define SA_ADDR2 0x4b
        !            76: 
        !            77: /* Index to functions, as function prototypes. */
        !            78: 
        !            79: extern int seeq8005_probe(struct device *dev);
        !            80: 
        !            81: static int seeq8005_probe1(struct device *dev, int ioaddr);
        !            82: static int seeq8005_open(struct device *dev);
        !            83: static int seeq8005_send_packet(struct sk_buff *skb, struct device *dev);
        !            84: static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs *regs);
        !            85: static void seeq8005_rx(struct device *dev);
        !            86: static int seeq8005_close(struct device *dev);
        !            87: static struct enet_statistics *seeq8005_get_stats(struct device *dev);
        !            88: static void set_multicast_list(struct device *dev);
        !            89: 
        !            90: /* Example routines you must write ;->. */
        !            91: #define tx_done(dev)   (inw(SEEQ_STATUS) & SEEQSTAT_TX_ON)
        !            92: extern void hardware_send_packet(struct device *dev, char *buf, int length);
        !            93: extern void seeq8005_init(struct device *dev, int startp);
        !            94: inline void wait_for_buffer(struct device *dev);
        !            95: 
        !            96: 
        !            97: /* Check for a network adaptor of this type, and return '0' iff one exists.
        !            98:    If dev->base_addr == 0, probe all likely locations.
        !            99:    If dev->base_addr == 1, always return failure.
        !           100:    If dev->base_addr == 2, allocate space for the device and return success
        !           101:    (detachable devices only).
        !           102:    */
        !           103: #ifdef HAVE_DEVLIST
        !           104: /* Support for a alternate probe manager, which will eliminate the
        !           105:    boilerplate below. */
        !           106: struct netdev_entry seeq8005_drv =
        !           107: {"seeq8005", seeq8005_probe1, SEEQ8005_IO_EXTENT, seeq8005_portlist};
        !           108: #else
        !           109: int
        !           110: seeq8005_probe(struct device *dev)
        !           111: {
        !           112:        int i;
        !           113:        int base_addr = dev ? dev->base_addr : 0;
        !           114: 
        !           115:        if (base_addr > 0x1ff)          /* Check a single specified location. */
        !           116:                return seeq8005_probe1(dev, base_addr);
        !           117:        else if (base_addr != 0)        /* Don't probe at all. */
        !           118:                return ENXIO;
        !           119: 
        !           120:        for (i = 0; seeq8005_portlist[i]; i++) {
        !           121:                int ioaddr = seeq8005_portlist[i];
        !           122:                if (check_region(ioaddr, SEEQ8005_IO_EXTENT))
        !           123:                        continue;
        !           124:                if (seeq8005_probe1(dev, ioaddr) == 0)
        !           125:                        return 0;
        !           126:        }
        !           127: 
        !           128:        return ENODEV;
        !           129: }
        !           130: #endif
        !           131: 
        !           132: /* This is the real probe routine.  Linux has a history of friendly device
        !           133:    probes on the ISA bus.  A good device probes avoids doing writes, and
        !           134:    verifies that the correct device exists and functions.  */
        !           135: 
        !           136: static int seeq8005_probe1(struct device *dev, int ioaddr)
        !           137: {
        !           138:        static unsigned version_printed = 0;
        !           139:        int i,j;
        !           140:        unsigned char SA_prom[32];
        !           141:        int old_cfg1;
        !           142:        int old_cfg2;
        !           143:        int old_stat;
        !           144:        int old_dmaar;
        !           145:        int old_rear;
        !           146: 
        !           147:        if (net_debug>1)
        !           148:                printk("seeq8005: probing at 0x%x\n",ioaddr);
        !           149: 
        !           150:        old_stat = inw(SEEQ_STATUS);                                    /* read status register */
        !           151:        if (old_stat == 0xffff)
        !           152:                return ENODEV;                                          /* assume that 0xffff == no device */
        !           153:        if ( (old_stat & 0x1800) != 0x1800 ) {                          /* assume that unused bits are 1, as my manual says */
        !           154:                if (net_debug>1) {
        !           155:                        printk("seeq8005: reserved stat bits != 0x1800\n");
        !           156:                        printk("          == 0x%04x\n",old_stat);
        !           157:                }
        !           158:                return ENODEV;
        !           159:        }
        !           160: 
        !           161:        old_rear = inw(SEEQ_REA);
        !           162:        if (old_rear == 0xffff) {
        !           163:                outw(0,SEEQ_REA);
        !           164:                if (inw(SEEQ_REA) == 0xffff) {                          /* assume that 0xffff == no device */
        !           165:                        return ENODEV;
        !           166:                }
        !           167:        } else if ((old_rear & 0xff00) != 0xff00) {                     /* assume that unused bits are 1 */
        !           168:                if (net_debug>1) {
        !           169:                        printk("seeq8005: unused rear bits != 0xff00\n");
        !           170:                        printk("          == 0x%04x\n",old_rear);
        !           171:                }
        !           172:                return ENODEV;
        !           173:        }
        !           174:        
        !           175:        old_cfg2 = inw(SEEQ_CFG2);                                      /* read CFG2 register */
        !           176:        old_cfg1 = inw(SEEQ_CFG1);
        !           177:        old_dmaar = inw(SEEQ_DMAAR);
        !           178:        
        !           179:        if (net_debug>4) {
        !           180:                printk("seeq8005: stat = 0x%04x\n",old_stat);
        !           181:                printk("seeq8005: cfg1 = 0x%04x\n",old_cfg1);
        !           182:                printk("seeq8005: cfg2 = 0x%04x\n",old_cfg2);
        !           183:                printk("seeq8005: raer = 0x%04x\n",old_rear);
        !           184:                printk("seeq8005: dmaar= 0x%04x\n",old_dmaar);
        !           185:        }
        !           186:        
        !           187:        outw( SEEQCMD_FIFO_WRITE | SEEQCMD_SET_ALL_OFF, SEEQ_CMD);      /* setup for reading PROM */
        !           188:        outw( 0, SEEQ_DMAAR);                                           /* set starting PROM address */
        !           189:        outw( SEEQCFG1_BUFFER_PROM, SEEQ_CFG1);                         /* set buffer to look at PROM */
        !           190:        
        !           191:        
        !           192:        j=0;
        !           193:        for(i=0; i <32; i++) {
        !           194:                j+= SA_prom[i] = inw(SEEQ_BUFFER) & 0xff;
        !           195:        }
        !           196: 
        !           197: #if 0
        !           198:        /* untested because I only have the one card */
        !           199:        if ( (j&0xff) != 0 ) {                                          /* checksum appears to be 8bit = 0 */
        !           200:                if (net_debug>1) {                                      /* check this before deciding that we have a card */
        !           201:                        printk("seeq8005: prom sum error\n");
        !           202:                }
        !           203:                outw( old_stat, SEEQ_STATUS);
        !           204:                outw( old_dmaar, SEEQ_DMAAR);
        !           205:                outw( old_cfg1, SEEQ_CFG1);
        !           206:                return ENODEV;
        !           207:        }
        !           208: #endif
        !           209: 
        !           210:        outw( SEEQCFG2_RESET, SEEQ_CFG2);                               /* reset the card */
        !           211:        SLOW_DOWN_IO;                                                   /* have to wait 4us after a reset - should be fixed */
        !           212:        SLOW_DOWN_IO;
        !           213:        SLOW_DOWN_IO;
        !           214:        SLOW_DOWN_IO;
        !           215:        outw( SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
        !           216:        
        !           217:        if (net_debug) {
        !           218:                printk("seeq8005: prom sum = 0x%08x\n",j);
        !           219:                for(j=0; j<32; j+=16) {
        !           220:                        printk("seeq8005: prom %02x: ",j);
        !           221:                        for(i=0;i<16;i++) {
        !           222:                                printk("%02x ",SA_prom[j|i]);
        !           223:                        }
        !           224:                        printk(" ");
        !           225:                        for(i=0;i<16;i++) {
        !           226:                                if ((SA_prom[j|i]>31)&&(SA_prom[j|i]<127)) {
        !           227:                                        printk("%c", SA_prom[j|i]);
        !           228:                                } else {
        !           229:                                        printk(" ");
        !           230:                                }
        !           231:                        }
        !           232:                        printk("\n");
        !           233:                }
        !           234:        }
        !           235: 
        !           236: #if 0  
        !           237:        /* 
        !           238:         * testing the packet buffer memory doesn't work yet
        !           239:         * but all other buffer accesses do 
        !           240:         *                      - fixing is not a priority
        !           241:         */
        !           242:        if (net_debug>1) {                                      /* test packet buffer memory */
        !           243:                printk("seeq8005: testing packet buffer ... ");
        !           244:                outw( SEEQCFG1_BUFFER_BUFFER, SEEQ_CFG1);
        !           245:                outw( SEEQCMD_FIFO_WRITE | SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
        !           246:                outw( 0 , SEEQ_DMAAR);
        !           247:                for(i=0;i<32768;i++) {
        !           248:                        outw(0x5a5a, SEEQ_BUFFER);
        !           249:                }
        !           250:                j=jiffies+HZ;
        !           251:                while ( ((inw(SEEQ_STATUS) & SEEQSTAT_FIFO_EMPTY) != SEEQSTAT_FIFO_EMPTY) && jiffies < j )
        !           252:                        mb();
        !           253:                outw( 0 , SEEQ_DMAAR);
        !           254:                while ( ((inw(SEEQ_STATUS) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && jiffies < j+HZ)
        !           255:                        mb();
        !           256:                if ( (inw(SEEQ_STATUS) & SEEQSTAT_WINDOW_INT) == SEEQSTAT_WINDOW_INT)
        !           257:                        outw( SEEQCMD_WINDOW_INT_ACK | (inw(SEEQ_STATUS)& SEEQCMD_INT_MASK), SEEQ_CMD);
        !           258:                outw( SEEQCMD_FIFO_READ | SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
        !           259:                j=0;
        !           260:                for(i=0;i<32768;i++) {
        !           261:                        if (inw(SEEQ_BUFFER) != 0x5a5a)
        !           262:                                j++;
        !           263:                }
        !           264:                if (j) {
        !           265:                        printk("%i\n",j);
        !           266:                } else {
        !           267:                        printk("ok.\n");
        !           268:                }
        !           269:        }
        !           270: #endif
        !           271: 
        !           272:        /* Allocate a new 'dev' if needed. */
        !           273:        if (dev == NULL)
        !           274:                dev = init_etherdev(0, sizeof(struct net_local));
        !           275: 
        !           276:        if (net_debug  &&  version_printed++ == 0)
        !           277:                printk(version);
        !           278: 
        !           279:        printk("%s: %s found at %#3x, ", dev->name, "seeq8005", ioaddr);
        !           280: 
        !           281:        /* Fill in the 'dev' fields. */
        !           282:        dev->base_addr = ioaddr;
        !           283: 
        !           284:        /* Retrieve and print the ethernet address. */
        !           285:        for (i = 0; i < 6; i++)
        !           286:                printk(" %2.2x", dev->dev_addr[i] = SA_prom[i+6]);
        !           287: 
        !           288:        if (dev->irq == 0xff)
        !           289:                ;                       /* Do nothing: a user-level program will set it. */
        !           290:        else if (dev->irq < 2) {        /* "Auto-IRQ" */
        !           291:                autoirq_setup(0);
        !           292:                
        !           293:                outw( SEEQCMD_RX_INT_EN | SEEQCMD_SET_RX_ON | SEEQCMD_SET_RX_OFF, SEEQ_CMD );
        !           294: 
        !           295:                dev->irq = autoirq_report(0);
        !           296:                
        !           297:                if (net_debug >= 2)
        !           298:                        printk(" autoirq is %d\n", dev->irq);
        !           299:        } else if (dev->irq == 2)
        !           300:          /* Fixup for users that don't know that IRQ 2 is really IRQ 9,
        !           301:           * or don't know which one to set. 
        !           302:           */
        !           303:          dev->irq = 9;
        !           304: 
        !           305: #if 0
        !           306:        {
        !           307:                 int irqval = request_irq(dev->irq, &seeq8005_interrupt, 0, "seeq8005", NULL);
        !           308:                 if (irqval) {
        !           309:                         printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
        !           310:                                         dev->irq, irqval);
        !           311:                         return EAGAIN;
        !           312:                 }
        !           313:        }
        !           314: #endif
        !           315: 
        !           316:        /* Grab the region so we can find another board if autoIRQ fails. */
        !           317:        request_region(ioaddr, SEEQ8005_IO_EXTENT,"seeq8005");
        !           318: 
        !           319:        /* Initialize the device structure. */
        !           320:        dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
        !           321:        if (dev->priv == NULL)
        !           322:                return -ENOMEM;
        !           323:        memset(dev->priv, 0, sizeof(struct net_local));
        !           324: 
        !           325:        dev->open               = seeq8005_open;
        !           326:        dev->stop               = seeq8005_close;
        !           327:        dev->hard_start_xmit = seeq8005_send_packet;
        !           328:        dev->get_stats  = seeq8005_get_stats;
        !           329:        dev->set_multicast_list = &set_multicast_list;
        !           330: 
        !           331:        /* Fill in the fields of the device structure with ethernet values. */
        !           332:        ether_setup(dev);
        !           333:        
        !           334:        dev->flags &= ~IFF_MULTICAST;
        !           335: 
        !           336:        return 0;
        !           337: }
        !           338: 
        !           339: 
        !           340: /* Open/initialize the board.  This is called (in the current kernel)
        !           341:    sometime after booting when the 'ifconfig' program is run.
        !           342: 
        !           343:    This routine should set everything up anew at each open, even
        !           344:    registers that "should" only need to be set once at boot, so that
        !           345:    there is non-reboot way to recover if something goes wrong.
        !           346:    */
        !           347: static int
        !           348: seeq8005_open(struct device *dev)
        !           349: {
        !           350:        struct net_local *lp = (struct net_local *)dev->priv;
        !           351: 
        !           352:        {
        !           353:                 int irqval = request_irq(dev->irq, &seeq8005_interrupt, 0, "seeq8005", NULL);
        !           354:                 if (irqval) {
        !           355:                         printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
        !           356:                                         dev->irq, irqval);
        !           357:                         return EAGAIN;
        !           358:                 }
        !           359:        }
        !           360:        irq2dev_map[dev->irq] = dev;
        !           361: 
        !           362:        /* Reset the hardware here.  Don't forget to set the station address. */
        !           363:        seeq8005_init(dev, 1);
        !           364: 
        !           365:        lp->open_time = jiffies;
        !           366: 
        !           367:        dev->tbusy = 0;
        !           368:        dev->interrupt = 0;
        !           369:        dev->start = 1;
        !           370:        return 0;
        !           371: }
        !           372: 
        !           373: static int
        !           374: seeq8005_send_packet(struct sk_buff *skb, struct device *dev)
        !           375: {
        !           376:        int ioaddr = dev->base_addr;
        !           377: 
        !           378:        if (dev->tbusy) {
        !           379:                /* If we get here, some higher level has decided we are broken.
        !           380:                   There should really be a "kick me" function call instead. */
        !           381:                int tickssofar = jiffies - dev->trans_start;
        !           382:                if (tickssofar < 5)
        !           383:                        return 1;
        !           384:                printk("%s: transmit timed out, %s?\n", dev->name,
        !           385:                           tx_done(dev) ? "IRQ conflict" : "network cable problem");
        !           386:                /* Try to restart the adaptor. */
        !           387:                seeq8005_init(dev, 1);
        !           388:                dev->tbusy=0;
        !           389:                dev->trans_start = jiffies;
        !           390:        }
        !           391: 
        !           392:        /* If some higher layer thinks we've missed an tx-done interrupt
        !           393:           we are passed NULL. Caution: dev_tint() handles the cli()/sti()
        !           394:           itself. */
        !           395:        if (skb == NULL) {
        !           396:                dev_tint(dev);
        !           397:                return 0;
        !           398:        }
        !           399: 
        !           400:        /* Block a timer-based transmit from overlapping.  This could better be
        !           401:           done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
        !           402:        if (set_bit(0, (void*)&dev->tbusy) != 0)
        !           403:                printk("%s: Transmitter access conflict.\n", dev->name);
        !           404:        else {
        !           405:                short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
        !           406:                unsigned char *buf = skb->data;
        !           407: 
        !           408:                hardware_send_packet(dev, buf, length); 
        !           409:                dev->trans_start = jiffies;
        !           410:        }
        !           411:        dev_kfree_skb (skb, FREE_WRITE);
        !           412: 
        !           413:        /* You might need to clean up and record Tx statistics here. */
        !           414: 
        !           415:        return 0;
        !           416: }
        !           417: 
        !           418: /* The typical workload of the driver:
        !           419:    Handle the network interface interrupts. */
        !           420: static void
        !           421: seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs)
        !           422: {
        !           423:        struct device *dev = (struct device *)(irq2dev_map[irq]);
        !           424:        struct net_local *lp;
        !           425:        int ioaddr, status, boguscount = 0;
        !           426: 
        !           427:        if (dev == NULL) {
        !           428:                printk ("net_interrupt(): irq %d for unknown device.\n", irq);
        !           429:                return;
        !           430:        }
        !           431:        
        !           432:        if (dev->interrupt)
        !           433:                printk ("%s: Re-entering the interrupt handler.\n", dev->name);
        !           434:        dev->interrupt = 1;
        !           435: 
        !           436:        ioaddr = dev->base_addr;
        !           437:        lp = (struct net_local *)dev->priv;
        !           438: 
        !           439:        status = inw(SEEQ_STATUS);
        !           440:        do {
        !           441:                if (net_debug >2) {
        !           442:                        printk("%s: int, status=0x%04x\n",dev->name,status);
        !           443:                }
        !           444:                
        !           445:                if (status & SEEQSTAT_WINDOW_INT) {
        !           446:                        outw( SEEQCMD_WINDOW_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
        !           447:                        if (net_debug) {
        !           448:                                printk("%s: window int!\n",dev->name);
        !           449:                        }
        !           450:                }
        !           451:                if (status & SEEQSTAT_TX_INT) {
        !           452:                        outw( SEEQCMD_TX_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
        !           453:                        lp->stats.tx_packets++;
        !           454:                        dev->tbusy = 0;
        !           455:                        mark_bh(NET_BH);        /* Inform upper layers. */
        !           456:                }
        !           457:                if (status & SEEQSTAT_RX_INT) {
        !           458:                        /* Got a packet(s). */
        !           459:                        seeq8005_rx(dev);
        !           460:                }
        !           461:                status = inw(SEEQ_STATUS);
        !           462:        } while ( (++boguscount < 10) && (status & SEEQSTAT_ANY_INT)) ;
        !           463: 
        !           464:        if(net_debug>2) {
        !           465:                printk("%s: eoi\n",dev->name);
        !           466:        }
        !           467:        dev->interrupt = 0;
        !           468:        return;
        !           469: }
        !           470: 
        !           471: /* We have a good packet(s), get it/them out of the buffers. */
        !           472: static void
        !           473: seeq8005_rx(struct device *dev)
        !           474: {
        !           475:        struct net_local *lp = (struct net_local *)dev->priv;
        !           476:        int boguscount = 10;
        !           477:        int pkt_hdr;
        !           478:        int ioaddr = dev->base_addr;
        !           479: 
        !           480:        do {
        !           481:                int next_packet;
        !           482:                int pkt_len;
        !           483:                int i;
        !           484:                int status;
        !           485: 
        !           486:                status = inw(SEEQ_STATUS);
        !           487:                outw( lp->receive_ptr, SEEQ_DMAAR);
        !           488:                outw(SEEQCMD_FIFO_READ | SEEQCMD_RX_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
        !           489:                wait_for_buffer(dev);
        !           490:                next_packet = ntohs(inw(SEEQ_BUFFER));
        !           491:                pkt_hdr = inw(SEEQ_BUFFER);
        !           492:                
        !           493:                if (net_debug>2) {
        !           494:                        printk("%s: 0x%04x recv next=0x%04x, hdr=0x%04x\n",dev->name,lp->receive_ptr,next_packet,pkt_hdr);
        !           495:                }
        !           496:                        
        !           497:                if ((next_packet == 0) || ((pkt_hdr & SEEQPKTH_CHAIN)==0)) {    /* Read all the frames? */
        !           498:                        return;                                                 /* Done for now */
        !           499:                }
        !           500:                        
        !           501:                if ((pkt_hdr & SEEQPKTS_DONE)==0)
        !           502:                        break;
        !           503:                        
        !           504:                if (next_packet < lp->receive_ptr) {
        !           505:                        pkt_len = (next_packet + 0x10000 - ((DEFAULT_TEA+1)<<8)) - lp->receive_ptr - 4;
        !           506:                } else {
        !           507:                        pkt_len = next_packet - lp->receive_ptr - 4;
        !           508:                }
        !           509:                
        !           510:                if (next_packet < ((DEFAULT_TEA+1)<<8)) {                       /* is the next_packet address sane? */
        !           511:                        printk("%s: recv packet ring corrupt, resetting board\n",dev->name);
        !           512:                        seeq8005_init(dev,1);
        !           513:                        return;
        !           514:                }
        !           515:                
        !           516:                lp->receive_ptr = next_packet;
        !           517:                
        !           518:                if (net_debug>2) {
        !           519:                        printk("%s: recv len=0x%04x\n",dev->name,pkt_len);
        !           520:                }
        !           521: 
        !           522:                if (pkt_hdr & SEEQPKTS_ANY_ERROR) {                             /* There was an error. */
        !           523:                        lp->stats.rx_errors++;
        !           524:                        if (pkt_hdr & SEEQPKTS_SHORT) lp->stats.rx_frame_errors++;
        !           525:                        if (pkt_hdr & SEEQPKTS_DRIB) lp->stats.rx_frame_errors++;
        !           526:                        if (pkt_hdr & SEEQPKTS_OVERSIZE) lp->stats.rx_over_errors++;
        !           527:                        if (pkt_hdr & SEEQPKTS_CRC_ERR) lp->stats.rx_crc_errors++;
        !           528:                        /* skip over this packet */
        !           529:                        outw( SEEQCMD_FIFO_WRITE | SEEQCMD_DMA_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
        !           530:                        outw( (lp->receive_ptr & 0xff00)>>8, SEEQ_REA);
        !           531:                } else {
        !           532:                        /* Malloc up new buffer. */
        !           533:                        struct sk_buff *skb;
        !           534:                        unsigned char *buf;
        !           535: 
        !           536:                        skb = dev_alloc_skb(pkt_len);
        !           537:                        if (skb == NULL) {
        !           538:                                printk("%s: Memory squeeze, dropping packet.\n", dev->name);
        !           539:                                lp->stats.rx_dropped++;
        !           540:                                break;
        !           541:                        }
        !           542:                        skb->dev = dev;
        !           543:                        skb_reserve(skb, 2);    /* align data on 16 byte */
        !           544:                        buf = skb_put(skb,pkt_len);
        !           545:                        
        !           546:                        insw(SEEQ_BUFFER, buf, (pkt_len + 1) >> 1);
        !           547:                        
        !           548:                        if (net_debug>2) {
        !           549:                                char * p = buf;
        !           550:                                printk("%s: recv ",dev->name);
        !           551:                                for(i=0;i<14;i++) {
        !           552:                                        printk("%02x ",*(p++)&0xff);
        !           553:                                }
        !           554:                                printk("\n");
        !           555:                        }
        !           556: 
        !           557:                        skb->protocol=eth_type_trans(skb,dev);
        !           558:                        netif_rx(skb);
        !           559:                        lp->stats.rx_packets++;
        !           560:                }
        !           561:        } while ((--boguscount) && (pkt_hdr & SEEQPKTH_CHAIN));
        !           562: 
        !           563:        /* If any worth-while packets have been received, netif_rx()
        !           564:           has done a mark_bh(NET_BH) for us and will work on them
        !           565:           when we get to the bottom-half routine. */
        !           566:        return;
        !           567: }
        !           568: 
        !           569: /* The inverse routine to net_open(). */
        !           570: static int
        !           571: seeq8005_close(struct device *dev)
        !           572: {
        !           573:        struct net_local *lp = (struct net_local *)dev->priv;
        !           574:        int ioaddr = dev->base_addr;
        !           575: 
        !           576:        lp->open_time = 0;
        !           577: 
        !           578:        dev->tbusy = 1;
        !           579:        dev->start = 0;
        !           580: 
        !           581:        /* Flush the Tx and disable Rx here. */
        !           582:        outw( SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
        !           583: 
        !           584:        free_irq(dev->irq, NULL);
        !           585: 
        !           586:        irq2dev_map[dev->irq] = 0;
        !           587: 
        !           588:        /* Update the statistics here. */
        !           589: 
        !           590:        return 0;
        !           591: 
        !           592: }
        !           593: 
        !           594: /* Get the current statistics. This may be called with the card open or
        !           595:    closed. */
        !           596: static struct enet_statistics *
        !           597: seeq8005_get_stats(struct device *dev)
        !           598: {
        !           599:        struct net_local *lp = (struct net_local *)dev->priv;
        !           600: 
        !           601:        return &lp->stats;
        !           602: }
        !           603: 
        !           604: /* Set or clear the multicast filter for this adaptor.
        !           605:    num_addrs == -1     Promiscuous mode, receive all packets
        !           606:    num_addrs == 0      Normal mode, clear multicast list
        !           607:    num_addrs > 0       Multicast mode, receive normal and MC packets, and do
        !           608:                        best-effort filtering.
        !           609:  */
        !           610: static void
        !           611: set_multicast_list(struct device *dev)
        !           612: {
        !           613: /*
        !           614:  * I _could_ do up to 6 addresses here, but won't (yet?)
        !           615:  */
        !           616: 
        !           617: #if 0
        !           618:        int ioaddr = dev->base_addr;
        !           619: /*
        !           620:  * hmm, not even sure if my matching works _anyway_ - seem to be receiving
        !           621:  * _everything_ . . .
        !           622:  */
        !           623:  
        !           624:        if (num_addrs) {                        /* Enable promiscuous mode */
        !           625:                outw( (inw(SEEQ_CFG1) & ~SEEQCFG1_MATCH_MASK)| SEEQCFG1_MATCH_ALL,  SEEQ_CFG1);
        !           626:                dev->flags|=IFF_PROMISC;
        !           627:        } else {                                /* Disable promiscuous mode, use normal mode */
        !           628:                outw( (inw(SEEQ_CFG1) & ~SEEQCFG1_MATCH_MASK)| SEEQCFG1_MATCH_BROAD, SEEQ_CFG1);
        !           629:        }
        !           630: #endif
        !           631: }
        !           632: 
        !           633: void seeq8005_init(struct device *dev, int startp)
        !           634: {
        !           635:        struct net_local *lp = (struct net_local *)dev->priv;
        !           636:        int ioaddr = dev->base_addr;
        !           637:        int i;
        !           638:        
        !           639:        outw(SEEQCFG2_RESET, SEEQ_CFG2);        /* reset device */
        !           640:        SLOW_DOWN_IO;                           /* have to wait 4us after a reset - should be fixed */
        !           641:        SLOW_DOWN_IO;
        !           642:        SLOW_DOWN_IO;
        !           643:        SLOW_DOWN_IO;
        !           644:        
        !           645:        outw( SEEQCMD_FIFO_WRITE | SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
        !           646:        outw( 0, SEEQ_DMAAR);                   /* load start address into both low and high byte */
        !           647: /*     wait_for_buffer(dev); */                /* I think that you only need a wait for memory buffer */
        !           648:        outw( SEEQCFG1_BUFFER_MAC0, SEEQ_CFG1);
        !           649:        
        !           650:        for(i=0;i<6;i++) {                      /* set Station address */
        !           651:                outb(dev->dev_addr[i], SEEQ_BUFFER);
        !           652:                SLOW_DOWN_IO;
        !           653:        }
        !           654:        
        !           655:        outw( SEEQCFG1_BUFFER_TEA, SEEQ_CFG1);  /* set xmit end area pointer to 16K */
        !           656:        outb( DEFAULT_TEA, SEEQ_BUFFER);        /* this gives us 16K of send buffer and 48K of recv buffer */
        !           657:        
        !           658:        lp->receive_ptr = (DEFAULT_TEA+1)<<8;   /* so we can find our packet_header */
        !           659:        outw( lp->receive_ptr, SEEQ_RPR);       /* Receive Pointer Register is set to recv buffer memory */
        !           660:        
        !           661:        outw( 0x00ff, SEEQ_REA);                /* Receive Area End */
        !           662: 
        !           663:        if (net_debug>4) {
        !           664:                printk("%s: SA0 = ",dev->name);
        !           665: 
        !           666:                outw( SEEQCMD_FIFO_READ | SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
        !           667:                outw( 0, SEEQ_DMAAR);
        !           668:                outw( SEEQCFG1_BUFFER_MAC0, SEEQ_CFG1);
        !           669:                
        !           670:                for(i=0;i<6;i++) {
        !           671:                        printk("%02x ",inb(SEEQ_BUFFER));
        !           672:                }
        !           673:                printk("\n");
        !           674:        }
        !           675:        
        !           676:        outw( SEEQCFG1_MAC0_EN | SEEQCFG1_MATCH_BROAD | SEEQCFG1_BUFFER_BUFFER, SEEQ_CFG1);
        !           677:        outw( SEEQCFG2_AUTO_REA | SEEQCFG2_CTRLO, SEEQ_CFG2);
        !           678:        outw( SEEQCMD_SET_RX_ON | SEEQCMD_TX_INT_EN | SEEQCMD_RX_INT_EN, SEEQ_CMD);
        !           679: 
        !           680:        if (net_debug>4) {
        !           681:                int old_cfg1;
        !           682:                old_cfg1 = inw(SEEQ_CFG1);
        !           683:                printk("%s: stat = 0x%04x\n",dev->name,inw(SEEQ_STATUS));
        !           684:                printk("%s: cfg1 = 0x%04x\n",dev->name,old_cfg1);
        !           685:                printk("%s: cfg2 = 0x%04x\n",dev->name,inw(SEEQ_CFG2));
        !           686:                printk("%s: raer = 0x%04x\n",dev->name,inw(SEEQ_REA));
        !           687:                printk("%s: dmaar= 0x%04x\n",dev->name,inw(SEEQ_DMAAR));
        !           688:                
        !           689:        }
        !           690: }      
        !           691: 
        !           692: 
        !           693: void hardware_send_packet(struct device * dev, char *buf, int length)
        !           694: {
        !           695:        int ioaddr = dev->base_addr;
        !           696:        int status = inw(SEEQ_STATUS);
        !           697:        int transmit_ptr = 0;
        !           698:        int tmp;
        !           699: 
        !           700:        if (net_debug>4) {
        !           701:                printk("%s: send 0x%04x\n",dev->name,length);
        !           702:        }
        !           703:        
        !           704:        /* Set FIFO to writemode and set packet-buffer address */
        !           705:        outw( SEEQCMD_FIFO_WRITE | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
        !           706:        outw( transmit_ptr, SEEQ_DMAAR);
        !           707:        
        !           708:        /* output SEEQ Packet header barfage */
        !           709:        outw( htons(length + 4), SEEQ_BUFFER);
        !           710:        outw( SEEQPKTH_XMIT | SEEQPKTH_DATA_FOLLOWS | SEEQPKTH_XMIT_INT_EN, SEEQ_BUFFER );
        !           711:        
        !           712:        /* blat the buffer */
        !           713:        outsw( SEEQ_BUFFER, buf, (length +1) >> 1);
        !           714:        /* paranoia !! */
        !           715:        outw( 0, SEEQ_BUFFER);
        !           716:        outw( 0, SEEQ_BUFFER);
        !           717:        
        !           718:        /* set address of start of transmit chain */
        !           719:        outw( transmit_ptr, SEEQ_TPR);
        !           720:        
        !           721:        /* drain FIFO */
        !           722:        tmp = jiffies;
        !           723:        while ( (((status=inw(SEEQ_STATUS)) & SEEQSTAT_FIFO_EMPTY) == 0) && (jiffies < tmp + HZ))
        !           724:                mb();
        !           725:        
        !           726:        /* doit ! */
        !           727:        outw( SEEQCMD_WINDOW_INT_ACK | SEEQCMD_SET_TX_ON | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
        !           728:        
        !           729: }
        !           730: 
        !           731: 
        !           732: /*
        !           733:  * wait_for_buffer
        !           734:  *
        !           735:  * This routine waits for the SEEQ chip to assert that the FIFO is ready
        !           736:  * by checking for a window interrupt, and then clearing it
        !           737:  */
        !           738: inline void wait_for_buffer(struct device * dev)
        !           739: {
        !           740:        int ioaddr = dev->base_addr;
        !           741:        int tmp;
        !           742:        int status;
        !           743:        
        !           744:        tmp = jiffies + HZ;
        !           745:        while ( ( ((status=inw(SEEQ_STATUS)) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && jiffies < tmp)
        !           746:                mb();
        !           747:                
        !           748:        if ( (status & SEEQSTAT_WINDOW_INT) == SEEQSTAT_WINDOW_INT)
        !           749:                outw( SEEQCMD_WINDOW_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
        !           750: }
        !           751:        
        !           752: 
        !           753: /*
        !           754:  * Local variables:
        !           755:  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c skeleton.c"
        !           756:  *  version-control: t
        !           757:  *  kept-new-versions: 5
        !           758:  *  tab-width: 4
        !           759:  * End:
        !           760:  */

unix.superglobalmegacorp.com

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