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_block_input
  6. ac_block_output
  7. ac_close_card
  8. init_module
  9. 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 "8390.h"
  33 
  34 /* Offsets from the base address. */
  35 #define AC_NIC_BASE             0x00
  36 #define AC_SA_PROM              0x16                    /* The station address PROM. */
  37 #define  AC_ADDR0                0x00                   /* Prefix station address values. */
  38 #define  AC_ADDR1                0x40                   /* !!!!These are just guesses!!!! */
  39 #define  AC_ADDR2                0x90
  40 #define AC_ID_PORT              0xC80
  41 #define AC_EISA_ID               0x0110d305
  42 #define AC_RESET_PORT   0xC84
  43 #define  AC_RESET                0x00
  44 #define  AC_ENABLE               0x01
  45 #define AC_CONFIG               0xC90   /* The configuration port. */
  46 
  47 /* Decoding of the configuration register. */
  48 static unsigned char config2irqmap[8] = {15, 12, 11, 10, 9, 7, 5, 3};
  49 static int addrmap[8] =
  50 {0xFF0000, 0xFE0000, 0xFD0000, 0xFFF0000, 0xFFE0000, 0xFFC0000,  0xD0000, 0 };
  51 static const char *port_name[4] = { "10baseT", "invalid", "AUI", "10base2"};
  52 
  53 #define config2irq(configval)   config2irqmap[((configval) >> 3) & 7]
  54 #define config2mem(configval)   addrmap[(configval) & 7]
  55 #define config2name(configval)  port_name[((configval) >> 6) & 3]
  56 
  57 /* First and last 8390 pages. */
  58 #define AC_START_PG             0x00    /* First page of 8390 TX buffer */
  59 #define AC_STOP_PG              0x80    /* Last page +1 of the 8390 RX ring */
  60 
  61 int ac3200_probe(struct device *dev);
  62 static int ac_probe1(int ioaddr, struct device *dev);
  63 
  64 static int ac_open(struct device *dev);
  65 static void ac_reset_8390(struct device *dev);
  66 static int ac_block_input(struct device *dev, int count,
  67                                                   char *buf, int ring_offset);
  68 static void ac_block_output(struct device *dev, const int count,
  69                                                         const unsigned char *buf, const int start_page);
  70 static int ac_close_card(struct device *dev);
  71 
  72 
  73 /*      Probe for the AC3200.
  74 
  75         The AC3200 can be identified by either the EISA configuration registers,
  76         or the unique value in the station address PROM.
  77         */
  78 
  79 int ac3200_probe(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  80 {
  81         unsigned short ioaddr = dev->base_addr;
  82 
  83         if (ioaddr > 0x1ff)             /* Check a single specified location. */
  84                 return ac_probe1(ioaddr, dev);
  85         else if (ioaddr > 0)            /* Don't probe at all. */
  86                 return ENXIO;
  87 
  88         /* If you have a pre-pl15 machine you should delete this line. */
  89         if ( ! EISA_bus)
  90                 return ENXIO;
  91 
  92         for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000)
  93                 if (ac_probe1(ioaddr, dev) == 0)
  94                         return 0;
  95 
  96         return ENODEV;
  97 }
  98 
  99 static int ac_probe1(int ioaddr, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 100 {
 101         int i;
 102 
 103 #ifndef final_version
 104         printk("AC3200 ethercard probe at %#3x:", ioaddr);
 105 
 106         for(i = 0; i < 6; i++)
 107                 printk(" %02x", inb(ioaddr + AC_SA_PROM + i));
 108 #endif
 109 
 110         /* !!!!The values of AC_ADDRn (see above) should be corrected when we
 111            find out the correct station address prefix!!!! */
 112         if (inb(ioaddr + AC_SA_PROM + 0) != AC_ADDR0
 113                 || inb(ioaddr + AC_SA_PROM + 1) != AC_ADDR1
 114                 || inb(ioaddr + AC_SA_PROM + 2) != AC_ADDR2 ) {
 115 #ifndef final_version
 116                 printk(" not found (invalid prefix).\n");
 117 #endif
 118                 return ENODEV;
 119         }
 120 
 121         /* The correct probe method is to check the EISA ID. */
 122         for (i = 0; i < 4; i++)
 123                 if (inl(ioaddr + AC_ID_PORT) != AC_EISA_ID) {
 124                         printk("EISA ID mismatch, %8x vs %8x.\n",
 125                                    inl(ioaddr + AC_EISA_ID), AC_EISA_ID); 
 126                         return ENODEV;
 127                 }
 128 
 129         for(i = 0; i < ETHER_ADDR_LEN; i++)
 130                 dev->dev_addr[i] = inb(ioaddr + AC_SA_PROM + i);
 131 
 132 #ifndef final_version
 133         printk("\nAC3200 ethercard configuration register is %#02x,"
 134                    " EISA ID %02x %02x %02x %02x.\n", inb(ioaddr + AC_CONFIG),
 135                    inb(ioaddr + AC_ID_PORT + 0), inb(ioaddr + AC_ID_PORT + 1),
 136                    inb(ioaddr + AC_ID_PORT + 2), inb(ioaddr + AC_ID_PORT + 3));
 137 #endif
 138 
 139         /* Assign and snarf the interrupt now. */
 140         if (dev->irq == 0)
 141                 dev->irq = config2irq(inb(ioaddr + AC_CONFIG));
 142         else if (dev->irq == 2)
 143                 dev->irq = 9;
 144 
 145         if (request_irq(dev->irq, ei_interrupt, 0, "ac3200")) {
 146                 printk (" unable to get IRQ %d.\n", dev->irq);
 147                 return 0;
 148         }
 149 
 150         dev->base_addr = ioaddr;
 151 
 152 #ifdef notyet
 153         if (dev->mem_start)     {               /* Override the value from the board. */
 154                 for (i = 0; i < 7; i++)
 155                         if (addrmap[i] == dev->mem_start)
 156                                 break;
 157                 if (i >= 7)
 158                         i = 0;
 159                 outb((inb(ioaddr + AC_CONFIG) & ~7) | i, ioaddr + AC_CONFIG);
 160         }
 161 #endif
 162 
 163         dev->if_port = inb(ioaddr + AC_CONFIG) >> 6;
 164         dev->mem_start = config2mem(inb(ioaddr + AC_CONFIG));
 165         dev->rmem_start = dev->mem_start + TX_PAGES*256;
 166         dev->mem_end = dev->rmem_end = dev->mem_start
 167                 + (AC_STOP_PG - AC_START_PG)*256;
 168 
 169         ethdev_init(dev);
 170 
 171         ei_status.name = "AC3200";
 172         ei_status.tx_start_page = AC_START_PG;
 173         ei_status.rx_start_page = AC_START_PG + TX_PAGES;
 174         ei_status.stop_page = AC_STOP_PG;
 175         ei_status.word16 = 1;
 176 
 177         printk("\n%s: AC3200 at %#x, IRQ %d, %s port, shared memory %#lx-%#lx.\n",
 178                    dev->name, ioaddr, dev->irq, port_name[dev->if_port],
 179                    dev->mem_start, dev->mem_end-1);
 180 
 181         if (ei_debug > 0)
 182                 printk(version);
 183 
 184         ei_status.reset_8390 = &ac_reset_8390;
 185         ei_status.block_input = &ac_block_input;
 186         ei_status.block_output = &ac_block_output;
 187 
 188         dev->open = &ac_open;
 189         dev->stop = &ac_close_card;
 190         NS8390_init(dev, 0);
 191         return 0;
 192 }
 193 
 194 static int ac_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 195 {
 196         int rc;
 197 #ifdef notyet
 198         /* Someday we may enable the IRQ and shared memory here. */
 199         int ioaddr = dev->base_addr;
 200 
 201         if (request_irq(dev->irq, ei_interrupt, 0, "ac3200"))
 202                 return -EAGAIN;
 203 #endif
 204 
 205         rc = ei_open(dev);
 206         if (rc != 0) return rc;
 207 
 208 #ifdef MODULE
 209         MOD_INC_USE_COUNT;
 210 #endif
 211 
 212         return 0;
 213 }
 214 
 215 static void ac_reset_8390(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 216 {
 217         ushort ioaddr = dev->base_addr;
 218 
 219         outb(AC_RESET, ioaddr + AC_RESET_PORT);
 220         if (ei_debug > 1) printk("resetting AC3200, t=%ld...", jiffies);
 221 
 222         ei_status.txing = 0;
 223         outb(AC_ENABLE, ioaddr + AC_RESET_PORT);
 224         if (ei_debug > 1) printk("reset done\n");
 225 
 226         return;
 227 }
 228 
 229 /*  Block input and output are easy on shared memory ethercards, the only
 230         complication is when the ring buffer wraps. */
 231 
 232 static int ac_block_input(struct device *dev, int count, char *buf,
     /* [previous][next][first][last][top][bottom][index][help] */
 233                                                   int ring_offset)
 234 {
 235         long xfer_start = dev->mem_start + ring_offset - (AC_START_PG<<8);
 236 
 237         if (xfer_start + count > dev->rmem_end) {
 238                 /* We must wrap the input move. */
 239                 int semi_count = dev->rmem_end - xfer_start;
 240                 memcpy(buf, (char*)xfer_start, semi_count);
 241                 count -= semi_count;
 242                 memcpy(buf + semi_count, (char *)dev->rmem_start, count);
 243                 return dev->rmem_start + count;
 244         }
 245         memcpy(buf, (char*)xfer_start, count);
 246 
 247         return ring_offset + count;
 248 }
 249 
 250 static void ac_block_output(struct device *dev, int count,
     /* [previous][next][first][last][top][bottom][index][help] */
 251                                                         const unsigned char *buf, int start_page)
 252 {
 253         long shmem = dev->mem_start + ((start_page - AC_START_PG)<<8);
 254 
 255         memcpy((unsigned char *)shmem, buf, count);
 256 }
 257 
 258 static int ac_close_card(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 259 {
 260         dev->start = 0;
 261         dev->tbusy = 1;
 262 
 263         if (ei_debug > 1)
 264                 printk("%s: Shutting down ethercard.\n", dev->name);
 265 
 266 #ifdef notyet
 267         /* We should someday disable shared memory and interrupts. */
 268         outb(0x00, ioaddr + 6); /* Disable interrupts. */
 269         free_irq(dev->irq);
 270         irq2dev_map[dev->irq] = 0;
 271 #endif
 272 
 273         NS8390_init(dev, 0);
 274 
 275 #ifdef MODULE
 276         MOD_DEC_USE_COUNT;
 277 #endif
 278 
 279         return 0;
 280 }
 281 
 282 #ifdef MODULE
 283 char kernel_version[] = UTS_RELEASE;
 284 static struct device dev_ac3200 = {
 285         "        " /*"ac3200"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ac3200_probe };
 286 
 287 int io = 0;
 288 int irq = 0;
 289 
 290 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 291 {
 292         dev_ac3200.base_addr = io;
 293         dev_ac3200.irq       = irq;
 294         if (register_netdev(&dev_ac3200) != 0) {
 295                 printk("ac3200: register_netdev() returned non-zero.\n");
 296                 return -EIO;
 297         }
 298         return 0;
 299 }
 300 
 301 void
 302 cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 303 {
 304         if (MOD_IN_USE)
 305                 printk("ac3200: device busy, remove delayed\n");
 306         else
 307         {
 308                 unregister_netdev(&dev_ac3200);
 309         }
 310 }
 311 #endif /* MODULE */
 312 
 313 /*
 314  * Local variables:
 315  * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c ac3200.c"
 316  *  version-control: t
 317  *  kept-new-versions: 5
 318  *  tab-width: 4
 319  * End:
 320  */

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