root/drivers/net/atp.c

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

DEFINITIONS

This source file includes following definitions.
  1. atp_init
  2. atp_probe1
  3. get_node_ID
  4. eeprom_op
  5. net_open
  6. hardware_init
  7. trigger_send
  8. write_packet
  9. net_send_packet
  10. net_interrupt
  11. net_rx
  12. read_block
  13. net_close
  14. net_get_stats
  15. set_multicast_list

   1 /* atp.c: Attached (pocket) ethernet adaptor 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 */
  13 
  14 static char *version =
  15         "atp.c:v0.04 2/25/94 Donald Becker (becker@super.org)\n";
  16 
  17 /*
  18         This file is a device driver for the RealTek (aka AT-Lan-Tec) pocket
  19         ethernet adaptor.  This is a common low-cost OEM pocket ethernet
  20         adaptor, sold under many names.
  21 
  22   Sources:
  23         This driver was written from the packet driver assembly code provided by
  24         Vincent Bono of AT-Lan-Tec.      Ever try to figure out how a complicated
  25         device works just from the assembly code?  It ain't pretty.  The following
  26         description is written based on guesses and writing lots of special-purpose
  27         code to test my theorized operation.
  28 
  29                                         Theory of Operation
  30         
  31         The RTL8002 adaptor seems to be built around a custom spin of the SEEQ
  32         controller core.  It probably has a 16K or 64K internal packet buffer, of
  33         which the first 4K is devoted to transmit and the rest to receive.
  34         The controller maintains the queue of received packet and the packet buffer
  35         access pointer internally, with only 'reset to beginning' and 'skip to next
  36         packet' commands visible.  The transmit packet queue holds two (or more?)
  37         packets: both 'retransmit this packet' (due to collision) and 'transmit next
  38         packet' commands must be started by hand.
  39 
  40         The station address is stored in a standard bit-serial EEPROM which must be
  41         read (ughh) by the device driver.  (Provisions have been made for
  42         substituting a 74S288 PROM, but I haven't gotten reports of any models
  43         using it.)  Unlike built-in devices, a pocket adaptor can temporarily lose
  44         power without indication to the device driver.  The major effect is that
  45         the station address, receive filter (promiscuous, etc.) and transceiver
  46         must be reset.
  47 
  48         The controller itself has 16 registers, some of which use only the lower
  49         bits.  The registers are read and written 4 bits at a time.  The four bit
  50         register address is presented on the data lines along with a few additional
  51         timing and control bits.  The data is then read from status port or written
  52         to the data port.
  53 
  54         Since the bulk data transfer of the actual packets through the slow
  55         parallel port dominates the driver's running time, four distinct data
  56         (non-register) transfer modes are provided by the adaptor, two in each
  57         direction.  In the first mode timing for the nibble transfers is
  58         provided through the data port.  In the second mode the same timing is
  59         provided through the control port.  In either case the data is read from
  60         the status port and written to the data port, just as it is accessing
  61         registers.
  62 
  63         In addition to the basic data transfer methods, several more are modes are
  64         created by adding some delay by doing multiple reads of the data to allow
  65         it to stabilize.  This delay seems to be needed on most machines.
  66 
  67         The data transfer mode is stored in the 'dev->if_port' field.  Its default
  68         value is '4'.  It may be overriden at boot-time using the third parameter
  69         to the "ether=..." initialization.
  70 
  71         The header file <atp.h> provides inline functions that encapsulate the
  72         register and data access methods.  These functions are hand-tuned to
  73         generate reasonable object code.  This header file also documents my
  74         interpretations of the device registers.
  75 */
  76 
  77 #include <linux/config.h>               /* Used only to override default values. */
  78 #include <linux/kernel.h>
  79 #include <linux/sched.h>
  80 #include <linux/types.h>
  81 #include <linux/fcntl.h>
  82 #include <linux/interrupt.h>
  83 #include <linux/ptrace.h>
  84 #include <linux/ioport.h>
  85 #include <linux/in.h>
  86 #include <linux/malloc.h>
  87 #include <linux/string.h>
  88 #include <asm/system.h>
  89 #include <asm/bitops.h>
  90 #include <asm/io.h>
  91 #include <asm/dma.h>
  92 #include <errno.h>
  93 
  94 #include <linux/netdevice.h>
  95 #include <linux/etherdevice.h>
  96 #include <linux/skbuff.h>
  97 
  98 #include "atp.h"
  99 
 100 /* Compatibility definitions for earlier kernel versions. */
 101 #ifndef HAVE_AUTOIRQ
 102 /* From auto_irq.c, in ioport.h for later versions. */
 103 extern void autoirq_setup(int waittime);
 104 extern int autoirq_report(int waittime);
 105 /* The map from IRQ number (as passed to the interrupt handler) to
 106    'struct device'. */
 107 extern struct device *irq2dev_map[16];
 108 #endif
 109 
 110 #ifndef HAVE_ALLOC_SKB
 111 #define alloc_skb(size, priority) (struct sk_buff *) kmalloc(size,priority)
 112 #define kfree_skbmem(addr, size) kfree_s(addr,size);
 113 #endif
 114 
 115 #ifndef HAVE_PORTRESERVE
 116 #define check_region(ioaddr, size)              0
 117 #define snarf_region(ioaddr, size);             do ; while (0)
 118 #endif
 119 
 120 /* use 0 for production, 1 for verification, >2 for debug */
 121 #ifndef NET_DEBUG
 122 #define NET_DEBUG 4
 123 #endif
 124 static unsigned int net_debug = NET_DEBUG;
 125 
 126 /* The number of low I/O ports used by the ethercard. */
 127 #define ETHERCARD_TOTAL_SIZE    3
 128 
 129 /* Index to functions, as function prototypes. */
 130 
 131 extern int atp_probe(struct device *dev);
 132 
 133 static int atp_probe1(struct device *dev, short ioaddr);
 134 static void get_node_ID(struct device *dev);
 135 static unsigned short eeprom_op(short ioaddr, unsigned int cmd);
 136 static int net_open(struct device *dev);
 137 static void hardware_init(struct device *dev);
 138 static void write_packet(short ioaddr, int length, unsigned char *packet, int mode);
 139 static void trigger_send(short ioaddr, int length);
 140 static int      net_send_packet(struct sk_buff *skb, struct device *dev);
 141 static void net_interrupt(int reg_ptr);
 142 static void net_rx(struct device *dev);
 143 static void read_block(short ioaddr, int length, unsigned char *buffer, int data_mode);
 144 static int net_close(struct device *dev);
 145 static struct enet_statistics *net_get_stats(struct device *dev);
 146 static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
 147 
 148 
 149 /* Check for a network adaptor of this type, and return '0' iff one exists.
 150    If dev->base_addr == 0, probe all likely locations.
 151    If dev->base_addr == 1, always return failure.
 152    If dev->base_addr == 2, alloate space for the device and return success
 153    (detachable devices only).
 154    */
 155 int
 156 atp_init(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 157 {
 158         int *port, ports[] = {0x378, 0x278, 0x3bc, 0};
 159         int base_addr = dev->base_addr;
 160 
 161         if (base_addr > 0x1ff)          /* Check a single specified location. */
 162                 return atp_probe1(dev, base_addr);
 163         else if (base_addr == 1)        /* Don't probe at all. */
 164                 return ENXIO;
 165 
 166         for (port = ports; *port; port++) {
 167                 int ioaddr = *port;
 168                 outb(0x57, ioaddr + PAR_DATA);
 169                 if (inb(ioaddr + PAR_DATA) != 0x57)
 170                         continue;
 171                 if (atp_probe1(dev, ioaddr) == 0)
 172                         return 0;
 173         }
 174 
 175         return ENODEV;
 176 }
 177 
 178 static int atp_probe1(struct device *dev, short ioaddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 179 {
 180         int saved_ctrl_reg, status;
 181 
 182         outb(0xff, ioaddr + PAR_DATA);
 183         /* Save the original value of the Control register, in case we guessed
 184            wrong. */
 185         saved_ctrl_reg = inb(ioaddr + PAR_CONTROL);
 186         /* IRQEN=0, SLCTB=high INITB=high, AUTOFDB=high, STBB=high. */
 187         outb(0x04, ioaddr + PAR_CONTROL);
 188         write_reg_high(ioaddr, CMR1, CMR1h_RESET);
 189         eeprom_delay(2048);
 190         status = read_nibble(ioaddr, CMR1);
 191 
 192         if ((status & 0x78) != 0x08) {
 193                 /* The pocket adaptor probe failed, restore the control register. */
 194                 outb(saved_ctrl_reg, ioaddr + PAR_CONTROL);
 195                 return 1;
 196         }
 197         status = read_nibble(ioaddr, CMR2_h);
 198         if ((status & 0x78) != 0x10) {
 199                 outb(saved_ctrl_reg, ioaddr + PAR_CONTROL);
 200                 return 1;
 201         }
 202         /* Find the IRQ used by triggering an interrupt. */
 203         write_reg_byte(ioaddr, CMR2, 0x01);                     /* No accept mode, IRQ out. */
 204         write_reg_high(ioaddr, CMR1, CMR1h_RxENABLE | CMR1h_TxENABLE);  /* Enable Tx and Rx. */
 205 
 206         /* Omit autoIRQ routine for now. Use "table lookup" instead.  Uhgggh. */
 207         if (ioaddr == 0x378)
 208                 dev->irq = 7;
 209         else
 210                 dev->irq = 5;
 211         write_reg_high(ioaddr, CMR1, CMR1h_TxRxOFF); /* Diable Tx and Rx units. */
 212         write_reg(ioaddr, CMR2, CMR2_NULL);
 213 
 214         dev->base_addr = ioaddr;
 215 
 216         /* Read the station address PROM.  */
 217         get_node_ID(dev);
 218 
 219         printk("%s: Pocket adaptor found at %#3x, IRQ %d, SAPROM "
 220                    "%02X:%02X:%02X:%02X:%02X:%02X.\n", dev->name, dev->base_addr,
 221                    dev->irq, dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
 222                    dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
 223 
 224         /* Leave the hardware in a reset state. */
 225     write_reg_high(ioaddr, CMR1, CMR1h_RESET);
 226 
 227         if (net_debug)
 228                 printk(version);
 229 
 230         /* Initialize the device structure. */
 231         ether_setup(dev);
 232         dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
 233         memset(dev->priv, 0, sizeof(struct net_local));
 234 
 235 
 236         {
 237                 struct net_local *lp = (struct net_local *)dev->priv;
 238                 lp->addr_mode = CMR2h_Normal;
 239         }
 240 
 241         /* For the ATP adaptor the "if_port" is really the data transfer mode. */
 242         dev->if_port = (dev->mem_start & 0xf) ? dev->mem_start & 0x7 : 4;
 243         if (dev->mem_end & 0xf)
 244                 net_debug = dev->mem_end & 7;
 245 
 246         dev->open               = net_open;
 247         dev->stop               = net_close;
 248         dev->hard_start_xmit = net_send_packet;
 249         dev->get_stats  = net_get_stats;
 250         dev->set_multicast_list = &set_multicast_list;
 251 
 252         return 0;
 253 }
 254 
 255 /* Read the station address PROM, usually a word-wide EEPROM. */
 256 static void get_node_ID(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 257 {
 258         short ioaddr = dev->base_addr;
 259         int sa_offset = 0;
 260         int i;
 261         
 262         write_reg(ioaddr, CMR2, CMR2_EEPROM);     /* Point to the EEPROM control registers. */
 263         
 264         /* Some adaptors have the station address at offset 15 instead of offset
 265            zero.  Check for it, and fix it if needed. */
 266         if (eeprom_op(ioaddr, EE_READ(0)) == 0xffff)
 267                 sa_offset = 15;
 268         
 269         for (i = 0; i < 3; i++)
 270                 ((unsigned short *)dev->dev_addr)[i] =
 271                         ntohs(eeprom_op(ioaddr, EE_READ(sa_offset + i)));
 272         
 273         write_reg(ioaddr, CMR2, CMR2_NULL);
 274 }
 275 
 276 /*
 277   An EEPROM read command starts by shifting out 0x60+address, and then
 278   shifting in the serial data. See the NatSemi databook for details.
 279  *                 ________________
 280  * CS : __|
 281  *                         ___     ___
 282  * CLK: ______|   |___|   |
 283  *               __ _______ _______
 284  * DI :  __X_______X_______X
 285  * DO :  _________X_______X
 286  */
 287 
 288 static unsigned short eeprom_op(short ioaddr, unsigned int cmd)
     /* [previous][next][first][last][top][bottom][index][help] */
 289 {
 290         unsigned eedata_out = 0;
 291         int num_bits = EE_CMD_SIZE;
 292         
 293         while (--num_bits >= 0) {
 294                 char outval = test_bit(num_bits, &cmd) ? EE_DATA_WRITE : 0;
 295                 write_reg_high(ioaddr, PROM_CMD, outval | EE_CLK_LOW);
 296                 eeprom_delay(5);
 297                 write_reg_high(ioaddr, PROM_CMD, outval | EE_CLK_HIGH);
 298                 eedata_out <<= 1;
 299                 if (read_nibble(ioaddr, PROM_DATA) & EE_DATA_READ)
 300                         eedata_out++;
 301                 eeprom_delay(5);
 302         }
 303         write_reg_high(ioaddr, PROM_CMD, EE_CLK_LOW & ~EE_CS);
 304         return eedata_out;
 305 }
 306 
 307 
 308 /* Open/initialize the board.  This is called (in the current kernel)
 309    sometime after booting when the 'ifconfig' program is run.
 310 
 311    This routine sets everything up anew at each open, even
 312    registers that "should" only need to be set once at boot, so that
 313    there is non-reboot way to recover if something goes wrong.
 314 
 315    This is an attachable device: if there is no dev->priv entry then it wasn't
 316    probed for at boot-time, and we need to probe for it again.
 317    */
 318 static int net_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 319 {
 320 
 321         /* The interrupt line is turned off (tri-stated) when the device isn't in
 322            use.  That's especially important for "attached" interfaces where the
 323            port or interrupt may be shared. */
 324         if (irq2dev_map[dev->irq] != 0
 325                 || (irq2dev_map[dev->irq] = dev) == 0
 326                 || request_irq(dev->irq, &net_interrupt)) {
 327                 return -EAGAIN;
 328         }
 329 
 330         hardware_init(dev);
 331         dev->start = 1;
 332         return 0;
 333 }
 334 
 335 /* This routine resets the hardware.  We initialize everything, assuming that
 336    the hardware may have been temporarily detacted. */
 337 static void hardware_init(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 338 {
 339         struct net_local *lp = (struct net_local *)dev->priv;
 340         int ioaddr = dev->base_addr;
 341     int i;
 342 
 343         write_reg_high(ioaddr, CMR1, CMR1h_RESET);
 344         
 345     for (i = 0; i < 6; i++)
 346                 write_reg_byte(ioaddr, PAR0 + i, dev->dev_addr[i]);
 347 
 348         write_reg_high(ioaddr, CMR2, lp->addr_mode);
 349 
 350         if (net_debug > 2) {
 351                 printk("%s: Reset: current Rx mode %d.\n", dev->name,
 352                            (read_nibble(ioaddr, CMR2_h) >> 3) & 0x0f);
 353         }
 354 
 355     write_reg(ioaddr, CMR2, CMR2_IRQOUT);
 356     write_reg_high(ioaddr, CMR1, CMR1h_RxENABLE | CMR1h_TxENABLE);
 357 
 358         /* Enable the interrupt line from the serial port. */
 359         outb(Ctrl_SelData + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
 360 
 361         /* Unmask the interesting interrupts. */
 362     write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
 363     write_reg_high(ioaddr, IMR, ISRh_RxErr);
 364 
 365         lp->tx_unit_busy = 0;
 366     lp->pac_cnt_in_tx_buf = 0;
 367         lp->saved_tx_size = 0;
 368 
 369         dev->tbusy = 0;
 370         dev->interrupt = 0;
 371 }
 372 
 373 static void trigger_send(short ioaddr, int length)
     /* [previous][next][first][last][top][bottom][index][help] */
 374 {
 375         write_reg_byte(ioaddr, TxCNT0, length & 0xff);
 376         write_reg(ioaddr, TxCNT1, length >> 8);
 377         write_reg(ioaddr, CMR1, CMR1_Xmit);
 378 }
 379 
 380 static void write_packet(short ioaddr, int length, unsigned char *packet, int data_mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 381 {
 382     length = (length + 1) & ~1;         /* Round up to word length. */
 383     outb(EOC+MAR, ioaddr + PAR_DATA);
 384     if ((data_mode & 1) == 0) {
 385                 /* Write the packet out, starting with the write addr. */
 386                 outb(WrAddr+MAR, ioaddr + PAR_DATA);
 387                 do {
 388                         write_byte_mode0(ioaddr, *packet++);
 389                 } while (--length > 0) ;
 390     } else {
 391                 /* Write the packet out in slow mode. */
 392                 unsigned char outbyte = *packet++;
 393 
 394                 outb(Ctrl_LNibWrite + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
 395                 outb(WrAddr+MAR, ioaddr + PAR_DATA);
 396 
 397                 outb((outbyte & 0x0f)|0x40, ioaddr + PAR_DATA);
 398                 outb(outbyte & 0x0f, ioaddr + PAR_DATA);
 399                 outbyte >>= 4;
 400                 outb(outbyte & 0x0f, ioaddr + PAR_DATA);
 401                 outb(Ctrl_HNibWrite + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
 402                 while (--length > 0)
 403                         write_byte_mode1(ioaddr, *packet++);
 404     }
 405     /* Terminate the Tx frame.  End of write: ECB. */
 406     outb(0xff, ioaddr + PAR_DATA);
 407     outb(Ctrl_HNibWrite | Ctrl_SelData | Ctrl_IRQEN, ioaddr + PAR_CONTROL);
 408 }
 409 
 410 static int
 411 net_send_packet(struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 412 {
 413         struct net_local *lp = (struct net_local *)dev->priv;
 414         int ioaddr = dev->base_addr;
 415 
 416         if (dev->tbusy) {
 417                 /* If we get here, some higher level has decided we are broken.
 418                    There should really be a "kick me" function call instead. */
 419                 int tickssofar = jiffies - dev->trans_start;
 420                 if (tickssofar < 5)
 421                         return 1;
 422                 printk("%s: transmit timed out, %s?\n", dev->name,
 423                            inb(ioaddr + PAR_CONTROL) & 0x10 ? "network cable problem"
 424                            :  "IRQ conflict");
 425                 lp->stats.tx_errors++;
 426                 /* Try to restart the adaptor. */
 427                 hardware_init(dev);
 428                 dev->tbusy=0;
 429                 dev->trans_start = jiffies;
 430         }
 431 
 432         /* If some higher layer thinks we've missed an tx-done interrupt
 433            we are passed NULL. Caution: dev_tint() handles the cli()/sti()
 434            itself. */
 435         if (skb == NULL) {
 436                 dev_tint(dev);
 437                 return 0;
 438         }
 439 
 440         /* Block a timer-based transmit from overlapping.  This could better be
 441            done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
 442         if (set_bit(0, (void*)&dev->tbusy) != 0)
 443                 printk("%s: Transmitter access conflict.\n", dev->name);
 444         else {
 445                 short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 446                 unsigned char *buf = skb->data;
 447                 int flags;
 448 
 449                 /* Disable interrupts by writing 0x00 to the Interrupt Mask Register.
 450                    This sequence must not be interrupted by an incoming packet. */
 451                 save_flags(flags);
 452                 cli();
 453                 write_reg(ioaddr, IMR, 0);
 454                 write_reg_high(ioaddr, IMR, 0);
 455                 restore_flags(flags);
 456 
 457                 write_packet(ioaddr, length, buf, dev->if_port);
 458 
 459                 lp->pac_cnt_in_tx_buf++;
 460                 if (lp->tx_unit_busy == 0) {
 461                         trigger_send(ioaddr, length);
 462                         lp->saved_tx_size = 0;                          /* Redundent */
 463                         lp->re_tx = 0;
 464                         lp->tx_unit_busy = 1;
 465                 } else
 466                         lp->saved_tx_size = length;
 467 
 468                 dev->trans_start = jiffies;
 469                 /* Re-enable the LPT interrupts. */
 470                 write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
 471                 write_reg_high(ioaddr, IMR, ISRh_RxErr);
 472         }
 473 
 474         if (skb->free)
 475                 kfree_skb (skb, FREE_WRITE);
 476 
 477         return 0;
 478 }
 479 
 480 /* The typical workload of the driver:
 481    Handle the network interface interrupts. */
 482 static void
 483 net_interrupt(int reg_ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 484 {
 485         int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2);
 486         struct device *dev = (struct device *)(irq2dev_map[irq]);
 487         struct net_local *lp;
 488         int ioaddr, status, boguscount = 20;
 489         static int num_tx_since_rx = 0;
 490 
 491         if (dev == NULL) {
 492                 printk ("ATP_interrupt(): irq %d for unknown device.\n", irq);
 493                 return;
 494         }
 495         dev->interrupt = 1;
 496 
 497         ioaddr = dev->base_addr;
 498         lp = (struct net_local *)dev->priv;
 499 
 500         /* Disable additional spurious interrupts. */
 501         outb(Ctrl_SelData, ioaddr + PAR_CONTROL);
 502 
 503         /* The adaptor's output is currently the IRQ line, switch it to data. */
 504         write_reg(ioaddr, CMR2, CMR2_NULL);
 505         write_reg(ioaddr, IMR, 0);
 506 
 507         if (net_debug > 5) printk("%s: In interrupt ", dev->name);
 508     while (--boguscount > 0) {
 509                 status = read_nibble(ioaddr, ISR);
 510                 if (net_debug > 5) printk("loop status %02x..", status);
 511 
 512                 if (status & (ISR_RxOK<<3)) {
 513                         write_reg(ioaddr, ISR, ISR_RxOK); /* Clear the Rx interrupt. */
 514                         do {
 515                                 int read_status = read_nibble(ioaddr, CMR1);
 516                                 if (net_debug > 6)
 517                                         printk("handling Rx packet %02x..", read_status);
 518                                 /* We acknowledged the normal Rx interrupt, so if the interrupt
 519                                    is still outstanding we must have a Rx error. */
 520                                 if (read_status & (CMR1_IRQ << 3)) { /* Overrun. */
 521                                         lp->stats.rx_over_errors++;
 522                                         /* Set to no-accept mode long enough to remove a packet. */
 523                                         write_reg_high(ioaddr, CMR2, CMR2h_OFF);
 524                                         net_rx(dev);
 525                                         /* Clear the interrupt and return to normal Rx mode. */
 526                                         write_reg_high(ioaddr, ISR, ISRh_RxErr);
 527                                         write_reg_high(ioaddr, CMR2, lp->addr_mode);
 528                                 } else if ((read_status & (CMR1_BufEnb << 3)) == 0) {
 529                                         net_rx(dev);
 530                                         dev->last_rx = jiffies;
 531                                         num_tx_since_rx = 0;
 532                                 } else
 533                                         break;
 534                         } while (--boguscount > 0);
 535                 } else if (status & ((ISR_TxErr + ISR_TxOK)<<3)) {
 536                         if (net_debug > 6)  printk("handling Tx done..");
 537                         /* Clear the Tx interrupt.  We should check for too many failures
 538                            and reinitialize the adaptor. */
 539                         write_reg(ioaddr, ISR, ISR_TxErr + ISR_TxOK);
 540                         if (status & (ISR_TxErr<<3)) {
 541                                 lp->stats.collisions++;
 542                                 if (++lp->re_tx > 15) {
 543                                         lp->stats.tx_aborted_errors++;
 544                                         hardware_init(dev);
 545                                         break;
 546                                 }
 547                                 /* Attempt to retransmit. */
 548                                 if (net_debug > 6)  printk("attempting to ReTx");
 549                                 write_reg(ioaddr, CMR1, CMR1_ReXmit + CMR1_Xmit);
 550                         } else {
 551                                 /* Finish up the transmit. */
 552                                 lp->stats.tx_packets++;
 553                                 lp->pac_cnt_in_tx_buf--;
 554                                 if ( lp->saved_tx_size) {
 555                                         trigger_send(ioaddr, lp->saved_tx_size);
 556                                         lp->saved_tx_size = 0;
 557                                         lp->re_tx = 0;
 558                                 } else
 559                                         lp->tx_unit_busy = 0;
 560                                 dev->tbusy = 0;
 561                                 mark_bh(NET_BH);        /* Inform upper layers. */
 562                         }
 563                         num_tx_since_rx++;
 564                 } else if (num_tx_since_rx > 8
 565                                    && jiffies > dev->last_rx + 100) {
 566                         if (net_debug > 2)
 567                                 printk("%s: Missed packet? No Rx after %d Tx and %ld jiffies"
 568                                            " status %02x  CMR1 %02x.\n", dev->name,
 569                                            num_tx_since_rx, jiffies - dev->last_rx, status,
 570                                            (read_nibble(ioaddr, CMR1) >> 3) & 15);
 571                         lp->stats.rx_missed_errors++;
 572                         hardware_init(dev);
 573                         num_tx_since_rx = 0;
 574                         break;
 575                 } else
 576                         break;
 577     }
 578 
 579         /* This following code fixes a rare (and very difficult to track down)
 580            problem where the adaptor forgets its ethernet address. */
 581         {
 582                 int i;
 583                 for (i = 0; i < 6; i++)
 584                         write_reg_byte(ioaddr, PAR0 + i, dev->dev_addr[i]);
 585         }
 586 
 587         /* Tell the adaptor that it can go back to using the output line as IRQ. */
 588     write_reg(ioaddr, CMR2, CMR2_IRQOUT);
 589         /* Enable the physical interrupt line, which is sure to be low until.. */
 590         outb(Ctrl_SelData + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
 591         /* .. we enable the interrupt sources. */
 592         write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
 593         write_reg_high(ioaddr, IMR, ISRh_RxErr);                        /* Hmmm, really needed? */
 594 
 595         if (net_debug > 5) printk("exiting interrupt.\n");
 596 
 597         dev->interrupt = 0;
 598 
 599         return;
 600 }
 601 
 602 /* We have a good packet(s), get it/them out of the buffers. */
 603 static void net_rx(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 604 {
 605         struct net_local *lp = (struct net_local *)dev->priv;
 606         int ioaddr = dev->base_addr;
 607 #ifdef notdef
 608         ushort header[4];
 609 #else
 610         struct rx_header rx_head;
 611 #endif
 612 
 613         /* Process the received packet. */
 614         outb(EOC+MAR, ioaddr + PAR_DATA);
 615         read_block(ioaddr, 8, (unsigned char*)&rx_head, dev->if_port);
 616         if (net_debug > 5)
 617                 printk(" rx_count %04x %04x %04x %04x..", rx_head.pad,
 618                            rx_head.rx_count, rx_head.rx_status, rx_head.cur_addr);
 619         if ((rx_head.rx_status & 0x77) != 0x01) {
 620                 lp->stats.rx_errors++;
 621                 /* Ackkk!  I don't have any documentation on what the error bits mean!
 622                    The best I can do is slap the device around a bit. */
 623                 if (net_debug > 3) printk("%s: Unknown ATP Rx error %04x.\n",
 624                                                                   dev->name, rx_head.rx_status);
 625                 hardware_init(dev);
 626                 return;
 627         } else {
 628                 /* Malloc up new buffer. */
 629                 int pkt_len = (rx_head.rx_count & 0x7ff) - 4;           /* The "-4" is omits the FCS (CRC). */
 630                 struct sk_buff *skb;
 631                 
 632                 skb = alloc_skb(pkt_len, GFP_ATOMIC);
 633                 if (skb == NULL) {
 634                         printk("%s: Memory squeeze, dropping packet.\n", dev->name);
 635                         lp->stats.rx_dropped++;
 636                         goto done;
 637                 }
 638                 skb->len = pkt_len;
 639                 skb->dev = dev;
 640                 
 641                 read_block(ioaddr, pkt_len, skb->data, dev->if_port);
 642 
 643                 if (net_debug > 6) {
 644                         unsigned char *data = skb->data;
 645                         printk(" data %02x%02x%02x %02x%02x%02x %02x%02x%02x"
 646                                    "%02x%02x%02x %02x%02x..",
 647                                    data[0], data[1], data[2], data[3], data[4], data[5],
 648                                    data[6], data[7], data[8], data[9], data[10], data[11],
 649                                    data[12], data[13]);
 650                 }
 651                 
 652                 netif_rx(skb);
 653                 lp->stats.rx_packets++;
 654         }
 655  done:
 656         write_reg(ioaddr, CMR1, CMR1_NextPkt);
 657         return;
 658 }
 659 
 660 static void read_block(short ioaddr, int length, unsigned char *p, int data_mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 661 {
 662 
 663         if (data_mode <= 3) { /* Mode 0 or 1 */
 664                 outb(Ctrl_LNibRead, ioaddr + PAR_CONTROL);
 665                 outb(length == 8  ?  RdAddr | HNib | MAR  :  RdAddr | MAR,
 666                          ioaddr + PAR_DATA);
 667                 if (data_mode <= 1) { /* Mode 0 or 1 */
 668                         do  *p++ = read_byte_mode0(ioaddr);  while (--length > 0);
 669                 } else  /* Mode 2 or 3 */
 670                         do  *p++ = read_byte_mode2(ioaddr);  while (--length > 0);
 671         } else if (data_mode <= 5)
 672                 do      *p++ = read_byte_mode4(ioaddr);  while (--length > 0);
 673         else
 674                 do      *p++ = read_byte_mode6(ioaddr);  while (--length > 0);
 675 
 676     outb(EOC+HNib+MAR, ioaddr + PAR_DATA);
 677         outb(Ctrl_SelData, ioaddr + PAR_CONTROL);
 678 }
 679 
 680 /* The inverse routine to net_open(). */
 681 static int
 682 net_close(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 683 {
 684         struct net_local *lp = (struct net_local *)dev->priv;
 685         int ioaddr = dev->base_addr;
 686 
 687         dev->tbusy = 1;
 688         dev->start = 0;
 689 
 690         /* Flush the Tx and disable Rx here. */
 691         lp->addr_mode = CMR2h_OFF;
 692         write_reg_high(ioaddr, CMR2, CMR2h_OFF);
 693 
 694         /* Free the IRQ line. */
 695         outb(0x00, ioaddr + PAR_CONTROL);
 696         free_irq(dev->irq);
 697         irq2dev_map[dev->irq] = 0;
 698 
 699         /* Leave the hardware in a reset state. */
 700     write_reg_high(ioaddr, CMR1, CMR1h_RESET);
 701 
 702         return 0;
 703 }
 704 
 705 /* Get the current statistics.  This may be called with the card open or
 706    closed. */
 707 static struct enet_statistics *
 708 net_get_stats(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 709 {
 710         struct net_local *lp = (struct net_local *)dev->priv;
 711         return &lp->stats;
 712 }
 713 
 714 /* Set or clear the multicast filter for this adaptor.
 715    num_addrs == -1      Promiscuous mode, receive all packets
 716    num_addrs == 0       Normal mode, clear multicast list
 717    num_addrs > 0        Multicast mode, receive normal and MC packets, and do
 718                         best-effort filtering.
 719  */
 720 static void
 721 set_multicast_list(struct device *dev, int num_addrs, void *addrs)
     /* [previous][next][first][last][top][bottom][index][help] */
 722 {
 723         struct net_local *lp = (struct net_local *)dev->priv;
 724         short ioaddr = dev->base_addr;
 725         lp->addr_mode = num_addrs ? CMR2h_PROMISC : CMR2h_Normal;
 726         write_reg_high(ioaddr, CMR2, lp->addr_mode);
 727 }
 728 
 729 /*
 730  * Local variables:
 731  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c atp.c"
 732  *  version-control: t
 733  *  kept-new-versions: 5
 734  *  tab-width: 4
 735  * End:
 736  */

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