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

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