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

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