root/drivers/net/fmv18x.c

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

DEFINITIONS

This source file includes following definitions.
  1. fmv18x_probe
  2. fmv18x_probe1
  3. net_open
  4. net_send_packet
  5. net_interrupt
  6. net_rx
  7. net_close
  8. net_get_stats
  9. set_multicast_list
  10. init_module
  11. cleanup_module

   1 /* fmv18x.c: A network device driver for  the Fujitsu FMV-181/182.
   2 
   3         Original: at1700.c (1993-94 by Donald Becker).
   4                 Copyright 1993 United States Government as represented by the
   5                 Director, National Security Agency.
   6                 The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
   7                 Center of Excellence in Space Data and Information Sciences
   8                    Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
   9 
  10         Modified by Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)
  11                 Copyright 1994 Fujitsu Laboratories Ltd.
  12         Special thanks to:
  13                 Masayoshi UTAKA (utaka@ace.yk.fujitsu.co.jp)
  14                         for testing this driver.
  15                 H. NEGISHI (agy, negishi@sun45.psd.cs.fujitsu.co.jp)
  16                         for suggestion of some program modification.
  17                 Masahiro SEKIGUCHI <seki@sysrap.cs.fujitsu.co.jp>
  18                         for suggestion of some program modification.
  19                 Kazutoshi MORIOKA (morioka@aurora.oaks.cs.fujitsu.co.jp)
  20                         for testing this driver.
  21 
  22         This software may be used and distributed according to the terms
  23         of the GNU Public License, incorporated herein by reference.
  24 
  25         This is a device driver for the Fujitsu FMV-181/182, which is a
  26         straight-forward Fujitsu MB86965 implementation.
  27 
  28   Sources:
  29     at1700.c
  30     The Fujitsu MB86965 datasheet.
  31     The Fujitsu FMV-181/182 user's guide
  32 */
  33 
  34 static const char *version =
  35         "fmv18x.c:v1.3.71e 03/04/96  Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)\n";
  36 
  37 #include <linux/module.h>
  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/malloc.h>
  48 #include <linux/string.h>
  49 #include <asm/system.h>
  50 #include <asm/bitops.h>
  51 #include <asm/io.h>
  52 #include <asm/dma.h>
  53 #include <linux/errno.h>
  54 
  55 #include <linux/netdevice.h>
  56 #include <linux/etherdevice.h>
  57 #include <linux/skbuff.h>
  58 #include <linux/delay.h>
  59 
  60 static int fmv18x_probe_list[] =
  61 {0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0};
  62 
  63 /* use 0 for production, 1 for verification, >2 for debug */
  64 #ifndef NET_DEBUG
  65 #define NET_DEBUG 1
  66 #endif
  67 static unsigned int net_debug = NET_DEBUG;
  68 
  69 typedef unsigned char uchar;
  70 
  71 /* Information that need to be kept for each board. */
  72 struct net_local {
  73         struct enet_statistics stats;
  74         long open_time;                         /* Useless example local info. */
  75         uint tx_started:1;                      /* Number of packet on the Tx queue. */
  76         uchar tx_queue;                         /* Number of packet on the Tx queue. */
  77         ushort tx_queue_len;            /* Current length of the Tx queue. */
  78 };
  79 
  80 
  81 /* Offsets from the base address. */
  82 #define STATUS                  0
  83 #define TX_STATUS               0
  84 #define RX_STATUS               1
  85 #define TX_INTR                 2               /* Bit-mapped interrupt enable registers. */
  86 #define RX_INTR                 3
  87 #define TX_MODE                 4
  88 #define RX_MODE                 5
  89 #define CONFIG_0                6               /* Misc. configuration settings. */
  90 #define CONFIG_1                7
  91 /* Run-time register bank 2 definitions. */
  92 #define DATAPORT                8               /* Word-wide DMA or programmed-I/O dataport. */
  93 #define TX_START                10
  94 #define COL16CNTL               11
  95 #define MODE13                  13
  96 /* Fujitsu FMV-18x Card Configuration */
  97 #define FJ_STATUS0              0x10
  98 #define FJ_STATUS1              0x11
  99 #define FJ_CONFIG0              0x12
 100 #define FJ_CONFIG1              0x13
 101 #define FJ_MACADDR              0x14    /* 0x14 - 0x19 */
 102 #define FJ_BUFCNTL              0x1A
 103 #define FJ_BUFDATA              0x1C
 104 #define FMV18X_IO_EXTENT        32
 105 
 106 /* Index to functions, as function prototypes. */
 107 
 108 extern int fmv18x_probe(struct device *dev);
 109 
 110 static int fmv18x_probe1(struct device *dev, short ioaddr);
 111 static int net_open(struct device *dev);
 112 static int      net_send_packet(struct sk_buff *skb, struct device *dev);
 113 static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 114 static void net_rx(struct device *dev);
 115 static int net_close(struct device *dev);
 116 static struct enet_statistics *net_get_stats(struct device *dev);
 117 static void set_multicast_list(struct device *dev);
 118 
 119 
 120 /* Check for a network adaptor of this type, and return '0' iff one exists.
 121    If dev->base_addr == 0, probe all likely locations.
 122    If dev->base_addr == 1, always return failure.
 123    If dev->base_addr == 2, allocate space for the device and return success
 124    (detachable devices only).
 125    */
 126 #ifdef HAVE_DEVLIST
 127 /* Support for a alternate probe manager, which will eliminate the
 128    boilerplate below. */
 129 struct netdev_entry fmv18x_drv =
 130 {"fmv18x", fmv18x_probe1, FMV18X_IO_EXTENT, fmv18x_probe_list};
 131 #else
 132 int
 133 fmv18x_probe(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 134 {
 135         int i;
 136         int base_addr = dev ? dev->base_addr : 0;
 137 
 138         if (base_addr > 0x1ff)          /* Check a single specified location. */
 139                 return fmv18x_probe1(dev, base_addr);
 140         else if (base_addr != 0)        /* Don't probe at all. */
 141                 return ENXIO;
 142 
 143         for (i = 0; fmv18x_probe_list[i]; i++) {
 144                 int ioaddr = fmv18x_probe_list[i];
 145                 if (check_region(ioaddr, FMV18X_IO_EXTENT))
 146                         continue;
 147                 if (fmv18x_probe1(dev, ioaddr) == 0)
 148                         return 0;
 149         }
 150 
 151         return ENODEV;
 152 }
 153 #endif
 154 
 155 /* The Fujitsu datasheet suggests that the NIC be probed for by checking its
 156    "signature", the default bit pattern after a reset.  This *doesn't* work --
 157    there is no way to reset the bus interface without a complete power-cycle!
 158 
 159    It turns out that ATI came to the same conclusion I did: the only thing
 160    that can be done is checking a few bits and then diving right into MAC
 161    address check. */
 162 
 163 int fmv18x_probe1(struct device *dev, short ioaddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 164 {
 165         char irqmap[4] = {3, 7, 10, 15};
 166         unsigned int i, irq;
 167 
 168         /* Resetting the chip doesn't reset the ISA interface, so don't bother.
 169            That means we have to be careful with the register values we probe for.
 170            */
 171 
 172         /* Check I/O address configuration and Fujitsu vendor code */
 173         if (fmv18x_probe_list[inb(ioaddr + FJ_CONFIG0) & 0x07] != ioaddr
 174         ||  inb(ioaddr+FJ_MACADDR  ) != 0x00
 175         ||  inb(ioaddr+FJ_MACADDR+1) != 0x00
 176         ||  inb(ioaddr+FJ_MACADDR+2) != 0x0e)
 177                 return -ENODEV;
 178 
 179         irq = irqmap[(inb(ioaddr + FJ_CONFIG0)>>6) & 0x03];
 180 
 181         /* Snarf the interrupt vector now. */
 182         if (request_irq(irq, &net_interrupt, 0, "fmv18x", NULL)) {
 183                 printk ("FMV-18x found at %#3x, but it's unusable due to a conflict on"
 184                                 "IRQ %d.\n", ioaddr, irq);
 185                 return EAGAIN;
 186         }
 187 
 188         /* Allocate a new 'dev' if needed. */
 189         if (dev == NULL)
 190                 dev = init_etherdev(0, sizeof(struct net_local));
 191 
 192         /* Grab the region so that we can find another board if the IRQ request
 193            fails. */
 194         request_region(ioaddr, FMV18X_IO_EXTENT, "fmv18x");
 195 
 196         printk("%s: FMV-18x found at %#3x, IRQ %d, address ", dev->name,
 197                    ioaddr, irq);
 198 
 199         dev->base_addr = ioaddr;
 200         dev->irq = irq;
 201         irq2dev_map[irq] = dev;
 202 
 203         for(i = 0; i < 6; i++) {
 204                 unsigned char val = inb(ioaddr + FJ_MACADDR + i);
 205                 printk("%02x", val);
 206                 dev->dev_addr[i] = val;
 207         }
 208 
 209         /* "FJ_STATUS0" 12 bit 0x0400 means use regular 100 ohm 10baseT signals,
 210            rather than 150 ohm shielded twisted pair compensation.
 211            0x0000 == auto-sense the interface
 212            0x0800 == use TP interface
 213            0x1800 == use coax interface
 214            */
 215         {
 216                 const char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2/5"};
 217                 ushort setup_value = inb(ioaddr + FJ_STATUS0);
 218 
 219                 switch( setup_value & 0x07 ){
 220                 case 0x01 /* 10base5 */:
 221                 case 0x02 /* 10base2 */: dev->if_port = 0x18; break;
 222                 case 0x04 /* 10baseT */: dev->if_port = 0x08; break;
 223                 default /* auto-sense*/: dev->if_port = 0x00; break;
 224                 }
 225                 printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]);
 226         }
 227 
 228         /* Initialize LAN Controller and LAN Card */
 229         outb(0xda, ioaddr + CONFIG_0);   /* Initialize LAN Controller */
 230         outb(0x00, ioaddr + CONFIG_1);   /* Stand by mode */
 231         outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */
 232         outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure (TAMIYA) */
 233 
 234         /* wait for a while */
 235         udelay(200);
 236 
 237         /* Set the station address in bank zero. */
 238         outb(0x00, ioaddr + CONFIG_1);
 239         for (i = 0; i < 6; i++)
 240                 outb(dev->dev_addr[i], ioaddr + 8 + i);
 241 
 242         /* Switch to bank 1 and set the multicast table to accept none. */
 243         outb(0x04, ioaddr + CONFIG_1);
 244         for (i = 0; i < 8; i++)
 245                 outb(0x00, ioaddr + 8 + i);
 246 
 247         /* Switch to bank 2 and lock our I/O address. */
 248         outb(0x08, ioaddr + CONFIG_1);
 249         outb(dev->if_port, ioaddr + MODE13);
 250 
 251         if (net_debug)
 252                 printk(version);
 253 
 254         /* Initialize the device structure. */
 255         dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
 256         if (dev->priv == NULL)
 257                 return -ENOMEM;
 258         memset(dev->priv, 0, sizeof(struct net_local));
 259 
 260         dev->open               = net_open;
 261         dev->stop               = net_close;
 262         dev->hard_start_xmit = net_send_packet;
 263         dev->get_stats  = net_get_stats;
 264         dev->set_multicast_list = &set_multicast_list;
 265 
 266         /* Fill in the fields of 'dev' with ethernet-generic values. */
 267            
 268         ether_setup(dev);
 269         return 0;
 270 }
 271 
 272 
 273 static int net_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 274 {
 275         struct net_local *lp = (struct net_local *)dev->priv;
 276         int ioaddr = dev->base_addr;
 277 
 278         /* Set the configuration register 0 to 32K 100ns. byte-wide memory,
 279            16 bit bus access, and two 4K Tx, enable the Rx and Tx. */
 280         outb(0x5a, ioaddr + CONFIG_0);
 281 
 282         /* Powerup and switch to register bank 2 for the run-time registers. */
 283         outb(0xe8, ioaddr + CONFIG_1);
 284 
 285         lp->tx_started = 0;
 286         lp->tx_queue = 0;
 287         lp->tx_queue_len = 0;
 288 
 289         /* Clear Tx and Rx Status */
 290         outb(0xff, ioaddr + TX_STATUS);
 291         outb(0xff, ioaddr + RX_STATUS);
 292         lp->open_time = jiffies;
 293 
 294         dev->tbusy = 0;
 295         dev->interrupt = 0;
 296         dev->start = 1;
 297 
 298         /* Enable the IRQ of the LAN Card */
 299         outb(0x80, ioaddr + FJ_CONFIG1);
 300 
 301         /* Enable both Tx and Rx interrupts */
 302         outw(0x8182, ioaddr+TX_INTR);
 303 
 304         MOD_INC_USE_COUNT;
 305 
 306         return 0;
 307 }
 308 
 309 static int
 310 net_send_packet(struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 311 {
 312         struct net_local *lp = (struct net_local *)dev->priv;
 313         int ioaddr = dev->base_addr;
 314 
 315         if (dev->tbusy) {
 316                 /* If we get here, some higher level has decided we are broken.
 317                    There should really be a "kick me" function call instead. */
 318                 int tickssofar = jiffies - dev->trans_start;
 319                 if (tickssofar < 10)
 320                         return 1;
 321                 printk("%s: transmit timed out with status %04x, %s?\n", dev->name,
 322                            htons(inw(ioaddr + TX_STATUS)),
 323                            inb(ioaddr + TX_STATUS) & 0x80
 324                            ? "IRQ conflict" : "network cable problem");
 325                 printk("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
 326                            dev->name, htons(inw(ioaddr + 0)),
 327                            htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)),
 328                            htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
 329                            htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
 330                            htons(inw(ioaddr +14)));
 331                 printk("eth card: %04x %04x\n",
 332                         htons(inw(ioaddr+FJ_STATUS0)),
 333                         htons(inw(ioaddr+FJ_CONFIG0)));
 334                 lp->stats.tx_errors++;
 335                 /* ToDo: We should try to restart the adaptor... */
 336                 cli();
 337 
 338                 /* Initialize LAN Controller and LAN Card */
 339                 outb(0xda, ioaddr + CONFIG_0);   /* Initialize LAN Controller */
 340                 outb(0x00, ioaddr + CONFIG_1);   /* Stand by mode */
 341                 outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */
 342                 outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure */
 343                 net_open(dev);
 344 
 345                 sti();
 346         }
 347 
 348         /* If some higher layer thinks we've missed an tx-done interrupt
 349            we are passed NULL. Caution: dev_tint() handles the cli()/sti()
 350            itself. */
 351         if (skb == NULL) {
 352                 dev_tint(dev);
 353                 return 0;
 354         }
 355 
 356         /* Block a timer-based transmit from overlapping.  This could better be
 357            done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
 358         if (set_bit(0, (void*)&dev->tbusy) != 0)
 359                 printk("%s: Transmitter access conflict.\n", dev->name);
 360         else {
 361                 short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 362                 unsigned char *buf = skb->data;
 363 
 364                 if (length > ETH_FRAME_LEN) {
 365                         if (net_debug)
 366                                 printk("%s: Attempting to send a large packet (%d bytes).\n",
 367                                         dev->name, length);
 368                         return 1;
 369                 }
 370 
 371                 if (net_debug > 4)
 372                         printk("%s: Transmitting a packet of length %lu.\n", dev->name,
 373                                    (unsigned long)skb->len);
 374 
 375                 /* Disable both interrupts. */
 376                 outw(0x0000, ioaddr + TX_INTR);
 377                 
 378                 outw(length, ioaddr + DATAPORT);
 379                 outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
 380 
 381                 lp->tx_queue++;
 382                 lp->tx_queue_len += length + 2;
 383 
 384                 if (lp->tx_started == 0) {
 385                         /* If the Tx is idle, always trigger a transmit. */
 386                         outb(0x80 | lp->tx_queue, ioaddr + TX_START);
 387                         lp->tx_queue = 0;
 388                         lp->tx_queue_len = 0;
 389                         dev->trans_start = jiffies;
 390                         lp->tx_started = 1;
 391                         dev->tbusy = 0;
 392                 } else if (lp->tx_queue_len < 4096 - 1502)
 393                         /* Yes, there is room for one more packet. */
 394                         dev->tbusy = 0;
 395 
 396                 /* Re-enable interrupts */
 397                 outw(0x8182, ioaddr + TX_INTR);
 398         }
 399         dev_kfree_skb (skb, FREE_WRITE);
 400 
 401         return 0;
 402 }
 403 
 404 /* The typical workload of the driver:
 405    Handle the network interface interrupts. */
 406 static void
 407 net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 408 {
 409         struct device *dev = (struct device *)(irq2dev_map[irq]);
 410         struct net_local *lp;
 411         int ioaddr, status;
 412 
 413         if (dev == NULL) {
 414                 printk ("fmv18x_interrupt(): irq %d for unknown device.\n", irq);
 415                 return;
 416         }
 417         dev->interrupt = 1;
 418 
 419         ioaddr = dev->base_addr;
 420         lp = (struct net_local *)dev->priv;
 421 
 422         /* Avoid multiple interrupts. */
 423         outw(0x0000, ioaddr + TX_INTR);
 424 
 425         status = inw(ioaddr + TX_STATUS);
 426         outw(status, ioaddr + TX_STATUS);
 427 
 428         if (net_debug > 4)
 429                 printk("%s: Interrupt with status %04x.\n", dev->name, status);
 430         if (status & 0xff00
 431                 ||  (inb(ioaddr + RX_MODE) & 0x40) == 0) {                      /* Got a packet(s). */
 432                 net_rx(dev);
 433         }
 434         if (status & 0x00ff) {
 435                 if (status & 0x80) {
 436                         lp->stats.tx_packets++;
 437                         if (lp->tx_queue) {
 438                                 outb(0x80 | lp->tx_queue, ioaddr + TX_START);
 439                                 lp->tx_queue = 0;
 440                                 lp->tx_queue_len = 0;
 441                                 dev->trans_start = jiffies;
 442                                 dev->tbusy = 0;
 443                                 mark_bh(NET_BH);        /* Inform upper layers. */
 444                         } else {
 445                                 lp->tx_started = 0;
 446                                 dev->tbusy = 0;
 447                                 mark_bh(NET_BH);        /* Inform upper layers. */
 448                         }
 449                 }
 450                 if (status & 0x02 ) {
 451                         if (net_debug > 4)
 452                                 printk("%s: 16 Collision occur during Txing.\n", dev->name);
 453                         /* Retry to send the packet */
 454                         outb(0x02, ioaddr + COL16CNTL);
 455                 }
 456         }
 457 
 458         dev->interrupt = 0;
 459         outw(0x8182, ioaddr + TX_INTR);
 460         return;
 461 }
 462 
 463 /* We have a good packet(s), get it/them out of the buffers. */
 464 static void
 465 net_rx(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 466 {
 467         struct net_local *lp = (struct net_local *)dev->priv;
 468         int ioaddr = dev->base_addr;
 469         int boguscount = 10;    /* 5 -> 10: by agy 19940922 */
 470 
 471         while ((inb(ioaddr + RX_MODE) & 0x40) == 0) {
 472                 /* Clear PKT_RDY bit: by agy 19940922 */
 473                 /* outb(0x80, ioaddr + RX_STATUS); */
 474                 ushort status = inw(ioaddr + DATAPORT);
 475 
 476                 if (net_debug > 4)
 477                         printk("%s: Rxing packet mode %02x status %04x.\n",
 478                                    dev->name, inb(ioaddr + RX_MODE), status);
 479 #ifndef final_version
 480                 if (status == 0) {
 481                         outb(0x05, ioaddr + 14);
 482                         break;
 483                 }
 484 #endif
 485 
 486                 if ((status & 0xF0) != 0x20) {  /* There was an error. */
 487                         lp->stats.rx_errors++;
 488                         if (status & 0x08) lp->stats.rx_length_errors++;
 489                         if (status & 0x04) lp->stats.rx_frame_errors++;
 490                         if (status & 0x02) lp->stats.rx_crc_errors++;
 491                         if (status & 0x01) lp->stats.rx_over_errors++;
 492                 } else {
 493                         ushort pkt_len = inw(ioaddr + DATAPORT);
 494                         /* Malloc up new buffer. */
 495                         struct sk_buff *skb;
 496 
 497                         if (pkt_len > 1550) {
 498                                 printk("%s: The FMV-18x claimed a very large packet, size %d.\n",
 499                                            dev->name, pkt_len);
 500                                 outb(0x05, ioaddr + 14);
 501                                 lp->stats.rx_errors++;
 502                                 break;
 503                         }
 504                         skb = dev_alloc_skb(pkt_len+3);
 505                         if (skb == NULL) {
 506                                 printk("%s: Memory squeeze, dropping packet (len %d).\n",
 507                                            dev->name, pkt_len);
 508                                 outb(0x05, ioaddr + 14);
 509                                 lp->stats.rx_dropped++;
 510                                 break;
 511                         }
 512                         skb->dev = dev;
 513                         skb_reserve(skb,2);
 514 
 515                         insw(ioaddr + DATAPORT, skb_put(skb,pkt_len), (pkt_len + 1) >> 1);
 516 
 517                         if (net_debug > 5) {
 518                                 int i;
 519                                 printk("%s: Rxed packet of length %d: ", dev->name, pkt_len);
 520                                 for (i = 0; i < 14; i++)
 521                                         printk(" %02x", skb->data[i]);
 522                                 printk(".\n");
 523                         }
 524 
 525                         skb->protocol=eth_type_trans(skb, dev);
 526                         netif_rx(skb);
 527                         lp->stats.rx_packets++;
 528                 }
 529                 if (--boguscount <= 0)
 530                         break;
 531         }
 532 
 533         /* If any worth-while packets have been received, dev_rint()
 534            has done a mark_bh(NET_BH) for us and will work on them
 535            when we get to the bottom-half routine. */
 536         {
 537                 int i;
 538                 for (i = 0; i < 20; i++) {
 539                         if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40)
 540                                 break;
 541                         (void)inw(ioaddr + DATAPORT);                           /* dummy status read */
 542                         outb(0x05, ioaddr + 14);
 543                 }
 544 
 545                 if (net_debug > 5 && i > 0)
 546                         printk("%s: Exint Rx packet with mode %02x after %d ticks.\n", 
 547                                    dev->name, inb(ioaddr + RX_MODE), i);
 548         }
 549 
 550         return;
 551 }
 552 
 553 /* The inverse routine to net_open(). */
 554 static int net_close(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 555 {
 556         int ioaddr = dev->base_addr;
 557 
 558         ((struct net_local *)dev->priv)->open_time = 0;
 559 
 560         dev->tbusy = 1;
 561         dev->start = 0;
 562 
 563         /* Set configuration register 0 to disable Tx and Rx. */
 564         outb(0xda, ioaddr + CONFIG_0);
 565 
 566         /* Update the statistics -- ToDo. */
 567 
 568         /* Power-down the chip.  Green, green, green! */
 569         outb(0x00, ioaddr + CONFIG_1);
 570 
 571         MOD_DEC_USE_COUNT;
 572 
 573         /* Set the ethernet adaptor disable IRQ */
 574         outb(0x00, ioaddr + FJ_CONFIG1);
 575 
 576         return 0;
 577 }
 578 
 579 /* Get the current statistics.  This may be called with the card open or
 580    closed. */
 581 static struct enet_statistics *
 582 net_get_stats(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 583 {
 584         struct net_local *lp = (struct net_local *)dev->priv;
 585 
 586         cli();
 587         /* ToDo: Update the statistics from the device registers. */
 588         sti();
 589 
 590         return &lp->stats;
 591 }
 592 
 593 /* Set or clear the multicast filter for this adaptor.
 594    num_addrs == -1      Promiscuous mode, receive all packets
 595    num_addrs == 0       Normal mode, clear multicast list
 596    num_addrs > 0        Multicast mode, receive normal and MC packets, and do
 597                         best-effort filtering.
 598  */
 599 static void
 600 set_multicast_list(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 601 {
 602         short ioaddr = dev->base_addr;
 603         if (dev->mc_count || dev->flags&(IFF_PROMISC|IFF_ALLMULTI)) 
 604         {
 605                 /*
 606                  *      We must make the kernel realise we had to move
 607                  *      into promisc mode or we start all out war on
 608                  *      the cable. - AC
 609                  */
 610                 dev->flags|=IFF_PROMISC;                
 611         
 612                 outb(3, ioaddr + RX_MODE);      /* Enable promiscuous mode */
 613         } 
 614         else
 615                 outb(2, ioaddr + RX_MODE);      /* Disable promiscuous, use normal mode */
 616 }
 617 
 618 #ifdef MODULE
 619 static char devicename[9] = { 0, };
 620 static struct device dev_fmv18x = {
 621         devicename, /* device name is inserted by linux/drivers/net/net_init.c */
 622         0, 0, 0, 0,
 623         0, 0,
 624         0, 0, 0, NULL, fmv18x_probe };
 625 
 626 static int io = 0x220;
 627 static int irq = 0;
 628 
 629 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 630 {
 631         if (io == 0)
 632                 printk("fmv18x: You should not use auto-probing with insmod!\n");
 633         dev_fmv18x.base_addr = io;
 634         dev_fmv18x.irq       = irq;
 635         if (register_netdev(&dev_fmv18x) != 0) {
 636                 printk("fmv18x: register_netdev() returned non-zero.\n");
 637                 return -EIO;
 638         }
 639         return 0;
 640 }
 641 
 642 void
 643 cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 644 {
 645         unregister_netdev(&dev_fmv18x);
 646         kfree(dev_fmv18x.priv);
 647         dev_fmv18x.priv = NULL;
 648 
 649         /* If we don't do this, we can't re-insmod it later. */
 650         free_irq(dev_fmv18x.irq, NULL);
 651         irq2dev_map[dev_fmv18x.irq] = NULL;
 652         release_region(dev_fmv18x.base_addr, FMV18X_IO_EXTENT);
 653 }
 654 #endif /* MODULE */
 655 
 656 /*
 657  * Local variables:
 658  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c fmv18x.c"
 659  *  version-control: t
 660  *  kept-new-versions: 5
 661  *  tab-width: 4
 662  *  c-indent-level: 4
 663  * End:
 664  */

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