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

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