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

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