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.04 11/30/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     /* Check chip ID nibble. */
  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 eeprom_irq = 0;
  89 
  90 
  91   /* Select the station address register set. */
  92   outb(0x7f & inb(ioaddr + 4), ioaddr + 4);
  93 
  94   for (i = 0; i < 8; i++)
  95       checksum += inb(ioaddr + 8 + i);
  96   if ((checksum & 0xff) != 0xFF)
  97       return ENODEV;
  98   
  99   printk("%s: SMC Ultra at %#3x,", dev->name, ioaddr);
 100   for (i = 0; i < 6; i++)
 101       printk(" %2.2X", station_addr[i] = inb(ioaddr + 8 + i));
 102 
 103   /* Switch from the station address to the alternate register set. */
 104   outb(0x80 | inb(ioaddr + 4), ioaddr + 4);
 105 
 106   model_name = "SMC Ultra";
 107 
 108   if (dev->irq < 2) {
 109       unsigned char irqmap[] = {0, 9, 3, 5, 7, 10, 11, 15};
 110       int irqreg = inb(ioaddr + 0xd);
 111       int irq;
 112 
 113       /* The IRQ bits are split. */
 114       irq = irqmap[((irqreg & 0x40) >> 4) + ((irqreg & 0x0c) >> 2)];
 115 
 116       if (irq == 0) {
 117           printk(", failed to detect IRQ line.\n");
 118           return -EAGAIN;
 119       }
 120       dev->irq = irq;
 121       eeprom_irq = 1;
 122   }
 123 
 124 
 125   /* OK, were are certain this is going to work.  Setup the device. */
 126   snarf_region(ioaddr, 32);
 127 
 128   /* The 8390 isn't at the base address, so fake the offset */
 129   dev->base_addr = ioaddr+ULTRA_NIC_OFFSET;
 130 
 131   { 
 132       int addr = inb(ioaddr + 0xb);
 133       int addr_tbl[4] = {0x0C0000, 0x0D0000, 0xFC0000, 0xFD0000};
 134       short num_pages_tbl[4] = {0x20, 0x40, 0x80, 0xff};
 135 
 136       dev->mem_start = ((addr & 0x0f) << 13) + addr_tbl[(addr >> 6) & 3] ;
 137       num_pages = num_pages_tbl[(addr >> 4) & 3];
 138   }
 139 
 140   ethdev_init(dev);
 141 
 142   ei_status.name = model_name;
 143   ei_status.word16 = 1;
 144   ei_status.tx_start_page = START_PG;
 145   ei_status.rx_start_page = START_PG + TX_PAGES;
 146   ei_status.stop_page = num_pages;
 147 
 148   dev->rmem_start = dev->mem_start + TX_PAGES*256;
 149   dev->mem_end = dev->rmem_end
 150       = dev->mem_start + (ei_status.stop_page - START_PG)*256;
 151 
 152   printk(",%s IRQ %d memory %#x-%#x.\n", eeprom_irq ? "" : "assigned ",
 153          dev->irq, dev->mem_start, dev->mem_end-1);
 154   if (ei_debug > 0)
 155       printk(version);
 156 
 157   ei_status.reset_8390 = &ultra_reset_8390;
 158   ei_status.block_input = &ultra_block_input;
 159   ei_status.block_output = &ultra_block_output;
 160   dev->open = &ultra_open;
 161   dev->stop = &ultra_close_card;
 162   NS8390_init(dev, 0);
 163 
 164   return 0;
 165 }
 166 
 167 static int
 168 ultra_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 169 {
 170   int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
 171 
 172   if (irqaction(dev->irq, &ei_sigaction))
 173       return -EAGAIN;
 174 
 175   /* Enabled FINE16 mode. */
 176   outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);
 177   outb(ULTRA_MEMENB, ioaddr);   /* Enable memory, 16 bit mode. */
 178   outb(0x80, ioaddr + 5);
 179   outb(0x01, ioaddr + 6);       /* Enable interrupts and memory. */
 180   return ei_open(dev);
 181 }
 182 
 183 static void
 184 ultra_reset_8390(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 185 {
 186     int cmd_port = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC base addr */
 187 
 188     outb(ULTRA_RESET, cmd_port);
 189     if (ei_debug > 1) printk("resetting Ultra, t=%d...", jiffies);
 190     ei_status.txing = 0;
 191 
 192     outb(ULTRA_MEMENB, cmd_port);
 193 
 194     if (ei_debug > 1) printk("reset done\n");
 195     return;
 196 }
 197 
 198 /* Block input and output are easy on shared memory ethercards, the only
 199    complication is when the ring buffer wraps. */
 200 
 201 static int
 202 ultra_block_input(struct device *dev, int count, char *buf, int ring_offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 203 {
 204     void *xfer_start = (void *)(dev->mem_start + ring_offset
 205                                 - (START_PG<<8));
 206 
 207     if (xfer_start + count > (void*) dev->rmem_end) {
 208         /* We must wrap the input move. */
 209         int semi_count = (void*)dev->rmem_end - xfer_start;
 210         memcpy(buf, xfer_start, semi_count);
 211         count -= semi_count;
 212         memcpy(buf + semi_count, (char *)dev->rmem_start, count);
 213         return dev->rmem_start + count;
 214     }
 215     memcpy(buf, xfer_start, count);
 216 
 217     return ring_offset + count;
 218 }
 219 
 220 static void
 221 ultra_block_output(struct device *dev, int count, const unsigned char *buf,
     /* [previous][next][first][last][top][bottom][index][help] */
 222                 int start_page)
 223 {
 224     unsigned char *shmem
 225         = (unsigned char *)dev->mem_start + ((start_page - START_PG)<<8);
 226 
 227     memcpy(shmem, buf, count);
 228 
 229 }
 230 
 231 static int
 232 ultra_close_card(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 233 {
 234     int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* CMDREG */
 235 
 236     dev->start = 0;
 237     dev->tbusy = 1;
 238 
 239     if (ei_debug > 1)
 240         printk("%s: Shutting down ethercard.\n", dev->name);
 241 
 242     outb(0x00, ioaddr + 6);     /* Disable interrupts. */
 243     free_irq(dev->irq);
 244     irq2dev_map[dev->irq] = 0;
 245 
 246     NS8390_init(dev, 0);
 247 
 248     /* We should someday disable shared memory and change to 8-bit mode
 249        "just in case"... */
 250 
 251     return 0;
 252 }
 253 
 254 
 255 /*
 256  * Local variables:
 257  *  compile-command: "gcc -D__KERNEL__ -Wall -O6 -I/usr/src/linux/net/inet -c smc-ultra.c"
 258  *  version-control: t
 259  *  kept-new-versions: 5
 260  * End:
 261  */

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