root/drivers/net/smc-ultra.c

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

DEFINITIONS

This source file includes following definitions.
  1. ultra_probe
  2. ultraprobe1
  3. ultra_open
  4. ultra_reset_8390
  5. ultra_block_input
  6. ultra_block_output
  7. ultra_close_card

   1 /* smc-ultra.c: A SMC Ultra ethernet driver for linux. */
   2 /*
   3     Written 1993 by Donald Becker.  If released, this code will be
   4     Copyright 1993 United States Government as represented by the
   5     Director, National Security Agency.  This software may be used and
   6     distributed according to the terms of the GNU Public License,
   7     incorporated herein by reference.
   8     
   9     This is a driver for the SMC Ultra ethercard.
  10 
  11     The Author may be reached as becker@super.org or
  12     C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
  13 
  14 */
  15 
  16 static char *version =
  17     "smc-ultra.c:v0.03 11/21/93 Donald Becker (becker@super.org)\n";
  18 
  19 #include <linux/config.h>
  20 #include <linux/kernel.h>
  21 #include <linux/sched.h>
  22 #include <linux/errno.h>
  23 #include <linux/string.h>
  24 #include <asm/io.h>
  25 #include <asm/system.h>
  26 
  27 #include "dev.h"
  28 #include "8390.h"
  29 
  30 /* Compatibility definitions for earlier kernel versions. */
  31 #ifndef HAVE_PORTRESERVE
  32 #define check_region(ioaddr, size)              0
  33 #define snarf_region(ioaddr, size);             do ; while (0)
  34 #endif
  35 
  36 int ultraprobe(int ioaddr, struct device *dev);
  37 int ultraprobe1(int ioaddr, struct device *dev);
  38 
  39 static int ultra_open(struct device *dev);
  40 static void ultra_reset_8390(struct device *dev);
  41 static int ultra_block_input(struct device *dev, int count,
  42                           char *buf, int ring_offset);
  43 static void ultra_block_output(struct device *dev, int count,
  44                             const unsigned char *buf, const start_page);
  45 static int ultra_close_card(struct device *dev);
  46 
  47 
  48 #define START_PG        0x00    /* First page of TX buffer */
  49 
  50 #define ULTRA_CMDREG    0       /* Offset to ASIC command register. */
  51 #define  ULTRA_RESET    0x80    /* Board reset, in ULTRA_CMDREG. */
  52 #define  ULTRA_MEMENB   0x40    /* Enable the shared memory. */
  53 #define ULTRA_NIC_OFFSET  16    /* NIC register offset from the base_addr. */
  54 
  55 /*  Probe for the Ultra.  This looks like a 8013 with the station
  56     address PROM at I/O ports <base>+8 to <base>+13, with a checksum
  57     following.
  58 */
  59 
  60 int ultra_probe(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  61 {
  62     int *port, ports[] = {0x200, 0x220, 0x240, 0x280, 0x300, 0x380, 0};
  63     unsigned short ioaddr = dev->base_addr;
  64 
  65     if (ioaddr > 0x1ff)
  66         return ! ultraprobe1(ioaddr, dev);
  67     else if (ioaddr > 0)
  68         return ENXIO;           /* Don't probe at all. */
  69 
  70     for (port = &ports[0]; *port; port++) {
  71         if (check_region(*port, 32))
  72             continue;
  73         if ((inb(*port + 7) & 0xF0) == 0x20
  74             && ultraprobe1(*port, dev) == 0)
  75             return 0;
  76     }
  77     dev->base_addr = ioaddr;
  78     return ENODEV;
  79 }
  80 
  81 int ultraprobe1(int ioaddr, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  82 {
  83   int i;
  84   unsigned char *station_addr = dev->dev_addr;
  85   int checksum = 0;
  86   char *model_name;
  87   int num_pages;
  88   unsigned char reg1, eeprom_irq = 0;
  89 
  90   /* Second probe check: at most one bit can be set in register 1. */
  91   reg1 = inb(ioaddr + 1);
  92   if (reg1 & (reg1 - 1))
  93       return ENODEV;
  94 
  95   /* Select the station address register set. */
  96   outb(0x7f & inb(ioaddr + 4), ioaddr + 4);
  97 
  98   for (i = 0; i < 8; i++)
  99       checksum += inb(ioaddr + 8 + i);
 100   if ((checksum & 0xff) != 0xFF)
 101       return ENODEV;
 102   
 103   printk("%s: SMC Ultra at %#3x,", dev->name, ioaddr);
 104   for (i = 0; i < 6; i++)
 105       printk(" %2.2X", station_addr[i] = inb(ioaddr + 8 + i));
 106 
 107   /* Switch from the station address to the alternate register set. */
 108   outb(0x80 | inb(ioaddr + 4), ioaddr + 4);
 109 
 110   model_name = "SMC Ultra";
 111 
 112   if (dev->irq < 2) {
 113       unsigned char irqmap[] = {0, 9, 3, 5, 7, 10, 11, 15};
 114       int irqreg = inb(ioaddr + 0xd);
 115       int irq;
 116 
 117       /* The IRQ bits are split. */
 118       irq = irqmap[((irqreg & 0x40) >> 4) + ((irqreg & 0x0c) >> 2)];
 119 
 120       if (irq == 0) {
 121           printk(", failed to detect IRQ line.\n");
 122           return -EAGAIN;
 123       }
 124       dev->irq = irq;
 125       eeprom_irq = 1;
 126   }
 127 
 128 
 129   /* OK, were are certain this is going to work.  Setup the device. */
 130   snarf_region(ioaddr, 32);
 131 
 132   /* The 8390 isn't at the base address, so fake the offset */
 133   dev->base_addr = ioaddr+ULTRA_NIC_OFFSET;
 134 
 135   { 
 136       int addr = inb(ioaddr + 0xb);
 137       int addr_tbl[4] = {0x0C0000, 0x0D0000, 0xFC0000, 0xFD0000};
 138       short num_pages_tbl[4] = {0x20, 0x40, 0x80, 0xff};
 139 
 140       dev->mem_start = ((addr & 0x0f) << 13) + addr_tbl[(addr >> 6) & 3] ;
 141       num_pages = num_pages_tbl[(addr >> 4) & 3];
 142   }
 143 
 144   ethdev_init(dev);
 145 
 146   ei_status.name = model_name;
 147   ei_status.word16 = 1;
 148   ei_status.tx_start_page = START_PG;
 149   ei_status.rx_start_page = START_PG + TX_PAGES;
 150   ei_status.stop_page = num_pages;
 151 
 152   dev->rmem_start = dev->mem_start + TX_PAGES*256;
 153   dev->mem_end = dev->rmem_end
 154       = dev->mem_start + (ei_status.stop_page - START_PG)*256;
 155 
 156   printk(",%s IRQ %d memory %#x-%#x.\n", eeprom_irq ? "" : "assigned ",
 157          dev->irq, dev->mem_start, dev->mem_end-1);
 158   if (ei_debug > 0)
 159       printk(version);
 160 
 161   ei_status.reset_8390 = &ultra_reset_8390;
 162   ei_status.block_input = &ultra_block_input;
 163   ei_status.block_output = &ultra_block_output;
 164   dev->open = &ultra_open;
 165   dev->stop = &ultra_close_card;
 166   NS8390_init(dev, 0);
 167 
 168   return 0;
 169 }
 170 
 171 static int
 172 ultra_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 173 {
 174   int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
 175 
 176   if (irqaction(dev->irq, &ei_sigaction))
 177       return -EAGAIN;
 178 
 179   /* Enabled FINE16 mode. */
 180   outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);
 181   outb(ULTRA_MEMENB, ioaddr);   /* Enable memory, 16 bit mode. */
 182   outb(0x80, ioaddr + 5);
 183   outb(0x01, ioaddr + 6);       /* Enable interrupts and memory. */
 184   return ei_open(dev);
 185 }
 186 
 187 static void
 188 ultra_reset_8390(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 189 {
 190     int cmd_port = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC base addr */
 191 
 192     outb(ULTRA_RESET, cmd_port);
 193     if (ei_debug > 1) printk("resetting Ultra, t=%d...", jiffies);
 194     ei_status.txing = 0;
 195 
 196     outb(ULTRA_MEMENB, cmd_port);
 197 
 198     if (ei_debug > 1) printk("reset done\n");
 199     return;
 200 }
 201 
 202 /* Block input and output are easy on shared memory ethercards, the only
 203    complication is when the ring buffer wraps. */
 204 
 205 static int
 206 ultra_block_input(struct device *dev, int count, char *buf, int ring_offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 207 {
 208     void *xfer_start = (void *)(dev->mem_start + ring_offset
 209                                 - (START_PG<<8));
 210 
 211     if (xfer_start + count > (void*) dev->rmem_end) {
 212         /* We must wrap the input move. */
 213         int semi_count = (void*)dev->rmem_end - xfer_start;
 214         memcpy(buf, xfer_start, semi_count);
 215         count -= semi_count;
 216         memcpy(buf + semi_count, (char *)dev->rmem_start, count);
 217         return dev->rmem_start + count;
 218     }
 219     memcpy(buf, xfer_start, count);
 220 
 221     return ring_offset + count;
 222 }
 223 
 224 static void
 225 ultra_block_output(struct device *dev, int count, const unsigned char *buf,
     /* [previous][next][first][last][top][bottom][index][help] */
 226                 int start_page)
 227 {
 228     unsigned char *shmem
 229         = (unsigned char *)dev->mem_start + ((start_page - START_PG)<<8);
 230 
 231     memcpy(shmem, buf, count);
 232 
 233 }
 234 
 235 static int
 236 ultra_close_card(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 237 {
 238     int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* CMDREG */
 239 
 240     dev->start = 0;
 241     dev->tbusy = 1;
 242 
 243     if (ei_debug > 1)
 244         printk("%s: Shutting down ethercard.\n", dev->name);
 245 
 246     outb(0x00, ioaddr + 6);     /* Disable interrupts. */
 247     free_irq(dev->irq);
 248     irq2dev_map[dev->irq] = 0;
 249 
 250     NS8390_init(dev, 0);
 251 
 252     /* We should someday disable shared memory and change to 8-bit mode
 253        "just in case"... */
 254 
 255     return 0;
 256 }
 257 
 258 
 259 /*
 260  * Local variables:
 261  *  compile-command: "gcc -D__KERNEL__ -Wall -O6 -I/usr/src/linux/net/inet -c smc-ultra.c"
 262  *  version-control: t
 263  *  kept-new-versions: 5
 264  * End:
 265  */

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