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

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