root/drivers/net/ni52.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ni52_close
  2. ni52_open
  3. check586
  4. alloc586
  5. ni52_probe
  6. ni52_probe1
  7. init586
  8. alloc_rfa
  9. ni52_interrupt
  10. ni52_rcv_int
  11. ni52_rnr_int
  12. ni52_xmt_int
  13. startrecv586
  14. ni52_send_packet
  15. ni52_get_stats
  16. set_multicast_list

   1 /* 
   2  * net-3-driver for the NI5210 card (i82586 Ethernet chip)
   3  *
   4  * This is an extension to the Linux operating system, and is covered by the
   5  * same Gnu Public License that covers that work.
   6  * 
   7  * Alphacode 0.62 (95/01/19) for Linux 1.1.82 (or later)
   8  * Copyrights (c) 1994,1995 by M.Hipp (Michael.Hipp@student.uni-tuebingen.de)
   9  *    [feel free to mail ....]
  10  *
  11  * CAN YOU PLEASE REPORT ME YOUR PERFORMANCE EXPERIENCES !!.
  12  * 
  13  * If you find a bug, please report me:
  14  *   The kernel panic output and any kmsg from the ni52 driver
  15  *   the ni5210-driver-version and the linux-kernel version 
  16  *   how many shared memory (memsize) on the netcard, 
  17  *   bootprom: yes/no, base_addr, mem_start
  18  *   maybe the ni5210-card revision and the i82586 version
  19  *
  20  * autoprobe for: base_addr: 0x300,0x280,0x360,0x320,0x340
  21  *                mem_start: 0xc8000,0xd0000,0xd4000,0xd8000 (8K and 16K)
  22  *
  23  * sources:
  24  *   skeleton.c from Donald Becker
  25  *
  26  * I have also done a look in the following sources: (mail me if you need them)
  27  *   crynwr-packet-driver by Russ Nelson
  28  *   Garret A. Wollman's (fourth) i82586-driver for BSD
  29  *   (before getting an i82596 (yes 596 not 586) manual, the existing drivers helped
  30  *    me a lot to understand this tricky chip.)
  31  *
  32  * Known Problems:
  33  *   The internal sysbus seems to be slow. So we often lose packets because of
  34  *   overruns while receiving from a fast remote host. 
  35  *   This can slow down TCP connections. Maybe the newer ni5210 cards are better.
  36  * 
  37  * IMPORTANT NOTE:
  38  *   On fast networks, it's a (very) good idea to have 16K shared memory. With
  39  *   8K, we can store only 4 receive frames, so it can (easily) happen that a remote 
  40  *   machine 'overruns' our system.
  41  *
  42  * Known i82586 bugs (I'm sure, there are many more!):
  43  *   Running the NOP-mode, the i82586 sometimes seems to forget to report
  44  *   every xmit-interrupt until we restart the CU.
  45  *   Another MAJOR bug is, that the RU sometimes seems to ignore the EL-Bit 
  46  *   in the RBD-Struct which indicates an end of the RBD queue. 
  47  *   Instead, the RU fetches another (randomly selected and 
  48  *   usually used) RBD and begins to fill it. (Maybe, this happens only if 
  49  *   the last buffer from the previous RFD fits exact into the queue and
  50  *   the next RFD can't fetch an initial RBD. Anyone knows more? )
  51  */
  52 
  53 /*
  54  * 19.Jan.95: verified (MH)
  55  *
  56  * 19.Sep.94: Added Multicast support (not tested yet) (MH)
  57  * 
  58  * 18.Sep.94: Workaround for 'EL-Bug'. Removed flexible RBD-handling. 
  59  *            Now, every RFD has exact one RBD. (MH)
  60  *
  61  * 14.Sep.94: added promiscuous mode, a few cleanups (MH)
  62  *
  63  * 19.Aug.94: changed request_irq() parameter (MH)
  64  * 
  65  * 20.July.94: removed cleanup bugs, removed a 16K-mem-probe-bug (MH)
  66  *
  67  * 19.July.94: lotsa cleanups .. (MH)
  68  *
  69  * 17.July.94: some patches ... verified to run with 1.1.29 (MH)
  70  *
  71  * 4.July.94: patches for Linux 1.1.24  (MH)
  72  *
  73  * 26.March.94: patches for Linux 1.0 and iomem-auto-probe (MH)
  74  *
  75  * 30.Sep.93: Added nop-chain .. driver now runs with only one Xmit-Buff, too (MH)
  76  *
  77  * < 30.Sep.93: first versions 
  78  */
  79  
  80 #include <linux/kernel.h>
  81 #include <linux/sched.h>
  82 #include <linux/string.h>
  83 #include <linux/errno.h>
  84 #include <linux/ioport.h>
  85 #include <linux/malloc.h>
  86 #include <linux/interrupt.h>
  87 #include <linux/delay.h>
  88 #include <asm/bitops.h>
  89 #include <asm/io.h>
  90 
  91 #include <linux/netdevice.h>
  92 #include <linux/etherdevice.h>
  93 #include <linux/skbuff.h>
  94 
  95 #include "ni52.h"
  96 
  97 #define DEBUG       /* debug on */
  98 #define SYSBUSVAL 1 /* 8 Bit */
  99 
 100 #define ni_attn586()  {outb(0,dev->base_addr+NI52_ATTENTION);}
 101 #define ni_reset586() {outb(0,dev->base_addr+NI52_RESET);}
 102 
 103 #define make32(ptr16) (p->memtop + (short) (ptr16) )
 104 #define make24(ptr32) ((char *) (ptr32) - p->base)
 105 #define make16(ptr32) ((unsigned short) ((unsigned long) (ptr32) - (unsigned long) p->memtop ))
 106 
 107 /******************* how to calculate the buffers *****************************
 108 
 109   * IMPORTANT NOTE: if you configure only one NUM_XMIT_BUFFS, the driver works
 110   * --------------- in a different (more stable?) mode. Only in this mode it's
 111   *                 possible to configure the driver with 'NO_NOPCOMMANDS'
 112 
 113 sizeof(scp)=12; sizeof(scb)=16; sizeof(iscp)=8;
 114 sizeof(scp)+sizeof(iscp)+sizeof(scb) = 36 = INIT
 115 sizeof(rfd) = 24; sizeof(rbd) = 12; 
 116 sizeof(tbd) = 8; sizeof(transmit_cmd) = 16;
 117 sizeof(nop_cmd) = 8; 
 118 
 119   * if you don't know the driver, better do not change this values: */
 120 
 121 #define RECV_BUFF_SIZE 1524 /* slightly oversized */
 122 #define XMIT_BUFF_SIZE 1524 /* slightly oversized */
 123 #define NUM_XMIT_BUFFS 1    /* config for both, 8K and 16K shmem */
 124 #define NUM_RECV_BUFFS_8  4 /* config for 8K shared mem */
 125 #define NUM_RECV_BUFFS_16 9 /* config for 16K shared mem */
 126 #define NO_NOPCOMMANDS      /* only possible with NUM_XMIT_BUFFS=1 */
 127 
 128 /**************************************************************************/
 129 
 130 #define DELAY(x) {int i=jiffies; \
 131                   if(loops_per_sec == 1) \
 132                      while(i+(x)>jiffies); \
 133                   else \
 134                      __delay((loops_per_sec>>5)*x); \
 135                  }
 136 
 137 /* a much shorter delay: */
 138 #define DELAY_16(); { __delay( (loops_per_sec>>16)+1 ); }
 139 
 140 /* wait for command with timeout: */
 141 #define WAIT_4_SCB_CMD() { int i; \
 142   for(i=0;i<1024;i++) { \
 143     if(!p->scb->cmd) break; \
 144     DELAY_16(); \
 145     if(i == 1023) { \
 146       printk("%s: scb_cmd timed out .. resetting i82586\n",dev->name); \
 147       ni_reset586(); } } }
 148 
 149 
 150 #define NI52_TOTAL_SIZE 16
 151 #define NI52_ADDR0 0x02
 152 #define NI52_ADDR1 0x07
 153 #define NI52_ADDR2 0x01
 154 
 155 #ifndef HAVE_PORTRESERVE
 156 #define check_region(ioaddr, size)              0
 157 #define request_region(ioaddr, size,name)    do ; while (0)
 158 #endif
 159 
 160 static int     ni52_probe1(struct device *dev,int ioaddr);
 161 static void    ni52_interrupt(int irq,struct pt_regs *reg_ptr);
 162 static int     ni52_open(struct device *dev);
 163 static int     ni52_close(struct device *dev);
 164 static int     ni52_send_packet(struct sk_buff *,struct device *);
 165 static struct  enet_statistics *ni52_get_stats(struct device *dev);
 166 static void    set_multicast_list(struct device *dev, int num_addrs, void *addrs);
 167 
 168 /* helper-functions */
 169 static int     init586(struct device *dev,int num_addrs,void *addrs);
 170 static int     check586(struct device *dev,char *where,unsigned size);
 171 static void    alloc586(struct device *dev);
 172 static void    startrecv586(struct device *dev);
 173 static void   *alloc_rfa(struct device *dev,void *ptr);
 174 static void    ni52_rcv_int(struct device *dev);
 175 static void    ni52_xmt_int(struct device *dev);
 176 static void    ni52_rnr_int(struct device *dev);
 177 
 178 struct priv
 179 {
 180   struct enet_statistics stats;
 181   unsigned long base;
 182   char *memtop;
 183   volatile struct rfd_struct  *rfd_last,*rfd_top,*rfd_first;
 184   volatile struct scp_struct  *scp;  /* volatile is important */
 185   volatile struct iscp_struct *iscp; /* volatile is important */
 186   volatile struct scb_struct  *scb;  /* volatile is important */
 187   volatile struct tbd_struct  *xmit_buffs[NUM_XMIT_BUFFS];
 188   volatile struct transmit_cmd_struct *xmit_cmds[NUM_XMIT_BUFFS];
 189 #if (NUM_XMIT_BUFFS == 1)
 190   volatile struct nop_cmd_struct *nop_cmds[2];
 191 #else
 192   volatile struct nop_cmd_struct *nop_cmds[NUM_XMIT_BUFFS];
 193 #endif
 194   volatile int    nop_point,num_recv_buffs;
 195   volatile char  *xmit_cbuffs[NUM_XMIT_BUFFS];
 196   volatile int    xmit_count,xmit_last;
 197 };
 198 
 199 
 200 /**********************************************
 201  * close device 
 202  */
 203 
 204 static int ni52_close(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 205 {
 206   free_irq(dev->irq);
 207   irq2dev_map[dev->irq] = 0;
 208 
 209   ni_reset586(); /* the hard way to stop the receiver */
 210 
 211   dev->start = 0;
 212   dev->tbusy = 0;
 213 
 214   return 0;
 215 }
 216 
 217 /**********************************************
 218  * open device 
 219  */
 220 
 221 static int ni52_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 222 {
 223   alloc586(dev);
 224   init586(dev,0,NULL);  
 225   startrecv586(dev);
 226 
 227   if(request_irq(dev->irq, &ni52_interrupt,0,"ni52")) 
 228   {    
 229     ni_reset586();
 230     return -EAGAIN;
 231   }  
 232   irq2dev_map[dev->irq] = dev;
 233 
 234   dev->interrupt = 0;
 235   dev->tbusy = 0;
 236   dev->start = 1;
 237 
 238   return 0; /* most done by init */
 239 }
 240 
 241 /**********************************************
 242  * Check to see if there's an 82586 out there. 
 243  */
 244 
 245 static int check586(struct device *dev,char *where,unsigned size)
     /* [previous][next][first][last][top][bottom][index][help] */
 246 {
 247   struct priv *p = (struct priv *) dev->priv;
 248   char *iscp_addrs[2];
 249   int i;
 250 
 251   p->base = (unsigned long) where + size - 0x01000000;
 252   p->memtop = where + size;
 253   p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS);
 254   memset((char *)p->scp,0, sizeof(struct scp_struct));
 255   p->scp->sysbus = SYSBUSVAL;        /* 1 = 8Bit-Bus, 0 = 16 Bit */
 256   
 257   iscp_addrs[0] = where;
 258   iscp_addrs[1]= (char *) p->scp - sizeof(struct iscp_struct);
 259 
 260   for(i=0;i<2;i++)
 261   {
 262     p->iscp = (struct iscp_struct *) iscp_addrs[i];
 263     memset((char *)p->iscp,0, sizeof(struct iscp_struct));
 264 
 265     p->scp->iscp = make24(p->iscp);
 266     p->iscp->busy = 1;
 267 
 268     ni_reset586();
 269     ni_attn586();
 270     DELAY(2);   /* wait a while... */
 271 
 272     if(p->iscp->busy) /* i82586 clears 'busy' after successful init */
 273       return 0;
 274   }
 275   return 1;
 276 }
 277 
 278 /******************************************************************
 279  * set iscp at the right place, called by ni52_probe1 and open586. 
 280  */
 281 
 282 void alloc586(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 283 {
 284   struct priv *p =  (struct priv *) dev->priv; 
 285 
 286   ni_reset586();
 287   DELAY(2);
 288 
 289   p->scp  = (struct scp_struct *)  (p->base + SCP_DEFAULT_ADDRESS);
 290   p->scb  = (struct scb_struct *)  (dev->mem_start);
 291   p->iscp = (struct iscp_struct *) ((char *)p->scp - sizeof(struct iscp_struct));
 292 
 293   memset((char *) p->iscp,0,sizeof(struct iscp_struct));
 294   memset((char *) p->scp ,0,sizeof(struct scp_struct));
 295 
 296   p->scp->iscp = make24(p->iscp);
 297   p->scp->sysbus = SYSBUSVAL;
 298   p->iscp->scb_offset = make16(p->scb);
 299 
 300   p->iscp->busy = 1;
 301   ni_reset586();
 302   ni_attn586();
 303 
 304   DELAY(2); 
 305 
 306   if(p->iscp->busy)
 307     printk("%s: Init-Problems (alloc).\n",dev->name);
 308 
 309   memset((char *)p->scb,0,sizeof(struct scb_struct));
 310 }
 311 
 312 /**********************************************
 313  * probe the ni5210-card
 314  */
 315 
 316 int ni52_probe(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 317 {
 318   int *port, ports[] = {0x300, 0x280, 0x360 , 0x320 , 0x340, 0};
 319   int base_addr = dev->base_addr;
 320 
 321   if (base_addr > 0x1ff)                /* Check a single specified location. */
 322     if( (inb(base_addr+NI52_MAGIC1) == NI52_MAGICVAL1) &&
 323         (inb(base_addr+NI52_MAGIC2) == NI52_MAGICVAL2))
 324       return ni52_probe1(dev, base_addr);
 325   else if (base_addr > 0)               /* Don't probe at all. */
 326     return ENXIO;
 327 
 328   for (port = ports; *port; port++) {
 329     int ioaddr = *port;
 330     if (check_region(ioaddr, NI52_TOTAL_SIZE))
 331       continue;
 332     if( !(inb(ioaddr+NI52_MAGIC1) == NI52_MAGICVAL1) || 
 333         !(inb(ioaddr+NI52_MAGIC2) == NI52_MAGICVAL2))
 334       continue;
 335 
 336     dev->base_addr = ioaddr;
 337     if (ni52_probe1(dev, ioaddr) == 0)
 338       return 0;
 339   }
 340 
 341   dev->base_addr = base_addr;
 342   return ENODEV;
 343 }
 344 
 345 static int ni52_probe1(struct device *dev,int ioaddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 346 {
 347   long memaddrs[] = { 0xd0000,0xd2000,0xc8000,0xca000,0xd4000,0xd6000,0xd8000, 0 };
 348   int i,size;
 349 
 350   for(i=0;i<ETH_ALEN;i++)
 351     dev->dev_addr[i] = inb(dev->base_addr+i);
 352 
 353   if(dev->dev_addr[0] != NI52_ADDR0 || dev->dev_addr[1] != NI52_ADDR1
 354                                     || dev->dev_addr[2] != NI52_ADDR2)
 355     return ENODEV;
 356 
 357   printk("%s: Ni52 found at %#3lx, ",dev->name,dev->base_addr);
 358 
 359   request_region(ioaddr,NI52_TOTAL_SIZE,"ni52");
 360 
 361   dev->priv = (void *) kmalloc(sizeof(struct priv),GFP_KERNEL); 
 362                                   /* warning: we don't free it on errors */
 363   memset((char *) dev->priv,0,sizeof(struct priv));
 364 
 365   /* 
 366    * check (or search) IO-Memory, 8K and 16K
 367    */
 368   if(dev->mem_start != 0) /* no auto-mem-probe */
 369   {
 370     size = 0x4000; /* check for 16K mem */
 371     if(!check586(dev,(char *) dev->mem_start,size)) {
 372       size = 0x2000; /* check for 8K mem */
 373       if(!check586(dev,(char *) dev->mem_start,size)) {
 374         printk("?memprobe, Can't find memory at 0x%lx!\n",dev->mem_start);
 375         return ENODEV;
 376       }
 377     }
 378   }
 379   else  
 380   {
 381     for(i=0;;i++)
 382     {
 383       if(!memaddrs[i]) {
 384         printk("?memprobe, Can't find io-memory!\n");
 385         return ENODEV;
 386       }
 387       dev->mem_start = memaddrs[i];
 388       size = 0x2000; /* check for 8K mem */
 389       if(check586(dev,(char *)dev->mem_start,size)) /* 8K-check */
 390         break;
 391       size = 0x4000; /* check for 16K mem */
 392       if(check586(dev,(char *)dev->mem_start,size)) /* 16K-check */
 393         break;
 394     }
 395   }
 396   dev->mem_end = dev->mem_start + size; /* set mem_end showed by 'ifconfig' */
 397   
 398   ((struct priv *) (dev->priv))->base =  dev->mem_start + size - 0x01000000;
 399   alloc586(dev);
 400 
 401   /* set number of receive-buffs according to memsize */
 402   if(size == 0x2000)
 403     ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_8;
 404   else
 405     ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16;
 406 
 407   printk("Memaddr: 0x%lx, Memsize: %d, ",dev->mem_start,size);
 408 
 409   if(dev->irq < 2)
 410   {
 411     autoirq_setup(0);
 412     ni_reset586();
 413     ni_attn586();
 414     if(!(dev->irq = autoirq_report(2)))
 415     {
 416       printk("?autoirq, Failed to detect IRQ line!\n"); 
 417       return 1;
 418     }
 419   }
 420   else if(dev->irq == 2) 
 421     dev->irq = 9;
 422 
 423   printk("IRQ %d.\n",dev->irq);
 424 
 425   dev->open            = &ni52_open;
 426   dev->stop            = &ni52_close;
 427   dev->get_stats       = &ni52_get_stats;
 428   dev->hard_start_xmit = &ni52_send_packet;
 429   dev->set_multicast_list = &set_multicast_list;
 430 
 431   dev->if_port         = 0;
 432 
 433   ether_setup(dev);
 434 
 435   dev->tbusy = 0;
 436   dev->interrupt = 0;
 437   dev->start = 0;
 438   
 439   return 0;
 440 }
 441 
 442 /********************************************** 
 443  * init the chip (ni52-interrupt should be disabled?!)
 444  * needs a correct 'allocated' memory
 445  */
 446 
 447 static int init586(struct device *dev,int num_addrs,void *addrs)
     /* [previous][next][first][last][top][bottom][index][help] */
 448 {
 449   void *ptr;
 450   unsigned long s;
 451   int i,result=0;
 452   struct priv *p = (struct priv *) dev->priv;
 453   volatile struct configure_cmd_struct  *cfg_cmd;
 454   volatile struct iasetup_cmd_struct *ias_cmd;
 455   volatile struct tdr_cmd_struct *tdr_cmd;
 456   volatile struct mcsetup_cmd_struct *mc_cmd;
 457 
 458   ptr = (void *) ((char *)p->scb + sizeof(struct scb_struct));
 459 
 460   cfg_cmd = (struct configure_cmd_struct *)ptr; /* configure-command */
 461   cfg_cmd->cmd_status = 0;
 462   cfg_cmd->cmd_cmd    = CMD_CONFIGURE | CMD_LAST;
 463   cfg_cmd->cmd_link   = 0xffff;
 464 
 465   cfg_cmd->byte_cnt   = 0x0a; /* number of cfg bytes */
 466   cfg_cmd->fifo       = 0x08; /* fifo-limit (8=tx:32/rx:64) */
 467   cfg_cmd->sav_bf     = 0x40; /* hold or discard bad recv frames (bit 7) */
 468   cfg_cmd->adr_len    = 0x2e; /* addr_len |!src_insert |pre-len |loopback */
 469   cfg_cmd->priority   = 0x00;
 470   cfg_cmd->ifs        = 0x60;
 471   cfg_cmd->time_low   = 0x00;
 472   cfg_cmd->time_high  = 0xf2;
 473   cfg_cmd->promisc    = (num_addrs < 0) ? 1 : 0;  /* promisc on/off */
 474   cfg_cmd->carr_coll  = 0x00;
 475  
 476   p->scb->cbl_offset = make16(cfg_cmd);
 477 
 478   p->scb->cmd = CUC_START; /* cmd.-unit start */
 479   ni_attn586();
 480  
 481   s = jiffies; /* warning: only active with interrupts on !! */
 482   while(!(cfg_cmd->cmd_status & STAT_COMPL)) 
 483     if(jiffies-s > 30) break;
 484 
 485   if((cfg_cmd->cmd_status & (STAT_OK|STAT_COMPL)) != (STAT_COMPL|STAT_OK))
 486   {
 487     printk("%s (ni52): configure command failed: %x\n",dev->name,cfg_cmd->cmd_status);
 488     return 1; 
 489   }
 490 
 491     /*
 492      * individual address setup
 493      */
 494   ias_cmd = (struct iasetup_cmd_struct *)ptr;
 495 
 496   ias_cmd->cmd_status = 0;
 497   ias_cmd->cmd_cmd    = CMD_IASETUP | CMD_LAST;
 498   ias_cmd->cmd_link   = 0xffff;
 499 
 500   memcpy((char *)&ias_cmd->iaddr,(char *) dev->dev_addr,ETH_ALEN);
 501 
 502   p->scb->cbl_offset = make16(ias_cmd);
 503 
 504   p->scb->cmd = CUC_START; /* cmd.-unit start */
 505   ni_attn586();
 506 
 507   s = jiffies;
 508   while(!(ias_cmd->cmd_status & STAT_COMPL)) 
 509     if(jiffies-s > 30) break;
 510 
 511   if((ias_cmd->cmd_status & (STAT_OK|STAT_COMPL)) != (STAT_OK|STAT_COMPL)) {
 512     printk("%s (ni52): individual address setup command failed: %04x\n",dev->name,ias_cmd->cmd_status);
 513     return 1; 
 514   }
 515 
 516    /* 
 517     * TDR, wire check .. e.g. no resistor e.t.c 
 518     */
 519   tdr_cmd = (struct tdr_cmd_struct *)ptr;
 520 
 521   tdr_cmd->cmd_status  = 0;
 522   tdr_cmd->cmd_cmd     = CMD_TDR | CMD_LAST;
 523   tdr_cmd->cmd_link    = 0xffff;
 524   tdr_cmd->status      = 0;
 525 
 526   p->scb->cbl_offset = make16(tdr_cmd);
 527 
 528   p->scb->cmd = CUC_START; /* cmd.-unit start */
 529   ni_attn586();
 530 
 531   s = jiffies; 
 532   while(!(tdr_cmd->cmd_status & STAT_COMPL))
 533     if(jiffies - s > 30) {
 534       printk("%s: Problems while running the TDR.\n",dev->name);
 535       result = 1;
 536     }
 537 
 538   if(!result)
 539   {
 540     DELAY(2); /* wait for result */
 541     result = tdr_cmd->status;
 542 
 543     p->scb->cmd = p->scb->status & STAT_MASK;
 544     ni_attn586(); /* ack the interrupts */
 545 
 546     if(result & TDR_LNK_OK) ;
 547     else if(result & TDR_XCVR_PRB)
 548       printk("%s: TDR: Transceiver problem!\n",dev->name);
 549     else if(result & TDR_ET_OPN)
 550       printk("%s: TDR: No correct termination %d clocks away.\n",dev->name,result & TDR_TIMEMASK);
 551     else if(result & TDR_ET_SRT) 
 552     {
 553       if (result & TDR_TIMEMASK) /* time == 0 -> strange :-) */
 554         printk("%s: TDR: Detected a short circuit %d clocks away.\n",dev->name,result & TDR_TIMEMASK);
 555     }
 556     else
 557       printk("%s: TDR: Unknown status %04x\n",dev->name,result);
 558   }
 559  
 560    /* 
 561     * ack interrupts 
 562     */
 563   p->scb->cmd = p->scb->status & STAT_MASK;
 564   ni_attn586();
 565 
 566    /*
 567     * alloc nop/xmit-cmds
 568     */
 569 #if (NUM_XMIT_BUFFS == 1)
 570   for(i=0;i<2;i++)
 571   {
 572     p->nop_cmds[i] = (struct nop_cmd_struct *)ptr;
 573     p->nop_cmds[i]->cmd_cmd    = CMD_NOP;
 574     p->nop_cmds[i]->cmd_status = 0;
 575     p->nop_cmds[i]->cmd_link   = make16((p->nop_cmds[i]));
 576     ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
 577   }
 578   p->xmit_cmds[0] = (struct transmit_cmd_struct *)ptr; /* transmit cmd/buff 0 */
 579   ptr = (char *) ptr + sizeof(struct transmit_cmd_struct);
 580 #else
 581   for(i=0;i<NUM_XMIT_BUFFS;i++)
 582   {
 583     p->nop_cmds[i] = (struct nop_cmd_struct *)ptr;
 584     p->nop_cmds[i]->cmd_cmd    = CMD_NOP;
 585     p->nop_cmds[i]->cmd_status = 0;
 586     p->nop_cmds[i]->cmd_link   = make16((p->nop_cmds[i]));
 587     ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
 588     p->xmit_cmds[i] = (struct transmit_cmd_struct *)ptr; /*transmit cmd/buff 0*/
 589     ptr = (char *) ptr + sizeof(struct transmit_cmd_struct);
 590   }
 591 #endif
 592 
 593   ptr = alloc_rfa(dev,(void *)ptr); /* init receive-frame-area */ 
 594 
 595   /* 
 596    * Multicast setup
 597    */
 598   
 599   if(num_addrs > 0)
 600   { /* I don't understand this: do we really need memory after the init? */
 601     int len = ((char *) p->iscp - (char *) ptr - 8) / 6;
 602     if(len <= 0)
 603     {
 604       printk("%s: Ooooops, no memory for MC-Setup!\n",dev->name);
 605     }
 606     else
 607     {
 608       if(len < num_addrs)
 609       {
 610         num_addrs = len;
 611         printk("%s: Sorry, can only apply %d MC-Address(es).\n",dev->name,num_addrs);
 612       }
 613       mc_cmd = (struct mcsetup_cmd_struct *) ptr;
 614       mc_cmd->cmd_status = 0;
 615       mc_cmd->cmd_cmd = CMD_MCSETUP | CMD_LAST;
 616       mc_cmd->cmd_link = 0xffff;
 617       mc_cmd->mc_cnt = num_addrs * 6;
 618       for(i=0;i<num_addrs;i++)
 619         memcpy((char *) mc_cmd->mc_list[i],((char (*)[6]) addrs)[i],6);
 620       p->scb->cbl_offset = make16(mc_cmd);
 621       p->scb->cmd = CUC_START;
 622       ni_attn586();
 623       s = jiffies;
 624       while(!(mc_cmd->cmd_status & STAT_COMPL))
 625         if(jiffies - s > 30)
 626           break;
 627       if(!(mc_cmd->cmd_status & STAT_COMPL))
 628         printk("%s: Can't apply multicast-address-list.\n",dev->name);
 629     }
 630   }
 631 
 632   /*
 633    * alloc xmit-buffs / init xmit_cmds
 634    */
 635   for(i=0;i<NUM_XMIT_BUFFS;i++)
 636   {
 637     p->xmit_cbuffs[i] = (char *)ptr; /* char-buffs */
 638     ptr = (char *) ptr + XMIT_BUFF_SIZE;
 639     p->xmit_buffs[i] = (struct tbd_struct *)ptr; /* TBD */
 640     ptr = (char *) ptr + sizeof(struct tbd_struct);
 641     if((void *)ptr > (void *)p->iscp) 
 642     {
 643       printk("%s: not enough shared-mem for your configuration!\n",dev->name);
 644       return 1;
 645     }   
 646     memset((char *)(p->xmit_cmds[i]) ,0, sizeof(struct transmit_cmd_struct));
 647     memset((char *)(p->xmit_buffs[i]),0, sizeof(struct tbd_struct));
 648     p->xmit_cmds[i]->cmd_status = STAT_COMPL;
 649     p->xmit_cmds[i]->cmd_cmd = CMD_XMIT | CMD_INT;
 650     p->xmit_cmds[i]->tbd_offset = make16((p->xmit_buffs[i]));
 651     p->xmit_buffs[i]->next = 0xffff;
 652     p->xmit_buffs[i]->buffer = make24((p->xmit_cbuffs[i]));
 653   }
 654 
 655   p->xmit_count = 0; 
 656   p->xmit_last  = 0;
 657 #ifndef NO_NOPCOMMANDS
 658   p->nop_point  = 0;
 659 #endif
 660 
 661    /*
 662     * 'start transmitter' (nop-loop)
 663     */
 664 #ifndef NO_NOPCOMMANDS
 665   p->scb->cbl_offset = make16(p->nop_cmds[0]);
 666   p->scb->cmd = CUC_START;
 667   ni_attn586();
 668   WAIT_4_SCB_CMD();
 669 #else
 670   p->xmit_cmds[0]->cmd_link = 0xffff;
 671   p->xmit_cmds[0]->cmd_cmd  = CMD_XMIT | CMD_LAST | CMD_INT;
 672 #endif
 673 
 674   return 0;
 675 }
 676 
 677 /******************************************************
 678  * This is a helper routine for ni52_rnr_int() and init586(). 
 679  * It sets up the Receive Frame Area (RFA).
 680  */
 681 
 682 static void *alloc_rfa(struct device *dev,void *ptr) 
     /* [previous][next][first][last][top][bottom][index][help] */
 683 {
 684   volatile struct rfd_struct *rfd = (struct rfd_struct *)ptr;
 685   volatile struct rbd_struct *rbd;
 686   int i;
 687   struct priv *p = (struct priv *) dev->priv;
 688 
 689   memset((char *) rfd,0,sizeof(struct rfd_struct)*p->num_recv_buffs);
 690   p->rfd_first = rfd;
 691 
 692   for(i = 0; i < p->num_recv_buffs; i++)
 693     rfd[i].next = make16(rfd + (i+1) % p->num_recv_buffs);
 694   rfd[p->num_recv_buffs-1].last = RFD_SUSP;   /* RU suspend */
 695 
 696   ptr = (void *) (rfd + p->num_recv_buffs);
 697 
 698   rbd = (struct rbd_struct *) ptr;
 699   ptr = (void *) (rbd + p->num_recv_buffs);
 700 
 701    /* clr descriptors */
 702   memset((char *) rbd,0,sizeof(struct rbd_struct)*p->num_recv_buffs);
 703 
 704   for(i=0;i<p->num_recv_buffs;i++)
 705   {
 706     rbd[i].next = make16((rbd + (i+1) % p->num_recv_buffs));
 707     rbd[i].size = RECV_BUFF_SIZE;
 708     rbd[i].buffer = make24(ptr);
 709     ptr = (char *) ptr + RECV_BUFF_SIZE;
 710   }
 711 
 712   p->rfd_top  = p->rfd_first;
 713   p->rfd_last = p->rfd_first + p->num_recv_buffs - 1;
 714 
 715   p->scb->rfa_offset            = make16(p->rfd_first);
 716   p->rfd_first->rbd_offset      = make16(rbd);
 717 
 718   return ptr;
 719 }
 720 
 721 
 722 /**************************************************
 723  * Interrupt Handler ...
 724  */
 725 
 726 static void ni52_interrupt(int irq,struct pt_regs *reg_ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 727 {
 728   struct device *dev = (struct device *) irq2dev_map[irq];
 729   unsigned short stat;
 730   struct priv *p;
 731 
 732   if (dev == NULL) {
 733     printk ("ni52-interrupt: irq %d for unknown device.\n",(int) -(((struct pt_regs *)reg_ptr)->orig_eax+2));
 734     return;
 735   }
 736   p = (struct priv *) dev->priv;
 737 
 738   dev->interrupt = 1;
 739 
 740   while((stat=p->scb->status & STAT_MASK))
 741   {
 742     p->scb->cmd = stat;
 743     ni_attn586(); /* ack inter. */
 744 
 745    if(stat & STAT_CX)    /* command with I-bit set complete */
 746       ni52_xmt_int(dev);
 747 
 748     if(stat & STAT_FR)   /* received a frame */
 749       ni52_rcv_int(dev);
 750 
 751 #ifndef NO_NOPCOMMANDS
 752     if(stat & STAT_CNA)  /* CU went 'not ready' */
 753     {
 754       if(dev->start)
 755         printk("%s: oops! CU has left active state. stat: %04x/%04x.\n",dev->name,(int) stat,(int) p->scb->status);
 756     }
 757 #endif
 758 
 759     if(stat & STAT_RNR) /* RU went 'not ready' */
 760     {
 761       if(p->scb->status & RU_SUSPEND) /* special case: RU_SUSPEND */
 762       {
 763         WAIT_4_SCB_CMD();
 764         p->scb->cmd = RUC_RESUME;
 765         ni_attn586();
 766       }
 767       else
 768       {
 769         printk("%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n",dev->name,(int) stat,(int) p->scb->status);
 770         ni52_rnr_int(dev); 
 771       }
 772     }
 773     WAIT_4_SCB_CMD(); /* wait for ack. (ni52_xmt_int can be faster than ack!!) */
 774     if(p->scb->cmd)   /* timed out? */
 775       break;
 776   }
 777 
 778   dev->interrupt = 0;
 779 }
 780 
 781 /*******************************************************
 782  * receive-interrupt
 783  */
 784 
 785 static void ni52_rcv_int(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 786 {
 787   int status;
 788   unsigned short totlen;
 789   struct sk_buff *skb;
 790   struct rbd_struct *rbd;
 791   struct priv *p = (struct priv *) dev->priv;
 792 
 793   for(;(status = p->rfd_top->status) & STAT_COMPL;)
 794   {
 795       rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset);
 796 
 797       if(status & STAT_OK) /* frame received without error? */
 798       {
 799         if( (totlen = rbd->status) & RBD_LAST) /* the first and the last buffer? */
 800         {
 801           totlen &= RBD_MASK; /* length of this frame */
 802           rbd->status = 0;
 803           skb = (struct sk_buff *) dev_alloc_skb(totlen+2);
 804           if(skb != NULL)
 805           {
 806             skb->dev = dev;
 807             skb_reserve(skb,2);         /* 16 byte alignment */
 808             memcpy(skb_put(skb,totlen),(char *) p->base+(unsigned long) rbd->buffer, totlen);
 809             skb->protocol=eth_type_trans(skb,dev);
 810             netif_rx(skb);
 811             p->stats.rx_packets++;
 812           }
 813           else
 814             p->stats.rx_dropped++;
 815         }
 816         else
 817         {
 818           printk("%s: received oversized frame.\n",dev->name);
 819           p->stats.rx_dropped++;
 820         }
 821       }
 822       else /* frame !(ok), only with 'save-bad-frames' */
 823       {
 824         printk("%s: oops! rfd-error-status: %04x\n",dev->name,status);
 825         p->stats.rx_errors++;
 826       }
 827       p->rfd_top->status = 0;
 828       p->rfd_top->last = RFD_SUSP;
 829       p->rfd_last->last = 0;        /* delete RU_SUSP  */
 830       p->rfd_last = p->rfd_top;
 831       p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next); /* step to next RFD */
 832   }
 833 }
 834 
 835 /**********************************************************
 836  * handle 'Receiver went not ready'. 
 837  */
 838 
 839 static void ni52_rnr_int(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 840 {
 841   struct priv *p = (struct priv *) dev->priv;
 842 
 843   p->stats.rx_errors++;
 844 
 845   WAIT_4_SCB_CMD();    /* wait for the last cmd */
 846   p->scb->cmd = RUC_ABORT; /* usually the RU is in the 'no resource'-state .. abort it now. */
 847   ni_attn586(); 
 848   WAIT_4_SCB_CMD();    /* wait for accept cmd. */
 849 
 850   alloc_rfa(dev,(char *)p->rfd_first);
 851   startrecv586(dev); /* restart RU */
 852 
 853   printk("%s: Receive-Unit restarted. Status: %04x\n",dev->name,p->scb->status);
 854 
 855 }
 856 
 857 /**********************************************************
 858  * handle xmit - interrupt
 859  */
 860 
 861 static void ni52_xmt_int(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 862 {
 863   int status;
 864   struct priv *p = (struct priv *) dev->priv;
 865 
 866   status = p->xmit_cmds[p->xmit_last]->cmd_status;
 867   if(!(status & STAT_COMPL))
 868     printk("%s: strange .. xmit-int without a 'COMPLETE'\n",dev->name);
 869 
 870   if(status & STAT_OK)
 871   {
 872     p->stats.tx_packets++;
 873     p->stats.collisions += (status & TCMD_MAXCOLLMASK);
 874   }
 875   else 
 876   {
 877     p->stats.tx_errors++;
 878     if(status & TCMD_LATECOLL) {
 879       printk("%s: late collision detected.\n",dev->name);
 880       p->stats.collisions++;
 881     } 
 882     else if(status & TCMD_NOCARRIER) {
 883       p->stats.tx_carrier_errors++;
 884       printk("%s: no carrier detected.\n",dev->name);
 885     } 
 886     else if(status & TCMD_LOSTCTS) 
 887       printk("%s: loss of CTS detected.\n",dev->name);
 888     else if(status & TCMD_UNDERRUN) {
 889       p->stats.tx_fifo_errors++;
 890       printk("%s: DMA underrun detected.\n",dev->name);
 891     }
 892     else if(status & TCMD_MAXCOLL) {
 893       printk("%s: Max. collisions exceeded.\n",dev->name);
 894       p->stats.collisions += 16;
 895     } 
 896   }
 897 
 898 #if (NUM_XMIT_BUFFS != 1)
 899   if( (++p->xmit_last) == NUM_XMIT_BUFFS) 
 900     p->xmit_last = 0;
 901 #endif
 902 
 903   dev->tbusy = 0;
 904   mark_bh(NET_BH);
 905 }
 906 
 907 /***********************************************************
 908  * (re)start the receiver
 909  */ 
 910 
 911 static void startrecv586(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 912 {
 913   struct priv *p = (struct priv *) dev->priv;
 914 
 915   p->scb->rfa_offset = make16(p->rfd_first);
 916   p->scb->cmd = RUC_START;
 917   ni_attn586();         /* start cmd. */
 918   WAIT_4_SCB_CMD();     /* wait for accept cmd. (no timeout!!) */
 919 }
 920 
 921 /******************************************************
 922  * send frame 
 923  */
 924 
 925 static int ni52_send_packet(struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 926 {
 927   int len,i;
 928 #ifndef NO_NOPCOMMANDS
 929   int next_nop;
 930 #endif
 931   struct priv *p = (struct priv *) dev->priv;
 932 
 933   if(dev->tbusy)
 934   {
 935     int tickssofar = jiffies - dev->trans_start;
 936     if (tickssofar < 5)
 937       return 1;
 938 
 939     if(p->scb->status & CU_ACTIVE) /* COMMAND-UNIT active? */
 940     {
 941       dev->tbusy = 0;
 942 #ifdef DEBUG
 943       printk("%s: strange ... timeout with CU active?!?\n",dev->name);
 944       printk("%s: X0: %04x N0: %04x N1: %04x %d\n",dev->name,(int)p->xmit_cmds[0]->cmd_status,(int)p->nop_cmds[0]->cmd_status,(int)p->nop_cmds[1]->cmd_status,(int)p->nop_point);
 945 #endif
 946       p->scb->cmd = CUC_ABORT;
 947       ni_attn586();
 948       WAIT_4_SCB_CMD();
 949       p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]);
 950       p->scb->cmd = CUC_START;
 951       ni_attn586();
 952       WAIT_4_SCB_CMD();
 953       dev->trans_start = jiffies;
 954       return 0;
 955     }
 956     else
 957     {
 958 #ifdef DEBUG
 959       printk("%s: xmitter timed out, try to restart! stat: %04x\n",dev->name,p->scb->status);
 960       printk("%s: command-stats: %04x %04x\n",dev->name,p->xmit_cmds[0]->cmd_status,p->xmit_cmds[1]->cmd_status);
 961 #endif
 962       ni52_close(dev);
 963       ni52_open(dev);
 964     }
 965     dev->trans_start = jiffies;
 966     return 0;
 967   }
 968 
 969   if(skb == NULL)
 970   {
 971     dev_tint(dev);
 972     return 0;
 973   }
 974 
 975   if (skb->len <= 0)
 976     return 0;
 977   if(skb->len > XMIT_BUFF_SIZE)
 978   {
 979     printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %ld bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len);
 980     return 0;
 981   }
 982 
 983   if (set_bit(0, (void*)&dev->tbusy) != 0)
 984      printk("%s: Transmitter access conflict.\n", dev->name);
 985   else
 986   {
 987     memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len);
 988     len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
 989 
 990 #if (NUM_XMIT_BUFFS == 1)
 991 #  ifdef NO_NOPCOMMANDS
 992     p->xmit_buffs[0]->size = TBD_LAST | len;
 993     for(i=0;i<16;i++)
 994     {
 995       p->scb->cbl_offset = make16(p->xmit_cmds[0]);
 996       p->scb->cmd = CUC_START;
 997       p->xmit_cmds[0]->cmd_status = 0;
 998 
 999       ni_attn586();
1000       dev->trans_start = jiffies;
1001       if(!i)
1002         dev_kfree_skb(skb,FREE_WRITE);
1003       WAIT_4_SCB_CMD();
1004       if( (p->scb->status & CU_ACTIVE)) /* test it, because CU sometimes doesn't start immediately */
1005         break;
1006       if(p->xmit_cmds[0]->cmd_status)
1007         break;
1008       if(i==15)
1009         printk("%s: Can't start transmit-command.\n",dev->name);
1010     }
1011 #  else
1012     next_nop = (p->nop_point + 1) & 0x1;
1013     p->xmit_buffs[0]->size = TBD_LAST | len;
1014 
1015     p->xmit_cmds[0]->cmd_link   = p->nop_cmds[next_nop]->cmd_link 
1016                                 = make16((p->nop_cmds[next_nop]));
1017     p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0;
1018 
1019     p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0]));
1020     dev->trans_start = jiffies;
1021     p->nop_point = next_nop;
1022     dev_kfree_skb(skb,FREE_WRITE);
1023 #  endif
1024 #else
1025     p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len;
1026     if( (next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS ) 
1027       next_nop = 0;
1028 
1029     p->xmit_cmds[p->xmit_count]->cmd_status  = 0;
1030     p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link 
1031                                           = make16((p->nop_cmds[next_nop]));
1032     p->nop_cmds[next_nop]->cmd_status = 0;
1033 
1034     p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count]));
1035     dev->trans_start = jiffies;
1036     p->xmit_count = next_nop;
1037   
1038     cli();
1039     if(p->xmit_count != p->xmit_last)
1040       dev->tbusy = 0;
1041     sti();
1042     dev_kfree_skb(skb,FREE_WRITE);
1043 #endif
1044   }
1045   return 0;
1046 }
1047 
1048 /*******************************************
1049  * Someone wanna have the statistics 
1050  */
1051 
1052 static struct enet_statistics *ni52_get_stats(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
1053 {
1054   struct priv *p = (struct priv *) dev->priv;
1055   unsigned short crc,aln,rsc,ovrn;
1056 
1057   crc = p->scb->crc_errs; /* get error-statistic from the ni82586 */
1058   p->scb->crc_errs -= crc;
1059   aln = p->scb->aln_errs;
1060   p->scb->aln_errs -= aln;
1061   rsc = p->scb->rsc_errs;
1062   p->scb->rsc_errs -= rsc;
1063   ovrn = p->scb->ovrn_errs;
1064   p->scb->ovrn_errs -= ovrn;
1065 
1066   p->stats.rx_crc_errors += crc;
1067   p->stats.rx_fifo_errors += ovrn;
1068   p->stats.rx_frame_errors += aln;
1069   p->stats.rx_dropped += rsc;
1070 
1071   return &p->stats;
1072 }
1073 
1074 /********************************************************
1075  * Set MC list ..  
1076  */
1077 
1078 static void set_multicast_list(struct device *dev, int num_addrs, void *addrs)
     /* [previous][next][first][last][top][bottom][index][help] */
1079 {
1080   if(!dev->start && !num_addrs)
1081   {
1082     printk("%s: Can't apply promiscuous/multicastmode to a not running interface.\n",dev->name);
1083     return;
1084   }
1085 
1086   dev->start = 0;
1087   alloc586(dev);
1088   init586(dev,num_addrs,addrs);  
1089   startrecv586(dev);
1090   dev->start = 1;
1091 }
1092 
1093 /*
1094  * END: linux/drivers/net/ni52.c 
1095  */

/* [previous][next][first][last][top][bottom][index][help] */