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

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

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