root/drivers/net/3c507.c

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

DEFINITIONS

This source file includes following definitions.
  1. el16_probe
  2. el16_probe1
  3. el16_open
  4. el16_send_packet
  5. el16_interrupt
  6. el16_close
  7. el16_get_stats
  8. init_rx_bufs
  9. init_82586_mem
  10. hardware_send_packet
  11. el16_rx

   1 /* 3c507.c: An EtherLink16 device driver for Linux. */
   2 /*
   3         Written 1993 by Donald Becker.
   4         Copyright 1993 United States Government as represented by the Director,
   5         National Security Agency.  This software may only be used and distributed
   6         according to the terms of the GNU Public License as modified by SRC,
   7         incorported herein by reference.
   8 
   9         The author may be reached as becker@super.org or
  10         C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
  11 
  12         Thanks go to jennings@Montrouge.SMR.slb.com ( Patrick Jennings)
  13         and jrs@world.std.com (Rick Sladkey) for testing and bugfixes.
  14         Mark Salazar <leslie@access.digex.net> made the changes for cards with
  15         only 16K packet buffers.
  16 
  17         Things remaining to do:
  18         Verify that the tx and rx buffers don't have fencepost errors.
  19         Move the theory of operation and memory map documentation.
  20         The statistics need to be updated correctly.
  21 */
  22 
  23 static char *version =
  24         "3c507.c:v0.99-15f 2/17/94 Donald Becker (becker@super.org)\n";
  25 
  26 #include <linux/config.h>
  27 
  28 /*
  29   Sources:
  30         This driver wouldn't have been written with the availability of the
  31         Crynwr driver source code.      It provided a known-working implementation
  32         that filled in the gaping holes of the Intel documention.  Three cheers
  33         for Russ Nelson.
  34 
  35         Intel Microcommunications Databook, Vol. 1, 1990. It provides just enough
  36         info that the casual reader might think that it documents the i82586.
  37 */
  38 
  39 #include <linux/kernel.h>
  40 #include <linux/sched.h>
  41 #include <linux/types.h>
  42 #include <linux/fcntl.h>
  43 #include <linux/interrupt.h>
  44 #include <linux/ptrace.h>
  45 #include <linux/ioport.h>
  46 #include <linux/in.h>
  47 #include <linux/string.h>
  48 #include <asm/system.h>
  49 #include <asm/bitops.h>
  50 #include <asm/io.h>
  51 #include <asm/dma.h>
  52 #include <linux/errno.h>
  53 
  54 #include <linux/netdevice.h>
  55 #include <linux/etherdevice.h>
  56 #include <linux/skbuff.h>
  57 #include <linux/malloc.h>
  58 
  59 /* use 0 for production, 1 for verification, 2..7 for debug */
  60 #ifndef NET_DEBUG
  61 #define NET_DEBUG 1
  62 #endif
  63 static unsigned int net_debug = NET_DEBUG;
  64 
  65 /*
  66                         Details of the i82586.
  67 
  68    You'll really need the databook to understand the details of this part,
  69    but the outline is that the i82586 has two seperate processing units.
  70    Both are started from a list of three configuration tables, of which only
  71    the last, the System Control Block (SCB), is used after reset-time.  The SCB
  72    has the following fileds:
  73                 Status word
  74                 Command word
  75                 Tx/Command block addr.
  76                 Rx block addr.
  77    The command word accepts the following controls for the Tx and Rx units:
  78   */
  79 
  80 #define  CUC_START       0x0100
  81 #define  CUC_RESUME      0x0200
  82 #define  CUC_SUSPEND 0x0300
  83 #define  RX_START        0x0010
  84 #define  RX_RESUME       0x0020
  85 #define  RX_SUSPEND      0x0030
  86 
  87 /* The Rx unit uses a list of frame descriptors and a list of data buffer
  88    descriptors.  We use full-sized (1518 byte) data buffers, so there is
  89    a one-to-one pairing of frame descriptors to buffer descriptors.
  90 
  91    The Tx ("command") unit executes a list of commands that look like:
  92                 Status word             Written by the 82586 when the command is done.
  93                 Command word    Command in lower 3 bits, post-command action in upper 3
  94                 Link word               The address of the next command.
  95                 Parameters              (as needed).
  96 
  97         Some definitions related to the Command Word are:
  98  */
  99 #define CMD_EOL         0x8000                  /* The last command of the list, stop. */
 100 #define CMD_SUSP        0x4000                  /* Suspend after doing cmd. */
 101 #define CMD_INTR        0x2000                  /* Interrupt after doing cmd. */
 102 
 103 enum commands {
 104         CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
 105         CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7};
 106 
 107 /* Information that need to be kept for each board. */
 108 struct net_local {
 109         struct enet_statistics stats;
 110         int last_restart;
 111         ushort rx_head;
 112         ushort rx_tail;
 113         ushort tx_head;
 114         ushort tx_cmd_link;
 115         ushort tx_reap;
 116 };
 117 
 118 /*
 119                 Details of the EtherLink16 Implementation
 120   The 3c507 is a generic shared-memory i82586 implementation.
 121   The host can map 16K, 32K, 48K, or 64K of the 64K memory into
 122   0x0[CD][08]0000, or all 64K into 0xF[02468]0000.
 123   */
 124 
 125 /* Offsets from the base I/O address. */
 126 #define SA_DATA         0       /* Station address data, or 3Com signature. */
 127 #define MISC_CTRL       6       /* Switch the SA_DATA banks, and bus config bits. */
 128 #define RESET_IRQ       10      /* Reset the latched IRQ line. */
 129 #define SIGNAL_CA       11      /* Frob the 82586 Channel Attention line. */
 130 #define ROM_CONFIG      13
 131 #define MEM_CONFIG      14
 132 #define IRQ_CONFIG      15
 133 
 134 /* The ID port is used at boot-time to locate the ethercard. */
 135 #define ID_PORT         0x100
 136 
 137 /* Offsets to registers in the mailbox (SCB). */
 138 #define iSCB_STATUS     0x8
 139 #define iSCB_CMD                0xA
 140 #define iSCB_CBL                0xC     /* Command BLock offset. */
 141 #define iSCB_RFA                0xE     /* Rx Frame Area offset. */
 142 
 143 /*  Since the 3c507 maps the shared memory window so that the last byte is
 144         at 82586 address FFFF, the first byte is at 82586 address 0, 16K, 32K, or
 145         48K cooresponding to window sizes of 64K, 48K, 32K and 16K respectively. 
 146         We can account for this be setting the 'SBC Base' entry in the ISCP table
 147         below for all the 16 bit offset addresses, and also adding the 'SCB Base'
 148         value to all 24 bit physical addresses (in the SCP table and the TX and RX
 149         Buffer Descriptors).
 150                                         -Mark   
 151         */
 152 #define SCB_BASE                ((unsigned)64*1024 - (dev->mem_end - dev->mem_start))
 153  
 154 /*
 155   What follows in 'init_words[]' is the "program" that is downloaded to the
 156   82586 memory.  It's mostly tables and command blocks, and starts at the
 157   reset address 0xfffff6.  This is designed to be similar to the EtherExpress,
 158   thus the unusual location of the SCB at 0x0008.
 159 
 160   Even with the additional "don't care" values, doing it this way takes less
 161   program space than initializing the individual tables, and I feel it's much
 162   cleaner.
 163 
 164   The databook is particularly useless for the first two structures, I had
 165   to use the Crynwr driver as an example.
 166 
 167    The memory setup is as follows:
 168    */
 169 
 170 #define CONFIG_CMD      0x0018
 171 #define SET_SA_CMD      0x0024
 172 #define SA_OFFSET       0x002A
 173 #define IDLELOOP        0x30
 174 #define TDR_CMD         0x38
 175 #define TDR_TIME        0x3C
 176 #define DUMP_CMD        0x40
 177 #define DIAG_CMD        0x48
 178 #define SET_MC_CMD      0x4E
 179 #define DUMP_DATA       0x56    /* A 170 byte buffer for dump and Set-MC into. */
 180 
 181 #define TX_BUF_START    0x0100
 182 #define NUM_TX_BUFS     4
 183 #define TX_BUF_SIZE     (1518+14+20+16) /* packet+header+TBD */
 184 
 185 #define RX_BUF_START    0x2000
 186 #define RX_BUF_SIZE     (1518+14+18)    /* packet+header+RBD */
 187 #define RX_BUF_END              (dev->mem_end - dev->mem_start)
 188 
 189 /*
 190   That's it: only 86 bytes to set up the beast, including every extra
 191   command available.  The 170 byte buffer at DUMP_DATA is shared between the
 192   Dump command (called only by the diagnostic program) and the SetMulticastList
 193   command. 
 194 
 195   To complete the memory setup you only have to write the station address at
 196   SA_OFFSET and create the Tx & Rx buffer lists.
 197 
 198   The Tx command chain and buffer list is setup as follows:
 199   A Tx command table, with the data buffer pointing to...
 200   A Tx data buffer descriptor.  The packet is in a single buffer, rather than
 201         chaining together several smaller buffers.
 202   A NoOp command, which initially points to itself,
 203   And the packet data.
 204 
 205   A transmit is done by filling in the Tx command table and data buffer,
 206   re-writing the NoOp command, and finally changing the offset of the last
 207   command to point to the current Tx command.  When the Tx command is finished,
 208   it jumps to the NoOp, when it loops until the next Tx command changes the
 209   "link offset" in the NoOp.  This way the 82586 never has to go through the
 210   slow restart sequence.
 211 
 212   The Rx buffer list is set up in the obvious ring structure.  We have enough
 213   memory (and low enough interrupt latency) that we can avoid the complicated
 214   Rx buffer linked lists by alway associating a full-size Rx data buffer with
 215   each Rx data frame.
 216 
 217   I current use four transmit buffers starting at TX_BUF_START (0x0100), and
 218   use the rest of memory, from RX_BUF_START to RX_BUF_END, for Rx buffers.
 219 
 220   */
 221 
 222 unsigned short init_words[] = {
 223         /*      System Configuration Pointer (SCP). */
 224         0x0000,                                 /* Set bus size to 16 bits. */
 225         0,0,                                    /* pad words. */
 226         0x0000,0x0000,                  /* ISCP phys addr, set in init_82586_mem(). */
 227 
 228         /*      Intermediate System Configuration Pointer (ISCP). */
 229         0x0001,                                 /* Status word that's cleared when init is done. */
 230         0x0008,0,0,                             /* SCB offset, (skip, skip) */
 231 
 232         /* System Control Block (SCB). */
 233         0,0xf000|RX_START|CUC_START,    /* SCB status and cmd. */
 234         CONFIG_CMD,                             /* Command list pointer, points to Configure. */
 235         RX_BUF_START,                           /* Rx block list. */
 236         0,0,0,0,                                /* Error count: CRC, align, buffer, overrun. */
 237 
 238         /* 0x0018: Configure command.  Change to put MAC data with packet. */
 239         0, CmdConfigure,                /* Status, command.             */
 240         SET_SA_CMD,                             /* Next command is Set Station Addr. */
 241         0x0804,                                 /* "4" bytes of config data, 8 byte FIFO. */
 242         0x2e40,                                 /* Magic values, including MAC data location. */
 243         0,                                              /* Unused pad word. */
 244 
 245         /* 0x0024: Setup station address command. */
 246         0, CmdSASetup,
 247         SET_MC_CMD,                             /* Next command. */
 248         0xaa00,0xb000,0x0bad,   /* Station address (to be filled in) */
 249 
 250         /* 0x0030: NOP, looping back to itself.  Point to first Tx buffer to Tx. */
 251         0, CmdNOp, IDLELOOP, 0 /* pad */,
 252 
 253         /* 0x0038: A unused Time-Domain Reflectometer command. */
 254         0, CmdTDR, IDLELOOP, 0,
 255 
 256         /* 0x0040: An unused Dump State command. */
 257         0, CmdDump, IDLELOOP, DUMP_DATA,
 258 
 259         /* 0x0048: An unused Diagnose command. */
 260         0, CmdDiagnose, IDLELOOP,
 261 
 262         /* 0x004E: An empty set-multicast-list command. */
 263         0, CmdMulticastList, IDLELOOP, 0,
 264 };
 265 
 266 /* Index to functions, as function prototypes. */
 267 
 268 extern int el16_probe(struct device *dev);      /* Called from Space.c */
 269 
 270 static int      el16_probe1(struct device *dev, short ioaddr);
 271 static int      el16_open(struct device *dev);
 272 static int      el16_send_packet(struct sk_buff *skb, struct device *dev);
 273 static void     el16_interrupt(int reg_ptr);
 274 static void el16_rx(struct device *dev);
 275 static int      el16_close(struct device *dev);
 276 static struct enet_statistics *el16_get_stats(struct device *dev);
 277 
 278 static void hardware_send_packet(struct device *dev, void *buf, short length);
 279 void init_82586_mem(struct device *dev);
 280 
 281 
 282 /* Check for a network adaptor of this type, and return '0' iff one exists.
 283         If dev->base_addr == 0, probe all likely locations.
 284         If dev->base_addr == 1, always return failure.
 285         If dev->base_addr == 2, (detachable devices only) alloate space for the
 286         device and return success.
 287         */
 288 int
 289 el16_probe(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 290 {
 291         /* Don't probe all settable addresses, 0x[23][0-F]0, just common ones. */
 292         int *port, ports[] = {0x300, 0x320, 0x340, 0x280, 0};
 293         int base_addr = dev->base_addr;
 294         ushort lrs_state = 0xff, i;
 295 
 296         if (base_addr > 0x1ff)  /* Check a single specified location. */
 297                 return el16_probe1(dev, base_addr);
 298         else if (base_addr > 0)
 299                 return ENXIO;           /* Don't probe at all. */
 300 
 301         /* Send the ID sequence to the ID_PORT to enable the board. */
 302         outb(0x00, ID_PORT);
 303         for(i = 0; i < 255; i++) {
 304                 outb(lrs_state, ID_PORT);
 305                 lrs_state <<= 1;
 306                 if (lrs_state & 0x100)
 307                         lrs_state ^= 0xe7;
 308         }
 309         outb(0x00, ID_PORT);
 310 
 311         for (port = &ports[0]; *port; port++) {
 312                 short ioaddr = *port;
 313 #if 0
 314                 /* This is my original code. */
 315                 if (inb(ioaddr) == '*' && inb(ioaddr+1) == '3'
 316                         && inb(ioaddr+2) == 'C' && inb(ioaddr+3) == 'O'
 317                         && el16_probe1(dev, *port) == 0)
 318                         return 0;
 319 #else
 320         /* This is code from jennings@Montrouge.SMR.slb.com, done so that
 321            the string can be printed out. */
 322                 char res[5];
 323                 res[0] = inb(ioaddr); res[1] = inb(ioaddr+1);
 324                 res[2] = inb(ioaddr+2); res[3] = inb(ioaddr+3);
 325                 res[4] = 0;
 326                 if (res[0] == '*' && res[1] == '3'
 327                         && res[2] == 'C' && res[3] == 'O'
 328                         && el16_probe1(dev, *port) == 0)
 329                   return 0;
 330 #endif
 331         }
 332 
 333         return ENODEV;                  /* ENODEV would be more accurate. */
 334 }
 335 
 336 int el16_probe1(struct device *dev, short ioaddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 337 {
 338         int i, irq, irqval;
 339 
 340         printk("%s: 3c507 at %#x,", dev->name, ioaddr);
 341 
 342         /* We should make a few more checks here, like the first three octets of
 343            the S.A. for the manufactor's code. */ 
 344 
 345         irq = inb(ioaddr + IRQ_CONFIG) & 0x0f;
 346 
 347         irqval = request_irq(irq, &el16_interrupt);
 348         if (irqval) {
 349                 printk ("unable to get IRQ %d (irqval=%d).\n", irq, irqval);
 350                 return EAGAIN;
 351         }
 352         
 353         /* We've committed to using the board, and can start filling in *dev. */
 354         snarf_region(ioaddr, 16);
 355         dev->base_addr = ioaddr;
 356 
 357         outb(0x01, ioaddr + MISC_CTRL);
 358         for (i = 0; i < 6; i++) {
 359                 dev->dev_addr[i] = inb(ioaddr + i);
 360                 printk(" %02x", dev->dev_addr[i]);
 361         }
 362 
 363         if ((dev->mem_start & 0xf) > 0)
 364                 net_debug = dev->mem_start & 7;
 365 
 366 #ifdef MEM_BASE
 367         dev->mem_start = MEM_BASE;
 368         dev->mem_end = dev->mem_start + 0x10000;
 369 #else
 370         {
 371                 int base;
 372                 int size;
 373                 char mem_config = inb(ioaddr + MEM_CONFIG);
 374                 if (mem_config & 0x20) {
 375                         size = 64*1024;
 376                         base = 0xf00000 + (mem_config & 0x08 ? 0x080000
 377                                                            : ((mem_config & 3) << 17));
 378                 } else {
 379                         size = ((mem_config & 3) + 1) << 14;
 380                         base = 0x0c0000 + ( (mem_config & 0x18) << 12);
 381                 }
 382                 dev->mem_start = base;
 383                 dev->mem_end = base + size;
 384         }
 385 #endif
 386 
 387         dev->if_port = (inb(ioaddr + ROM_CONFIG) & 0x80) ? 1 : 0;
 388         dev->irq = inb(ioaddr + IRQ_CONFIG) & 0x0f;
 389 
 390         printk(", IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->irq,
 391                    dev->if_port ? "ex" : "in", dev->mem_start, dev->mem_end-1);
 392 
 393         if (net_debug)
 394                 printk(version);
 395 
 396         /* Initialize the device structure. */
 397         dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
 398         memset(dev->priv, 0, sizeof(struct net_local));
 399 
 400         dev->open               = el16_open;
 401         dev->stop               = el16_close;
 402         dev->hard_start_xmit = el16_send_packet;
 403         dev->get_stats  = el16_get_stats;
 404 
 405         ether_setup(dev);       /* Generic ethernet behaviour */
 406 
 407         return 0;
 408 }
 409 
 410 
 411 
 412 static int
 413 el16_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 414 {
 415         irq2dev_map[dev->irq] = dev;
 416 
 417         /* Initialize the 82586 memory and start it. */
 418         init_82586_mem(dev);
 419 
 420         dev->tbusy = 0;
 421         dev->interrupt = 0;
 422         dev->start = 1;
 423         return 0;
 424 }
 425 
 426 static int
 427 el16_send_packet(struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 428 {
 429         struct net_local *lp = (struct net_local *)dev->priv;
 430         int ioaddr = dev->base_addr;
 431         short *shmem = (short*)dev->mem_start;
 432 
 433         if (dev->tbusy) {
 434                 /* If we get here, some higher level has decided we are broken.
 435                    There should really be a "kick me" function call instead. */
 436                 int tickssofar = jiffies - dev->trans_start;
 437                 if (tickssofar < 5)
 438                         return 1;
 439                 if (net_debug > 1)
 440                         printk("%s: transmit timed out, %s?  ", dev->name,
 441                                    shmem[iSCB_STATUS>>1] & 0x8000 ? "IRQ conflict" :
 442                                    "network cable problem");
 443                 /* Try to restart the adaptor. */
 444                 if (lp->last_restart == lp->stats.tx_packets) {
 445                         if (net_debug > 1) printk("Resetting board.\n");
 446                         /* Completely reset the adaptor. */
 447                         init_82586_mem(dev);
 448                 } else {
 449                         /* Issue the channel attention signal and hope it "gets better". */
 450                         if (net_debug > 1) printk("Kicking board.\n");
 451                         shmem[iSCB_CMD>>1] = 0xf000|CUC_START|RX_START;
 452                         outb(0, ioaddr + SIGNAL_CA);                    /* Issue channel-attn. */
 453                         lp->last_restart = lp->stats.tx_packets;
 454                 }
 455                 dev->tbusy=0;
 456                 dev->trans_start = jiffies;
 457         }
 458 
 459         /* If some higher layer thinks we've missed an tx-done interrupt
 460            we are passed NULL. Caution: dev_tint() handles the cli()/sti()
 461            itself. */
 462         if (skb == NULL) {
 463                 dev_tint(dev);
 464                 return 0;
 465         }
 466 
 467         /* Block a timer-based transmit from overlapping. */
 468         if (set_bit(0, (void*)&dev->tbusy) != 0)
 469                 printk("%s: Transmitter access conflict.\n", dev->name);
 470         else {
 471                 short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 472                 unsigned char *buf = skb->data;
 473 
 474                 /* Disable the 82586's input to the interrupt line. */
 475                 outb(0x80, ioaddr + MISC_CTRL);
 476                 hardware_send_packet(dev, buf, length);
 477                 dev->trans_start = jiffies;
 478                 /* Enable the 82586 interrupt input. */
 479                 outb(0x84, ioaddr + MISC_CTRL);
 480         }
 481 
 482         dev_kfree_skb (skb, FREE_WRITE);
 483 
 484         /* You might need to clean up and record Tx statistics here. */
 485 
 486         return 0;
 487 }
 488 
 489 /*      The typical workload of the driver:
 490         Handle the network interface interrupts. */
 491 static void
 492 el16_interrupt(int reg_ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 493 {
 494         int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2);
 495         struct device *dev = (struct device *)(irq2dev_map[irq]);
 496         struct net_local *lp;
 497         int ioaddr, status, boguscount = 0;
 498         ushort ack_cmd = 0;
 499         ushort *shmem;
 500         
 501         if (dev == NULL) {
 502                 printk ("net_interrupt(): irq %d for unknown device.\n", irq);
 503                 return;
 504         }
 505         dev->interrupt = 1;
 506         
 507         ioaddr = dev->base_addr;
 508         lp = (struct net_local *)dev->priv;
 509         shmem = ((ushort*)dev->mem_start);
 510         
 511         status = shmem[iSCB_STATUS>>1];
 512         
 513         if (net_debug > 4) {
 514                 printk("%s: 3c507 interrupt, status %4.4x.\n", dev->name, status);
 515         }
 516 
 517         /* Disable the 82586's input to the interrupt line. */
 518         outb(0x80, ioaddr + MISC_CTRL);
 519 
 520         /* Reap the Tx packet buffers. */
 521         while (lp->tx_reap != lp->tx_head) {
 522           unsigned short tx_status = shmem[lp->tx_reap>>1];
 523 
 524           if (tx_status == 0) {
 525                 if (net_debug > 5)  printk("Couldn't reap %#x.\n", lp->tx_reap);
 526                 break;
 527           }
 528           if (tx_status & 0x2000) {
 529                 lp->stats.tx_packets++;
 530                 lp->stats.collisions += tx_status & 0xf;
 531                 dev->tbusy = 0;
 532                 mark_bh(NET_BH);                /* Inform upper layers. */
 533           } else {
 534                 lp->stats.tx_errors++;
 535                 if (tx_status & 0x0600)  lp->stats.tx_carrier_errors++;
 536                 if (tx_status & 0x0100)  lp->stats.tx_fifo_errors++;
 537                 if (!(tx_status & 0x0040))  lp->stats.tx_heartbeat_errors++;
 538                 if (tx_status & 0x0020)  lp->stats.tx_aborted_errors++;
 539           }
 540           if (net_debug > 5)
 541                   printk("Reaped %x, Tx status %04x.\n" , lp->tx_reap, tx_status);
 542           lp->tx_reap += TX_BUF_SIZE;
 543           if (lp->tx_reap > RX_BUF_START - TX_BUF_SIZE)
 544                 lp->tx_reap = TX_BUF_START;
 545           if (++boguscount > 4)
 546                 break;
 547         }
 548 
 549         if (status & 0x4000) { /* Packet received. */
 550                 if (net_debug > 5)
 551                         printk("Received packet, rx_head %04x.\n", lp->rx_head);
 552                 el16_rx(dev);
 553         }
 554 
 555         /* Acknowledge the interrupt sources. */
 556         ack_cmd = status & 0xf000;
 557 
 558         if ((status & 0x0700) != 0x0200 && dev->start) {
 559                 if (net_debug)
 560                         printk("%s: Command unit stopped, status %04x, restarting.\n",
 561                                    dev->name, status);
 562                 /* If this ever occurs we should really re-write the idle loop, reset
 563                    the Tx list, and do a complete restart of the command unit.
 564                    For now we rely on the Tx timeout if the resume doesn't work. */
 565                 ack_cmd |= CUC_RESUME;
 566         }
 567 
 568         if ((status & 0x0070) != 0x0040  &&  dev->start) {
 569           static void init_rx_bufs(struct device *);
 570                 /* The Rx unit is not ready, it must be hung.  Restart the receiver by
 571                    initializing the rx buffers, and issuing an Rx start command. */
 572                 if (net_debug)
 573                         printk("%s: Rx unit stopped, status %04x, restarting.\n",
 574                                    dev->name, status);
 575                 init_rx_bufs(dev);
 576                 shmem[iSCB_RFA >> 1] = RX_BUF_START;
 577                 ack_cmd |= RX_START;
 578         }
 579 
 580         shmem[iSCB_CMD>>1] = ack_cmd;
 581         outb(0, ioaddr + SIGNAL_CA);                    /* Issue channel-attn. */
 582 
 583         /* Clear the latched interrupt. */
 584         outb(0, ioaddr + RESET_IRQ);
 585 
 586         /* Enable the 82586's interrupt input. */
 587         outb(0x84, ioaddr + MISC_CTRL);
 588 
 589         return;
 590 }
 591 
 592 static int
 593 el16_close(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 594 {
 595         int ioaddr = dev->base_addr;
 596         ushort *shmem = (short*)dev->mem_start;
 597 
 598         dev->tbusy = 1;
 599         dev->start = 0;
 600 
 601         /* Flush the Tx and disable Rx. */
 602         shmem[iSCB_CMD >> 1] = RX_SUSPEND | CUC_SUSPEND;
 603         outb(0, ioaddr + SIGNAL_CA);
 604 
 605         /* Disable the 82586's input to the interrupt line. */
 606         outb(0x80, ioaddr + MISC_CTRL);
 607 
 608         /* We always physically use the IRQ line, so we don't do free_irq().
 609            We do remove ourselves from the map. */
 610 
 611         irq2dev_map[dev->irq] = 0;
 612 
 613         /* Update the statistics here. */
 614 
 615         return 0;
 616 }
 617 
 618 /* Get the current statistics.  This may be called with the card open or
 619    closed. */
 620 static struct enet_statistics *
 621 el16_get_stats(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 622 {
 623         struct net_local *lp = (struct net_local *)dev->priv;
 624 
 625         /* ToDo: decide if there are any useful statistics from the SCB. */
 626 
 627         return &lp->stats;
 628 }
 629 
 630 /* Initialize the Rx-block list. */
 631 static void
 632 init_rx_bufs(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 633 {
 634         struct net_local *lp = (struct net_local *)dev->priv;
 635         unsigned short *write_ptr;
 636         unsigned short SCB_base = SCB_BASE;
 637 
 638         int cur_rxbuf = lp->rx_head = RX_BUF_START;
 639         
 640         /* Initialize each Rx frame + data buffer. */
 641         do {    /* While there is room for one more. */
 642 
 643           write_ptr = (unsigned short *)(dev->mem_start + cur_rxbuf);
 644 
 645                 *write_ptr++ = 0x0000;                          /* Status */
 646                 *write_ptr++ = 0x0000;                          /* Command */
 647                 *write_ptr++ = cur_rxbuf + RX_BUF_SIZE; /* Link */
 648                 *write_ptr++ = cur_rxbuf + 22;          /* Buffer offset */
 649                 *write_ptr++ = 0x0000;                          /* Pad for dest addr. */
 650                 *write_ptr++ = 0x0000;
 651                 *write_ptr++ = 0x0000;
 652                 *write_ptr++ = 0x0000;                          /* Pad for source addr. */
 653                 *write_ptr++ = 0x0000;
 654                 *write_ptr++ = 0x0000;
 655                 *write_ptr++ = 0x0000;                          /* Pad for protocol. */
 656                 
 657                 *write_ptr++ = 0x0000;                          /* Buffer: Actual count */
 658                 *write_ptr++ = -1;                                      /* Buffer: Next (none). */
 659                 *write_ptr++ = cur_rxbuf + 0x20 + SCB_base;     /* Buffer: Address low */
 660                 *write_ptr++ = 0x0000;
 661                 /* Finally, the number of bytes in the buffer. */
 662                 *write_ptr++ = 0x8000 + RX_BUF_SIZE-0x20;
 663                 
 664                 lp->rx_tail = cur_rxbuf;
 665                 cur_rxbuf += RX_BUF_SIZE;
 666         } while (cur_rxbuf <= RX_BUF_END - RX_BUF_SIZE);
 667         
 668         /* Terminate the list by setting the EOL bit, and wrap the pointer to make
 669            the list a ring. */
 670         write_ptr = (unsigned short *)
 671           (dev->mem_start + lp->rx_tail + 2);
 672         *write_ptr++ = 0xC000;                                  /* Command, mark as last. */
 673         *write_ptr++ = lp->rx_head;                             /* Link */
 674 
 675 }
 676 
 677 void
 678 init_82586_mem(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 679 {
 680         struct net_local *lp = (struct net_local *)dev->priv;
 681         short ioaddr = dev->base_addr;
 682         ushort *shmem = (short*)dev->mem_start;
 683 
 684         /* Enable loopback to protect the wire while starting up,
 685            and hold the 586 in reset during the memory initialization. */
 686         outb(0x20, ioaddr + MISC_CTRL);
 687 
 688         /* Fix the ISCP address and base. */
 689         init_words[3] = SCB_BASE;
 690         init_words[7] = SCB_BASE;
 691 
 692         /* Write the words at 0xfff6 (address-aliased to 0xfffff6). */
 693         memcpy((void*)dev->mem_end-10, init_words, 10);
 694 
 695         /* Write the words at 0x0000. */
 696         memcpy((char*)dev->mem_start, init_words + 5, sizeof(init_words) - 10);
 697 
 698         /* Fill in the station address. */
 699         memcpy((char*)dev->mem_start+SA_OFFSET, dev->dev_addr,
 700                    sizeof(dev->dev_addr));
 701 
 702         /* The Tx-block list is written as needed.  We just set up the values. */
 703         lp->tx_cmd_link = IDLELOOP + 4;
 704         lp->tx_head = lp->tx_reap = TX_BUF_START;
 705 
 706         init_rx_bufs(dev);
 707 
 708         /* Start the 586 by releasing the reset line, but leave loopback. */
 709         outb(0xA0, ioaddr + MISC_CTRL);
 710 
 711         /* This was time consuming to track down: you need to give two channel
 712            attention signals to reliably start up the i82586. */
 713         outb(0, ioaddr + SIGNAL_CA);
 714 
 715         {
 716                 int boguscnt = 50;
 717                 while (shmem[iSCB_STATUS>>1] == 0)
 718                         if (--boguscnt == 0) {
 719                                 printk("%s: i82586 initialization timed out with status %04x,"
 720                                            "cmd %04x.\n", dev->name,
 721                                            shmem[iSCB_STATUS>>1], shmem[iSCB_CMD>>1]);
 722                                 break;
 723                         }
 724                 /* Issue channel-attn -- the 82586 won't start. */
 725                 outb(0, ioaddr + SIGNAL_CA);
 726         }
 727 
 728         /* Disable loopback and enable interrupts. */
 729         outb(0x84, ioaddr + MISC_CTRL);
 730         if (net_debug > 4)
 731                 printk("%s: Initialized 82586, status %04x.\n", dev->name,
 732                            shmem[iSCB_STATUS>>1]);
 733         return;
 734 }
 735 
 736 static void
 737 hardware_send_packet(struct device *dev, void *buf, short length)
     /* [previous][next][first][last][top][bottom][index][help] */
 738 {
 739         struct net_local *lp = (struct net_local *)dev->priv;
 740         short ioaddr = dev->base_addr;
 741         ushort tx_block = lp->tx_head;
 742         ushort *write_ptr =       (ushort *)(dev->mem_start + tx_block);
 743 
 744         /* Set the write pointer to the Tx block, and put out the header. */
 745         *write_ptr++ = 0x0000;                          /* Tx status */
 746         *write_ptr++ = CMD_INTR|CmdTx;          /* Tx command */
 747         *write_ptr++ = tx_block+16;                     /* Next command is a NoOp. */
 748         *write_ptr++ = tx_block+8;                      /* Data Buffer offset. */
 749 
 750         /* Output the data buffer descriptor. */
 751         *write_ptr++ = length | 0x8000;         /* Byte count parameter. */
 752         *write_ptr++ = -1;                                      /* No next data buffer. */
 753         *write_ptr++ = tx_block+22+SCB_BASE;/* Buffer follows the NoOp command. */
 754         *write_ptr++ = 0x0000;                          /* Buffer address high bits (always zero). */
 755 
 756         /* Output the Loop-back NoOp command. */
 757         *write_ptr++ = 0x0000;                          /* Tx status */
 758         *write_ptr++ = CmdNOp;                          /* Tx command */
 759         *write_ptr++ = tx_block+16;                     /* Next is myself. */
 760 
 761         /* Output the packet at the write pointer. */
 762         memcpy(write_ptr, buf, length);
 763 
 764         /* Set the old command link pointing to this send packet. */
 765         *(ushort*)(dev->mem_start + lp->tx_cmd_link) = tx_block;
 766         lp->tx_cmd_link = tx_block + 20;
 767 
 768         /* Set the next free tx region. */
 769         lp->tx_head = tx_block + TX_BUF_SIZE;
 770         if (lp->tx_head > RX_BUF_START - TX_BUF_SIZE)
 771                 lp->tx_head = TX_BUF_START;
 772 
 773         if (net_debug > 4) {
 774                 printk("%s: 3c507 @%x send length = %d, tx_block %3x, next %3x.\n",
 775                            dev->name, ioaddr, length, tx_block, lp->tx_head);
 776         }
 777 
 778         if (lp->tx_head != lp->tx_reap)
 779                 dev->tbusy = 0;
 780 }
 781 
 782 static void
 783 el16_rx(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 784 {
 785         struct net_local *lp = (struct net_local *)dev->priv;
 786         short *shmem = (short*)dev->mem_start;
 787         ushort rx_head = lp->rx_head;
 788         ushort rx_tail = lp->rx_tail;
 789         ushort boguscount = 10;
 790         short frame_status;
 791 
 792         while ((frame_status = shmem[rx_head>>1]) < 0) {   /* Command complete */
 793                 ushort *read_frame =  (short *)(dev->mem_start + rx_head);
 794                 ushort rfd_cmd = read_frame[1];
 795                 ushort next_rx_frame = read_frame[2];
 796                 ushort data_buffer_addr = read_frame[3];
 797                 ushort *data_frame = (short *)(dev->mem_start + data_buffer_addr);
 798                 ushort pkt_len = data_frame[0];
 799 
 800                 if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22
 801                         || pkt_len & 0xC000 != 0xC000) {
 802                         printk("%s: Rx frame at %#x corrupted, status %04x cmd %04x"
 803                                    "next %04x data-buf @%04x %04x.\n", dev->name, rx_head,
 804                                    frame_status, rfd_cmd, next_rx_frame, data_buffer_addr,
 805                                    pkt_len);
 806                 } else if ((frame_status & 0x2000) == 0) {
 807                         /* Frame Rxed, but with error. */
 808                         lp->stats.rx_errors++;
 809                         if (frame_status & 0x0800) lp->stats.rx_crc_errors++;
 810                         if (frame_status & 0x0400) lp->stats.rx_frame_errors++;
 811                         if (frame_status & 0x0200) lp->stats.rx_fifo_errors++;
 812                         if (frame_status & 0x0100) lp->stats.rx_over_errors++;
 813                         if (frame_status & 0x0080) lp->stats.rx_length_errors++;
 814                 } else {
 815                         /* Malloc up new buffer. */
 816                         struct sk_buff *skb;
 817 
 818                         pkt_len &= 0x3fff;
 819                         skb = alloc_skb(pkt_len, GFP_ATOMIC);
 820                         if (skb == NULL) {
 821                                 printk("%s: Memory squeeze, dropping packet.\n", dev->name);
 822                                 lp->stats.rx_dropped++;
 823                                 break;
 824                         }
 825                         skb->len = pkt_len;
 826                         skb->dev = dev;
 827 
 828                         /* 'skb->data' points to the start of sk_buff data area. */
 829                         memcpy(skb->data, data_frame + 5, pkt_len);
 830                 
 831                         netif_rx(skb);
 832                         lp->stats.rx_packets++;
 833                 }
 834 
 835                 /* Clear the status word and set End-of-List on the rx frame. */
 836                 read_frame[0] = 0;
 837                 read_frame[1] = 0xC000;
 838                 /* Clear the end-of-list on the prev. RFD. */
 839                 *(short*)(dev->mem_start + rx_tail + 2) = 0x0000;
 840 
 841                 rx_tail = rx_head;
 842                 rx_head = next_rx_frame;
 843                 if (--boguscount == 0)
 844                         break;
 845         }
 846 
 847         lp->rx_head = rx_head;
 848         lp->rx_tail = rx_tail;
 849 }
 850 
 851 /*
 852  * Local variables:
 853  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -I/usr/src/linux/drivers/net -Wall -Wstrict-prototypes -O6 -m486 -c 3c507.c"
 854  *  version-control: t
 855  *  kept-new-versions: 5
 856  *  tab-width: 4
 857  *  c-indent-level: 4
 858  * End:
 859  */
 860 

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