root/drivers/net/at1700.c

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

DEFINITIONS

This source file includes following definitions.
  1. at1700_probe
  2. at1700_probe1
  3. read_eeprom
  4. net_open
  5. net_send_packet
  6. net_interrupt
  7. net_rx
  8. net_close
  9. net_get_stats
  10. set_multicast_list

   1 /* at1700.c: A network device driver for  the Allied Telesis AT1700.
   2 
   3    Written 1993 by Donald Becker.  This is a alpha test limited release.
   4    This version may only be used and distributed according to the terms of the
   5    GNU Public License, incorporated herein by reference.
   6 
   7    The author may be reached as becker@super.org or
   8    C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
   9 
  10    This is a device driver for the Allied Telesis AT1700, which is a
  11    straight-foward Fujitsu MB86965 implementation.
  12 */
  13 
  14 static char *version =
  15         "at1700.c:v0.06 3/3/94  Donald Becker (becker@super.org)\n";
  16 
  17 #include <linux/config.h>
  18 
  19 /*
  20   Sources:
  21     The Fujitsu MB86695 datasheet.
  22 
  23         After this driver was written, ATI provided their EEPROM configuration
  24         code header file.  Thanks to Gerry Sockins of ATI.
  25 */
  26 
  27 #include <linux/kernel.h>
  28 #include <linux/sched.h>
  29 #include <linux/types.h>
  30 #include <linux/fcntl.h>
  31 #include <linux/interrupt.h>
  32 #include <linux/ptrace.h>
  33 #include <linux/ioport.h>
  34 #include <linux/in.h>
  35 #include <linux/malloc.h>
  36 #include <linux/string.h>
  37 #include <asm/system.h>
  38 #include <asm/bitops.h>
  39 #include <asm/io.h>
  40 #include <asm/dma.h>
  41 #include <errno.h>
  42 
  43 #include "dev.h"
  44 #include "eth.h"
  45 #include "skbuff.h"
  46 #include "arp.h"
  47 
  48 #ifndef HAVE_AUTOIRQ
  49 /* From auto_irq.c, in ioport.h for later versions. */
  50 extern void autoirq_setup(int waittime);
  51 extern int autoirq_report(int waittime);
  52 /* The map from IRQ number (as passed to the interrupt handler) to
  53    'struct device'. */
  54 extern struct device *irq2dev_map[16];
  55 #endif
  56 
  57 #ifndef HAVE_ALLOC_SKB
  58 #define alloc_skb(size, priority) (struct sk_buff *) kmalloc(size,priority)
  59 #define kfree_skbmem(addr, size) kfree_s(addr,size);
  60 #endif
  61 
  62 /* use 0 for production, 1 for verification, >2 for debug */
  63 #ifndef NET_DEBUG
  64 #define NET_DEBUG 2
  65 #endif
  66 static unsigned int net_debug = NET_DEBUG;
  67 
  68 typedef unsigned char uchar;
  69 
  70 /* Information that need to be kept for each board. */
  71 struct net_local {
  72         struct enet_statistics stats;
  73         long open_time;                         /* Useless example local info. */
  74         uint tx_started:1;                      /* Number of packet on the Tx queue. */
  75         uchar tx_queue;                         /* Number of packet on the Tx queue. */
  76         ushort tx_queue_len;            /* Current length of the Tx queue. */
  77 };
  78 
  79 
  80 /* Offsets from the base address. */
  81 #define STATUS                  0
  82 #define TX_STATUS               0
  83 #define RX_STATUS               1
  84 #define TX_INTR                 2               /* Bit-mapped interrupt enable registers. */
  85 #define RX_INTR                 3
  86 #define TX_MODE                 4
  87 #define RX_MODE                 5
  88 #define CONFIG_0                6               /* Misc. configuration settings. */
  89 #define CONFIG_1                7
  90 /* Run-time register bank 2 definitions. */
  91 #define DATAPORT                8               /* Word-wide DMA or programmed-I/O dataport. */
  92 #define TX_START                10
  93 #define MODE13                  13
  94 #define EEPROM_Ctrl     16
  95 #define EEPROM_Data     17
  96 
  97 /*  EEPROM_Ctrl bits. */
  98 #define EE_SHIFT_CLK    0x40    /* EEPROM shift clock, in reg. 16. */
  99 #define EE_CS                   0x20    /* EEPROM chip select, in reg. 16. */
 100 #define EE_DATA_WRITE   0x80    /* EEPROM chip data in, in reg. 17. */
 101 #define EE_DATA_READ    0x80    /* EEPROM chip data out, in reg. 17. */
 102 
 103 /* Delay between EEPROM clock transitions. */
 104 #define eeprom_delay()  do { int _i = 40; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
 105 
 106 /* The EEPROM commands include the alway-set leading bit. */
 107 #define EE_WRITE_CMD    (5 << 6)
 108 #define EE_READ_CMD             (6 << 6)
 109 #define EE_ERASE_CMD    (7 << 6)
 110 
 111 
 112 /* Index to functions, as function prototypes. */
 113 
 114 extern int at1700_probe(struct device *dev);
 115 
 116 static int at1700_probe1(struct device *dev, short ioaddr);
 117 static int read_eeprom(int ioaddr, int location);
 118 static int net_open(struct device *dev);
 119 static int      net_send_packet(struct sk_buff *skb, struct device *dev);
 120 static void net_interrupt(int reg_ptr);
 121 static void net_rx(struct device *dev);
 122 static int net_close(struct device *dev);
 123 static struct enet_statistics *net_get_stats(struct device *dev);
 124 #ifdef HAVE_MULTICAST
 125 static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
 126 #endif
 127 
 128 
 129 /* Check for a network adaptor of this type, and return '0' iff one exists.
 130    If dev->base_addr == 0, probe all likely locations.
 131    If dev->base_addr == 1, always return failure.
 132    If dev->base_addr == 2, alloate space for the device and return success
 133    (detachable devices only).
 134    */
 135 int
 136 at1700_probe(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 137 {
 138         short ports[] = {0x300, 0x280, 0x380, 0x320, 0x340, 0x260, 0x2a0, 0x240, 0};
 139         short *port, base_addr = dev->base_addr;
 140 
 141         if (base_addr > 0x1ff)          /* Check a single specified location. */
 142                 return at1700_probe1(dev, base_addr);
 143         else if (base_addr > 0)         /* Don't probe at all. */
 144                 return ENXIO;
 145 
 146         for (port = &ports[0]; *port; port++) {
 147                 int ioaddr = *port;
 148                 if (check_region(ioaddr, 32))
 149                         continue;
 150                 if (at1700_probe1(dev, ioaddr) == 0)
 151                         return 0;
 152         }
 153 
 154         return ENODEV;
 155 }
 156 
 157 /* The Fujitsu datasheet suggests that the NIC be probed for by checking its
 158    "signature", the default bit pattern after a reset.  This *doesn't* work --
 159    there is no way to reset the bus interface without a complete power-cycle!
 160 
 161    It turns out that ATI came to the same conclusion I did: the only thing
 162    that can be done is checking a few bits and then diving right into an
 163    EEPROM read. */
 164 
 165 int at1700_probe1(struct device *dev, short ioaddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 166 {
 167         unsigned short signature[4]         = {0xffff, 0xffff, 0x7ff7, 0xff5f};
 168         unsigned short signature_invalid[4] = {0xffff, 0xffff, 0x7ff7, 0xdf0f};
 169         char irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15};
 170         unsigned short *station_address = (unsigned short *)dev->dev_addr;
 171         unsigned int i, irq;
 172 
 173         /* Resetting the chip doesn't reset the ISA interface, so don't bother.
 174            That means we have to be careful with the register values we probe for.
 175            */
 176         for (i = 0; i < 4; i++)
 177                 if ((inw(ioaddr + 2*i) | signature_invalid[i]) != signature[i]) {
 178                         if (net_debug > 2)
 179                                 printk("AT1700 signature match failed at %d (%04x vs. %04x)\n",
 180                                            i, inw(ioaddr + 2*i), signature[i]);
 181                         return -ENODEV;
 182                 }
 183         if (read_eeprom(ioaddr, 4) != 0x0000
 184                 || read_eeprom(ioaddr, 5) & 0x00ff != 0x00F4)
 185                 return -ENODEV;
 186 
 187         /* Grab the region so that we can find another board if the IRQ request
 188            fails. */
 189         snarf_region(ioaddr, 32);
 190 
 191         irq = irqmap[(read_eeprom(ioaddr, 12)&0x04)
 192                                  | (read_eeprom(ioaddr, 0)>>14)];
 193 
 194         /* Snarf the interrupt vector now. */
 195         if (request_irq(irq, &net_interrupt)) {
 196                 printk ("AT1700 found at %#3x, but it's unusable due to a conflict on"
 197                                 "IRQ %d.\n", ioaddr, irq);
 198                 return EAGAIN;
 199         }
 200 
 201         printk("%s: AT1700 found at %#3x, IRQ %d, address ", dev->name,
 202                    ioaddr, irq);
 203 
 204         dev->base_addr = ioaddr;
 205         dev->irq = irq;
 206         irq2dev_map[irq] = dev;
 207 
 208         for(i = 0; i < 3; i++) {
 209                 unsigned short eeprom_val = read_eeprom(ioaddr, 4+i);
 210                 printk("%04x", eeprom_val);
 211                 station_address[i] = ntohs(eeprom_val);
 212         }
 213 
 214         /* The EEPROM word 12 bit 0x0400 means use regular 100 ohm 10baseT signals,
 215            rather than 150 ohm shielded twisted pair compansation.
 216            0x0000 == auto-sense the interface
 217            0x0800 == use TP interface
 218            0x1800 == use coax interface
 219            */
 220         {
 221                 char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2"};
 222                 ushort setup_value = read_eeprom(ioaddr, 12);
 223 
 224                 dev->if_port = setup_value >> 8;
 225                 printk(" %s interface (%04x).\n", porttype[(dev->if_port>>3) & 3],
 226                            setup_value);
 227         }
 228 
 229         /* Set the station address in bank zero. */
 230         outb(0xe0, ioaddr + 7);
 231         for (i = 0; i < 6; i++)
 232                 outb(dev->dev_addr[i], ioaddr + 8 + i);
 233 
 234         /* Switch to bank 1 and set the multicast table to accept none. */
 235         outb(0xe4, ioaddr + 7);
 236         for (i = 0; i < 8; i++)
 237                 outb(0x00, ioaddr + 8 + i);
 238 
 239         /* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit
 240            bus access, two 4K Tx queues, and disabled Tx and Rx. */
 241         outb(0xda, ioaddr + CONFIG_0);
 242 
 243         /* Switch to bank 2 and lock our I/O address. */
 244         outb(0xe8, ioaddr + 7);
 245         outb(dev->if_port, MODE13);
 246 
 247         /* Power-down the chip.  Aren't we green! */
 248         outb(0x00, ioaddr + CONFIG_1);
 249 
 250         if (net_debug)
 251                 printk(version);
 252 
 253         /* Initialize the device structure. */
 254         dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
 255         memset(dev->priv, 0, sizeof(struct net_local));
 256 
 257         dev->open               = net_open;
 258         dev->stop               = net_close;
 259         dev->hard_start_xmit = net_send_packet;
 260         dev->get_stats  = net_get_stats;
 261 #ifdef HAVE_MULTICAST
 262         dev->set_multicast_list = &set_multicast_list;
 263 #endif
 264 
 265         /* Fill in the fields of the device structure with ethernet-generic values.
 266            This should be in a common file instead of per-driver.  */
 267         for (i = 0; i < DEV_NUMBUFFS; i++)
 268                 dev->buffs[i] = NULL;
 269 
 270         dev->hard_header        = eth_header;
 271         dev->add_arp            = eth_add_arp;
 272         dev->queue_xmit         = dev_queue_xmit;
 273         dev->rebuild_header     = eth_rebuild_header;
 274         dev->type_trans         = eth_type_trans;
 275 
 276         dev->type               = ARPHRD_ETHER;
 277         dev->hard_header_len = ETH_HLEN;
 278         dev->mtu                = 1500; /* eth_mtu */
 279         dev->addr_len   = ETH_ALEN;
 280         for (i = 0; i < ETH_ALEN; i++) {
 281                 dev->broadcast[i]=0xff;
 282         }
 283 
 284         /* New-style flags. */
 285         dev->flags              = IFF_BROADCAST;
 286         dev->family             = AF_INET;
 287         dev->pa_addr    = 0;
 288         dev->pa_brdaddr = 0;
 289         dev->pa_mask    = 0;
 290         dev->pa_alen    = sizeof(unsigned long);
 291 
 292         return 0;
 293 }
 294 
 295 static int read_eeprom(int ioaddr, int location)
     /* [previous][next][first][last][top][bottom][index][help] */
 296 {
 297         int i;
 298         unsigned short retval = 0;
 299         short ee_addr = ioaddr + EEPROM_Ctrl;
 300         short ee_daddr = ioaddr + EEPROM_Data;
 301         int read_cmd = location | EE_READ_CMD;
 302         short ctrl_val = EE_CS;
 303         
 304         outb(ctrl_val, ee_addr);
 305         
 306         /* Shift the read command bits out. */
 307         for (i = 9; i >= 0; i--) {
 308                 short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
 309                 outb(dataval, ee_daddr);
 310                 outb(EE_CS | EE_SHIFT_CLK, ee_addr);    /* EEPROM clock tick. */
 311                 eeprom_delay();
 312                 outb(EE_CS, ee_addr);   /* Finish EEPROM a clock tick. */
 313                 eeprom_delay();
 314         }
 315         outb(EE_CS, ee_addr);
 316         
 317         for (i = 16; i > 0; i--) {
 318                 outb(EE_CS | EE_SHIFT_CLK, ee_addr);
 319                 eeprom_delay();
 320                 retval = (retval << 1) | ((inb(ee_daddr) & EE_DATA_READ) ? 1 : 0);
 321                 outb(EE_CS, ee_addr);
 322                 eeprom_delay();
 323         }
 324 
 325         /* Terminate the EEPROM access. */
 326         ctrl_val &= ~EE_CS;
 327         outb(ctrl_val | EE_SHIFT_CLK, ee_addr);
 328         eeprom_delay();
 329         outb(ctrl_val, ee_addr);
 330         eeprom_delay();
 331         return retval;
 332 }
 333 
 334 
 335 
 336 static int net_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 337 {
 338         struct net_local *lp = (struct net_local *)dev->priv;
 339         int ioaddr = dev->base_addr;
 340         int i;
 341 
 342         /* Powerup the chip, initialize config register 1, and select bank 0. */
 343         outb(0xe0, ioaddr + CONFIG_1);
 344 
 345         /* Set the station address in bank zero. */
 346         for (i = 0; i < 6; i++)
 347                 outb(dev->dev_addr[i], ioaddr + 8 + i);
 348 
 349         /* Switch to bank 1 and set the multicast table to accept none. */
 350         outb(0xe4, ioaddr + 7);
 351         for (i = 0; i < 8; i++)
 352                 outb(0x00, ioaddr + 8 + i);
 353 
 354         /* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit
 355            bus access, and two 4K Tx queues. */
 356         outb(0xda, ioaddr + CONFIG_0);
 357 
 358         /* Same config 0, except enable the Rx and Tx. */
 359         outb(0x5a, ioaddr + CONFIG_0);
 360         /* Switch to register bank 2 for the run-time registers. */
 361         outb(0xe8, ioaddr + CONFIG_1);
 362 
 363         /* Turn on Rx interrupts, leave Tx interrupts off until packet Tx. */
 364         outb(0x00, ioaddr + TX_INTR);
 365         outb(0x81, ioaddr + RX_INTR);
 366 
 367         lp->open_time = jiffies;
 368 
 369         dev->tbusy = 0;
 370         dev->interrupt = 0;
 371         dev->start = 1;
 372 
 373         return 0;
 374 }
 375 
 376 static int
 377 net_send_packet(struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 378 {
 379         struct net_local *lp = (struct net_local *)dev->priv;
 380         int ioaddr = dev->base_addr;
 381 
 382         if (dev->tbusy) {
 383                 /* If we get here, some higher level has decided we are broken.
 384                    There should really be a "kick me" function call instead. */
 385                 int tickssofar = jiffies - dev->trans_start;
 386                 if (tickssofar < 10)
 387                         return 1;
 388                 printk("%s: transmit timed out with status %04x, %s?\n", dev->name,
 389                            inw(ioaddr + STATUS), inb(ioaddr + TX_STATUS) & 0x80
 390                            ? "IRQ conflict" : "network cable problem");
 391                 printk("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
 392                            dev->name, inw(ioaddr + 0), inw(ioaddr + 2), inw(ioaddr + 4),
 393                            inw(ioaddr + 6), inw(ioaddr + 8), inw(ioaddr + 10),
 394                            inw(ioaddr + 12), inw(ioaddr + 14));
 395                 lp->stats.tx_errors++;
 396                 /* ToDo: We should try to restart the adaptor... */
 397                 outw(0xffff, ioaddr + 24);
 398                 outw(0xffff, ioaddr + TX_STATUS);
 399                 outw(0xe85a, ioaddr + CONFIG_0);
 400                 outw(0x8100, ioaddr + TX_INTR);
 401                 dev->tbusy=0;
 402                 dev->trans_start = jiffies;
 403         }
 404 
 405         /* If some higher layer thinks we've missed an tx-done interrupt
 406            we are passed NULL. Caution: dev_tint() handles the cli()/sti()
 407            itself. */
 408         if (skb == NULL) {
 409                 dev_tint(dev);
 410                 return 0;
 411         }
 412 
 413         /* For ethernet, fill in the header.  This should really be done by a
 414            higher level, rather than duplicated for each ethernet adaptor. */
 415         if (!skb->arp  &&  dev->rebuild_header(skb->data, dev)) {
 416                 skb->dev = dev;
 417                 arp_queue (skb);
 418                 return 0;
 419         }
 420         skb->arp=1;
 421 
 422         /* Block a timer-based transmit from overlapping.  This could better be
 423            done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
 424         if (set_bit(0, (void*)&dev->tbusy) != 0)
 425                 printk("%s: Transmitter access conflict.\n", dev->name);
 426         else {
 427                 short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 428                 unsigned char *buf = skb->data;
 429 
 430                 /* Turn off the possible Tx interrupts. */
 431                 outb(0x00, ioaddr + TX_INTR);
 432                 
 433                 outw(length, ioaddr + DATAPORT);
 434                 outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
 435 
 436                 lp->tx_queue++;
 437                 lp->tx_queue_len += length + 2;
 438 
 439                 if (lp->tx_started == 0) {
 440                         /* If the Tx is idle, always trigger a transmit. */
 441                         outb(0x80 | lp->tx_queue, ioaddr + TX_START);
 442                         lp->tx_queue = 0;
 443                         lp->tx_queue_len = 0;
 444                         dev->trans_start = jiffies;
 445                         lp->tx_started = 1;
 446                 } else if (lp->tx_queue_len < 4096 - 1502)      /* Room for one more packet? */
 447                         dev->tbusy = 0;
 448 
 449                 /* Turn on Tx interrupts back on. */
 450                 outb(0x82, ioaddr + TX_INTR);
 451         }
 452         if (skb->free)
 453                 kfree_skb (skb, FREE_WRITE);
 454 
 455         return 0;
 456 }
 457 
 458 /* The typical workload of the driver:
 459    Handle the network interface interrupts. */
 460 static void
 461 net_interrupt(int reg_ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 462 {
 463         int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2);
 464         struct device *dev = (struct device *)(irq2dev_map[irq]);
 465         struct net_local *lp;
 466         int ioaddr, status;
 467 
 468         if (dev == NULL) {
 469                 printk ("at1700_interrupt(): irq %d for unknown device.\n", irq);
 470                 return;
 471         }
 472         dev->interrupt = 1;
 473 
 474         ioaddr = dev->base_addr;
 475         lp = (struct net_local *)dev->priv;
 476         status = inw(ioaddr + TX_STATUS);
 477         outw(status, ioaddr + TX_STATUS);
 478 
 479         if (net_debug > 4)
 480                 printk("%s: Interrupt with status %04x.\n", dev->name, status);
 481         if (status & 0xff00
 482                 ||  (inb(ioaddr + RX_MODE) & 0x40) == 0) {                      /* Got a packet(s). */
 483                 net_rx(dev);
 484         }
 485         if (status & 0x00ff) {
 486                 if (status & 0x80) {
 487                         lp->stats.tx_packets++;
 488                         if (lp->tx_queue) {
 489                                 outb(0x80 | lp->tx_queue, ioaddr + TX_START);
 490                                 lp->tx_queue = 0;
 491                                 lp->tx_queue_len = 0;
 492                                 dev->trans_start = jiffies;
 493                                 dev->tbusy = 0;
 494                                 mark_bh(INET_BH);       /* Inform upper layers. */
 495                         } else {
 496                                 lp->tx_started = 0;
 497                                 /* Turn on Tx interrupts off. */
 498                                 outb(0x00, ioaddr + TX_INTR);
 499                                 dev->tbusy = 0;
 500                         }
 501                 }
 502         }
 503 
 504         return;
 505 }
 506 
 507 /* We have a good packet(s), get it/them out of the buffers. */
 508 static void
 509 net_rx(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 510 {
 511         struct net_local *lp = (struct net_local *)dev->priv;
 512         int ioaddr = dev->base_addr;
 513         int boguscount = 5;
 514 
 515         while ((inb(ioaddr + RX_MODE) & 0x40) == 0) {
 516                 ushort status = inw(ioaddr + DATAPORT);
 517 
 518                 if (net_debug > 4)
 519                         printk("%s: Rxing packet mode %02x status %04x.\n",
 520                                    dev->name, inb(ioaddr + RX_MODE), status);
 521 #ifndef final_version
 522                 if (status == 0) {
 523                         outb(0x05, ioaddr + 14);
 524                         break;
 525                 }
 526 #endif
 527 
 528                 if ((status & 0xF0) != 0x20) {  /* There was an error. */
 529                         lp->stats.rx_errors++;
 530                         if (status & 0x08) lp->stats.rx_length_errors++;
 531                         if (status & 0x04) lp->stats.rx_frame_errors++;
 532                         if (status & 0x02) lp->stats.rx_crc_errors++;
 533                         if (status & 0x01) lp->stats.rx_over_errors++;
 534                 } else {
 535                         ushort pkt_len = inw(ioaddr + DATAPORT);
 536                         /* Malloc up new buffer. */
 537                         int sksize = sizeof(struct sk_buff) + pkt_len;
 538                         struct sk_buff *skb;
 539 
 540                         if (pkt_len > 1550) {
 541                                 printk("%s: The AT1700 claimed a very large packet, size %d.\n",
 542                                            dev->name, pkt_len);
 543                                 outb(0x05, ioaddr + 14);
 544                                 lp->stats.rx_errors++;
 545                                 break;
 546                         }
 547                         skb = alloc_skb(sksize, GFP_ATOMIC);
 548                         if (skb == NULL) {
 549                                 printk("%s: Memory squeeze, dropping packet (len %d).\n",
 550                                            dev->name, pkt_len);
 551                                 outb(0x05, ioaddr + 14);
 552                                 lp->stats.rx_dropped++;
 553                                 break;
 554                         }
 555                         skb->mem_len = sksize;
 556                         skb->mem_addr = skb;
 557                         skb->len = pkt_len;
 558                         skb->dev = dev;
 559 
 560                         insw(ioaddr + DATAPORT, skb->data, (pkt_len + 1) >> 1);
 561 
 562                         if (net_debug > 5) {
 563                                 int i;
 564                                 printk("%s: Rxed packet of length %d: ", dev->name, pkt_len);
 565                                 for (i = 0; i < 14; i++)
 566                                         printk(" %02x", skb->data[i]);
 567                                 printk(".\n");
 568                         }
 569 
 570 #ifdef HAVE_NETIF_RX
 571                         netif_rx(skb);
 572 #else
 573                         skb->lock = 0;
 574                         if (dev_rint((unsigned char*)skb, pkt_len, IN_SKBUFF, dev) != 0) {
 575                                 kfree_s(skb, sksize);
 576                                 lp->stats.rx_dropped++;
 577                                 break;
 578                         }
 579 #endif
 580                         lp->stats.rx_packets++;
 581                 }
 582                 if (--boguscount <= 0)
 583                         break;
 584         }
 585 
 586         /* If any worth-while packets have been received, dev_rint()
 587            has done a mark_bh(INET_BH) for us and will work on them
 588            when we get to the bottom-half routine. */
 589         {
 590                 int i;
 591                 for (i = 0; i < 20; i++) {
 592                         if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40)
 593                                 break;
 594                         outb(0x05, ioaddr + 14);
 595                 }
 596 
 597                 if (net_debug > 5)
 598                         printk("%s: Exint Rx packet with mode %02x after %d ticks.\n", 
 599                                    dev->name, inb(ioaddr + RX_MODE), i);
 600         }
 601         return;
 602 }
 603 
 604 /* The inverse routine to net_open(). */
 605 static int net_close(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 606 {
 607         struct net_local *lp = (struct net_local *)dev->priv;
 608         int ioaddr = dev->base_addr;
 609 
 610         lp->open_time = 0;
 611 
 612         dev->tbusy = 1;
 613         dev->start = 0;
 614 
 615         /* Set configuration register 0 to disable Tx and Rx. */
 616         outb(0xda, ioaddr + CONFIG_0);
 617 
 618         /* Update the statistics -- ToDo. */
 619 
 620         /* Power-down the chip.  Green, green, green! */
 621         outb(0x00, ioaddr + CONFIG_1);
 622 
 623         return 0;
 624 }
 625 
 626 /* Get the current statistics.  This may be called with the card open or
 627    closed. */
 628 static struct enet_statistics *
 629 net_get_stats(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 630 {
 631         struct net_local *lp = (struct net_local *)dev->priv;
 632 
 633         cli();
 634         /* ToDo: Update the statistics from the device registers. */
 635         sti();
 636 
 637         return &lp->stats;
 638 }
 639 
 640 #ifdef HAVE_MULTICAST
 641 /* Set or clear the multicast filter for this adaptor.
 642    num_addrs == -1      Promiscuous mode, receive all packets
 643    num_addrs == 0       Normal mode, clear multicast list
 644    num_addrs > 0        Multicast mode, receive normal and MC packets, and do
 645                         best-effort filtering.
 646  */
 647 static void
 648 set_multicast_list(struct device *dev, int num_addrs, void *addrs)
     /* [previous][next][first][last][top][bottom][index][help] */
 649 {
 650         short ioaddr = dev->base_addr;
 651         if (num_addrs) {
 652                 outw(3, ioaddr + RX_MODE);      /* Enable promiscuous mode */
 653         } else
 654                 outw(2, ioaddr + RX_MODE);      /* Disable promiscuous, use normal mode */
 655 }
 656 #endif
 657 
 658 /*
 659  * Local variables:
 660  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c at1700.c"
 661  *  version-control: t
 662  *  kept-new-versions: 5
 663  *  tab-width: 4
 664  * End:
 665  */

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