root/drivers/net/ac3200.c

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

DEFINITIONS

This source file includes following definitions.
  1. ac3200_probe
  2. ac_probe1
  3. ac_open
  4. ac_reset_8390
  5. ac_get_8390_hdr
  6. ac_block_input
  7. ac_block_output
  8. ac_close_card
  9. init_module
  10. cleanup_module

   1 /* ac3200.c: A driver for the Ansel Communications EISA ethernet adaptor. */
   2 /*
   3         Written 1993, 1994 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         incorporated herein by reference.
   8 
   9         The author may be reached as becker@cesdis.gsfc.nasa.gov, or
  10     C/O Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
  11 
  12         This is driver for the Ansel Communications Model 3200 EISA Ethernet LAN
  13         Adapter.  The programming information is from the users manual, as related
  14         by glee@ardnassak.math.clemson.edu.
  15   */
  16 
  17 static const char *version =
  18         "ac3200.c:v1.01 7/1/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
  19 
  20 #ifdef MODULE
  21 #include <linux/module.h>
  22 #include <linux/version.h>
  23 #endif
  24 #include <linux/kernel.h>
  25 #include <linux/sched.h>
  26 #include <linux/errno.h>
  27 #include <linux/string.h>
  28 #include <asm/system.h>
  29 #include <asm/io.h>
  30 
  31 #include <linux/netdevice.h>
  32 #include <linux/etherdevice.h>
  33 #include "8390.h"
  34 
  35 /* Offsets from the base address. */
  36 #define AC_NIC_BASE             0x00
  37 #define AC_SA_PROM              0x16                    /* The station address PROM. */
  38 #define  AC_ADDR0                0x00                   /* Prefix station address values. */
  39 #define  AC_ADDR1                0x40                   /* !!!!These are just guesses!!!! */
  40 #define  AC_ADDR2                0x90
  41 #define AC_ID_PORT              0xC80
  42 #define AC_EISA_ID               0x0110d305
  43 #define AC_RESET_PORT   0xC84
  44 #define  AC_RESET                0x00
  45 #define  AC_ENABLE               0x01
  46 #define AC_CONFIG               0xC90   /* The configuration port. */
  47 
  48 #define AC_IO_EXTENT 0x10               /* IS THIS REALLY TRUE ??? */
  49                                 /* Actually accessed is:
  50                                                                  * AC_NIC_BASE (0-15)
  51                                                                  * AC_SA_PROM (0-5)
  52                                                                  * AC_ID_PORT (0-3)
  53                                                                  * AC_RESET_PORT
  54                                                                  * AC_CONFIG
  55                                                                  */
  56 
  57 /* Decoding of the configuration register. */
  58 static unsigned char config2irqmap[8] = {15, 12, 11, 10, 9, 7, 5, 3};
  59 static int addrmap[8] =
  60 {0xFF0000, 0xFE0000, 0xFD0000, 0xFFF0000, 0xFFE0000, 0xFFC0000,  0xD0000, 0 };
  61 static const char *port_name[4] = { "10baseT", "invalid", "AUI", "10base2"};
  62 
  63 #define config2irq(configval)   config2irqmap[((configval) >> 3) & 7]
  64 #define config2mem(configval)   addrmap[(configval) & 7]
  65 #define config2name(configval)  port_name[((configval) >> 6) & 3]
  66 
  67 /* First and last 8390 pages. */
  68 #define AC_START_PG             0x00    /* First page of 8390 TX buffer */
  69 #define AC_STOP_PG              0x80    /* Last page +1 of the 8390 RX ring */
  70 
  71 int ac3200_probe(struct device *dev);
  72 static int ac_probe1(int ioaddr, struct device *dev);
  73 
  74 static int ac_open(struct device *dev);
  75 static void ac_reset_8390(struct device *dev);
  76 static void ac_block_input(struct device *dev, int count,
  77                                         struct sk_buff *skb, int ring_offset);
  78 static void ac_block_output(struct device *dev, const int count,
  79                                                         const unsigned char *buf, const int start_page);
  80 static void ac_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
  81                                         int ring_page);
  82 
  83 static int ac_close_card(struct device *dev);
  84 
  85 
  86 /*      Probe for the AC3200.
  87 
  88         The AC3200 can be identified by either the EISA configuration registers,
  89         or the unique value in the station address PROM.
  90         */
  91 
  92 int ac3200_probe(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  93 {
  94         unsigned short ioaddr = dev->base_addr;
  95 
  96         if (ioaddr > 0x1ff)             /* Check a single specified location. */
  97                 return ac_probe1(ioaddr, dev);
  98         else if (ioaddr > 0)            /* Don't probe at all. */
  99                 return ENXIO;
 100 
 101         /* If you have a pre-pl15 machine you should delete this line. */
 102         if ( ! EISA_bus)
 103                 return ENXIO;
 104 
 105         for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000)
 106                 if (ac_probe1(ioaddr, dev) == 0)
 107                         return 0;
 108 
 109         return ENODEV;
 110 }
 111 
 112 static int ac_probe1(int ioaddr, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 113 {
 114         int i;
 115 
 116 #ifndef final_version
 117         printk("AC3200 ethercard probe at %#3x:", ioaddr);
 118 
 119         for(i = 0; i < 6; i++)
 120                 printk(" %02x", inb(ioaddr + AC_SA_PROM + i));
 121 #endif
 122 
 123         /* !!!!The values of AC_ADDRn (see above) should be corrected when we
 124            find out the correct station address prefix!!!! */
 125         if (inb(ioaddr + AC_SA_PROM + 0) != AC_ADDR0
 126                 || inb(ioaddr + AC_SA_PROM + 1) != AC_ADDR1
 127                 || inb(ioaddr + AC_SA_PROM + 2) != AC_ADDR2 ) {
 128 #ifndef final_version
 129                 printk(" not found (invalid prefix).\n");
 130 #endif
 131                 return ENODEV;
 132         }
 133 
 134         /* The correct probe method is to check the EISA ID. */
 135         for (i = 0; i < 4; i++)
 136                 if (inl(ioaddr + AC_ID_PORT) != AC_EISA_ID) {
 137                         printk("EISA ID mismatch, %8x vs %8x.\n",
 138                                    inl(ioaddr + AC_EISA_ID), AC_EISA_ID); 
 139                         return ENODEV;
 140                 }
 141 
 142         for(i = 0; i < ETHER_ADDR_LEN; i++)
 143                 dev->dev_addr[i] = inb(ioaddr + AC_SA_PROM + i);
 144 
 145 #ifndef final_version
 146         printk("\nAC3200 ethercard configuration register is %#02x,"
 147                    " EISA ID %02x %02x %02x %02x.\n", inb(ioaddr + AC_CONFIG),
 148                    inb(ioaddr + AC_ID_PORT + 0), inb(ioaddr + AC_ID_PORT + 1),
 149                    inb(ioaddr + AC_ID_PORT + 2), inb(ioaddr + AC_ID_PORT + 3));
 150 #endif
 151 
 152         /* Assign and snarf the interrupt now. */
 153         if (dev->irq == 0)
 154                 dev->irq = config2irq(inb(ioaddr + AC_CONFIG));
 155         else if (dev->irq == 2)
 156                 dev->irq = 9;
 157 
 158         if (request_irq(dev->irq, ei_interrupt, 0, "ac3200")) {
 159                 printk (" unable to get IRQ %d.\n", dev->irq);
 160                 return EAGAIN;
 161         }
 162 
 163         request_region(ioaddr, AC_IO_EXTENT, "ac3200");
 164 
 165         dev->base_addr = ioaddr;
 166 
 167 #ifdef notyet
 168         if (dev->mem_start)     {               /* Override the value from the board. */
 169                 for (i = 0; i < 7; i++)
 170                         if (addrmap[i] == dev->mem_start)
 171                                 break;
 172                 if (i >= 7)
 173                         i = 0;
 174                 outb((inb(ioaddr + AC_CONFIG) & ~7) | i, ioaddr + AC_CONFIG);
 175         }
 176 #endif
 177 
 178         dev->if_port = inb(ioaddr + AC_CONFIG) >> 6;
 179         dev->mem_start = config2mem(inb(ioaddr + AC_CONFIG));
 180         dev->rmem_start = dev->mem_start + TX_PAGES*256;
 181         dev->mem_end = dev->rmem_end = dev->mem_start
 182                 + (AC_STOP_PG - AC_START_PG)*256;
 183 
 184         ethdev_init(dev);
 185 
 186         ei_status.name = "AC3200";
 187         ei_status.tx_start_page = AC_START_PG;
 188         ei_status.rx_start_page = AC_START_PG + TX_PAGES;
 189         ei_status.stop_page = AC_STOP_PG;
 190         ei_status.word16 = 1;
 191 
 192         printk("\n%s: AC3200 at %#x, IRQ %d, %s port, shared memory %#lx-%#lx.\n",
 193                    dev->name, ioaddr, dev->irq, port_name[dev->if_port],
 194                    dev->mem_start, dev->mem_end-1);
 195 
 196         if (ei_debug > 0)
 197                 printk(version);
 198 
 199         ei_status.reset_8390 = &ac_reset_8390;
 200         ei_status.block_input = &ac_block_input;
 201         ei_status.block_output = &ac_block_output;
 202         ei_status.get_8390_hdr = &ac_get_8390_hdr;
 203 
 204         dev->open = &ac_open;
 205         dev->stop = &ac_close_card;
 206         NS8390_init(dev, 0);
 207         return 0;
 208 }
 209 
 210 static int ac_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 211 {
 212         int rc;
 213 #ifdef notyet
 214         /* Someday we may enable the IRQ and shared memory here. */
 215         int ioaddr = dev->base_addr;
 216 
 217         if (request_irq(dev->irq, ei_interrupt, 0, "ac3200"))
 218                 return -EAGAIN;
 219 #endif
 220 
 221         rc = ei_open(dev);
 222         if (rc != 0) return rc;
 223 
 224 #ifdef MODULE
 225         MOD_INC_USE_COUNT;
 226 #endif
 227 
 228         return 0;
 229 }
 230 
 231 static void ac_reset_8390(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 232 {
 233         ushort ioaddr = dev->base_addr;
 234 
 235         outb(AC_RESET, ioaddr + AC_RESET_PORT);
 236         if (ei_debug > 1) printk("resetting AC3200, t=%ld...", jiffies);
 237 
 238         ei_status.txing = 0;
 239         outb(AC_ENABLE, ioaddr + AC_RESET_PORT);
 240         if (ei_debug > 1) printk("reset done\n");
 241 
 242         return;
 243 }
 244 
 245 /* Grab the 8390 specific header. Similar to the block_input routine, but
 246    we don't need to be concerned with ring wrap as the header will be at
 247    the start of a page, so we optimize accordingly. */
 248 
 249 static void
 250 ac_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
     /* [previous][next][first][last][top][bottom][index][help] */
 251 {
 252         unsigned long hdr_start = dev->mem_start + ((ring_page - AC_START_PG)<<8);
 253         memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 254 }
 255 
 256 /*  Block input and output are easy on shared memory ethercards, the only
 257         complication is when the ring buffer wraps. */
 258 
 259 static void ac_block_input(struct device *dev, int count, struct sk_buff *skb,
     /* [previous][next][first][last][top][bottom][index][help] */
 260                                                   int ring_offset)
 261 {
 262         unsigned long xfer_start = dev->mem_start + ring_offset - (AC_START_PG<<8);
 263 
 264         if (xfer_start + count > dev->rmem_end) {
 265                 /* We must wrap the input move. */
 266                 int semi_count = dev->rmem_end - xfer_start;
 267                 memcpy_fromio(skb->data, xfer_start, semi_count);
 268                 count -= semi_count;
 269                 memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
 270         } else {
 271                 /* Packet is in one chunk -- we can copy + cksum. */
 272                 eth_io_copy_and_sum(skb, xfer_start, count, 0);
 273         }
 274 }
 275 
 276 static void ac_block_output(struct device *dev, int count,
     /* [previous][next][first][last][top][bottom][index][help] */
 277                                                         const unsigned char *buf, int start_page)
 278 {
 279         unsigned long shmem = dev->mem_start + ((start_page - AC_START_PG)<<8);
 280 
 281         memcpy_toio(shmem, buf, count);
 282 }
 283 
 284 static int ac_close_card(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 285 {
 286         dev->start = 0;
 287         dev->tbusy = 1;
 288 
 289         if (ei_debug > 1)
 290                 printk("%s: Shutting down ethercard.\n", dev->name);
 291 
 292 #ifdef notyet
 293         /* We should someday disable shared memory and interrupts. */
 294         outb(0x00, ioaddr + 6); /* Disable interrupts. */
 295         free_irq(dev->irq);
 296         irq2dev_map[dev->irq] = 0;
 297 #endif
 298 
 299         NS8390_init(dev, 0);
 300 
 301 #ifdef MODULE
 302         MOD_DEC_USE_COUNT;
 303 #endif
 304 
 305         return 0;
 306 }
 307 
 308 #ifdef MODULE
 309 char kernel_version[] = UTS_RELEASE;
 310 static char devicename[9] = { 0, };
 311 static struct device dev_ac3200 = {
 312         devicename, /* device name is inserted by linux/drivers/net/net_init.c */
 313         0, 0, 0, 0,
 314         0, 0,
 315         0, 0, 0, NULL, ac3200_probe };
 316 
 317 int io = 0;
 318 int irq = 0;
 319 
 320 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 321 {
 322         dev_ac3200.base_addr = io;
 323         dev_ac3200.irq       = irq;
 324         if (register_netdev(&dev_ac3200) != 0) {
 325                 printk("ac3200: register_netdev() returned non-zero.\n");
 326                 return -EIO;
 327         }
 328         return 0;
 329 }
 330 
 331 void
 332 cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 333 {
 334         if (MOD_IN_USE)
 335                 printk("ac3200: device busy, remove delayed\n");
 336         else
 337         {
 338                 unregister_netdev(&dev_ac3200);
 339 
 340                 /* If we don't do this, we can't re-insmod it later. */
 341                 free_irq(dev_ac3200.irq);
 342                 release_region(dev_ac3200.base_addr, AC_IO_EXTENT);
 343         }
 344 }
 345 #endif /* MODULE */
 346 
 347 /*
 348  * Local variables:
 349  * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c ac3200.c"
 350  *  version-control: t
 351  *  kept-new-versions: 5
 352  *  tab-width: 4
 353  * End:
 354  */

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