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

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