~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/net/smc-ultra.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* smc-ultra.c: A SMC Ultra ethernet driver for linux. */
  2 /*
  3         This is a driver for the SMC Ultra and SMC EtherEZ ISA ethercards.
  4 
  5         Written 1993-1998 by Donald Becker.
  6 
  7         Copyright 1993 United States Government as represented by the
  8         Director, National Security Agency.
  9 
 10         This software may be used and distributed according to the terms
 11         of the GNU Public License, incorporated herein by reference.
 12 
 13         The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
 14         Center of Excellence in Space Data and Information Sciences
 15                 Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
 16 
 17         This driver uses the cards in the 8390-compatible mode.
 18         Most of the run-time complexity is handled by the generic code in
 19         8390.c.  The code in this file is responsible for
 20 
 21                 ultra_probe()           Detecting and initializing the card.
 22                 ultra_probe1()
 23 
 24                 ultra_open()            The card-specific details of starting, stopping
 25                 ultra_reset_8390()      and resetting the 8390 NIC core.
 26                 ultra_close()
 27 
 28                 ultra_block_input()             Routines for reading and writing blocks of
 29                 ultra_block_output()    packet buffer memory.
 30                 ultra_pio_input()
 31                 ultra_pio_output()
 32 
 33         This driver enables the shared memory only when doing the actual data
 34         transfers to avoid a bug in early version of the card that corrupted
 35         data transferred by a AHA1542.
 36 
 37         This driver now supports the programmed-I/O (PIO) data transfer mode of
 38         the EtherEZ. It does not use the non-8390-compatible "Altego" mode.
 39         That support (if available) is in smc-ez.c.
 40 
 41         Changelog:
 42 
 43         Paul Gortmaker  : multiple card support for module users.
 44         Donald Becker   : 4/17/96 PIO support, minor potential problems avoided.
 45         Donald Becker   : 6/6/96 correctly set auto-wrap bit.
 46 */
 47 
 48 static const char *version =
 49         "smc-ultra.c:v2.02 2/3/98 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
 50 
 51 #include <linux/module.h>
 52 
 53 #include <linux/kernel.h>
 54 #include <linux/sched.h>
 55 #include <linux/errno.h>
 56 #include <linux/string.h>
 57 #include <linux/init.h>
 58 #include <asm/io.h>
 59 #include <asm/system.h>
 60 
 61 #include <linux/netdevice.h>
 62 #include <linux/etherdevice.h>
 63 #include "8390.h"
 64 
 65 /* A zero-terminated list of I/O addresses to be probed. */
 66 static unsigned int ultra_portlist[] __initdata =
 67 {0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380, 0};
 68 
 69 int ultra_probe(struct net_device *dev);
 70 static int ultra_probe1(struct net_device *dev, int ioaddr);
 71 
 72 static int ultra_open(struct net_device *dev);
 73 static void ultra_reset_8390(struct net_device *dev);
 74 static void ultra_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 75                                                 int ring_page);
 76 static void ultra_block_input(struct net_device *dev, int count,
 77                                                   struct sk_buff *skb, int ring_offset);
 78 static void ultra_block_output(struct net_device *dev, int count,
 79                                                         const unsigned char *buf, const int start_page);
 80 static void ultra_pio_get_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 81                                                 int ring_page);
 82 static void ultra_pio_input(struct net_device *dev, int count,
 83                                                   struct sk_buff *skb, int ring_offset);
 84 static void ultra_pio_output(struct net_device *dev, int count,
 85                                                          const unsigned char *buf, const int start_page);
 86 static int ultra_close_card(struct net_device *dev);
 87 
 88 
 89 #define START_PG                0x00    /* First page of TX buffer */
 90 
 91 #define ULTRA_CMDREG    0               /* Offset to ASIC command register. */
 92 #define  ULTRA_RESET    0x80    /* Board reset, in ULTRA_CMDREG. */
 93 #define  ULTRA_MEMENB   0x40    /* Enable the shared memory. */
 94 #define IOPD    0x02                    /* I/O Pipe Data (16 bits), PIO operation. */
 95 #define IOPA    0x07                    /* I/O Pipe Address for PIO operation. */
 96 #define ULTRA_NIC_OFFSET  16    /* NIC register offset from the base_addr. */
 97 #define ULTRA_IO_EXTENT 32
 98 #define EN0_ERWCNT              0x08    /* Early receive warning count. */
 99 
100 /*      Probe for the Ultra.  This looks like a 8013 with the station
101         address PROM at I/O ports <base>+8 to <base>+13, with a checksum
102         following.
103 */
104 
105 int __init ultra_probe(struct net_device *dev)
106 {
107         int i;
108         int base_addr = dev->base_addr;
109 
110         SET_MODULE_OWNER(dev);
111 
112         if (base_addr > 0x1ff)          /* Check a single specified location. */
113                 return ultra_probe1(dev, base_addr);
114         else if (base_addr != 0)        /* Don't probe at all. */
115                 return -ENXIO;
116 
117         for (i = 0; ultra_portlist[i]; i++)
118                 if (ultra_probe1(dev, ultra_portlist[i]) == 0)
119                         return 0;
120 
121         return -ENODEV;
122 }
123 
124 static int __init ultra_probe1(struct net_device *dev, int ioaddr)
125 {
126         int i, retval;
127         int checksum = 0;
128         const char *model_name;
129         unsigned char eeprom_irq = 0;
130         static unsigned version_printed;
131         /* Values from various config regs. */
132         unsigned char num_pages, irqreg, addr, piomode;
133         unsigned char idreg = inb(ioaddr + 7);
134         unsigned char reg4 = inb(ioaddr + 4) & 0x7f;
135 
136         if (!request_region(ioaddr, ULTRA_IO_EXTENT, dev->name))
137                 return -EBUSY;
138 
139         /* Check the ID nibble. */
140         if ((idreg & 0xF0) != 0x20                      /* SMC Ultra */
141                 && (idreg & 0xF0) != 0x40) {            /* SMC EtherEZ */
142                 retval = -ENODEV;
143                 goto out;
144         }
145 
146         /* Select the station address register set. */
147         outb(reg4, ioaddr + 4);
148 
149         for (i = 0; i < 8; i++)
150                 checksum += inb(ioaddr + 8 + i);
151         if ((checksum & 0xff) != 0xFF) {
152                 retval = -ENODEV;
153                 goto out;
154         }
155 
156         if (ei_debug  &&  version_printed++ == 0)
157                 printk(version);
158 
159         model_name = (idreg & 0xF0) == 0x20 ? "SMC Ultra" : "SMC EtherEZ";
160 
161         printk("%s: %s at %#3x,", dev->name, model_name, ioaddr);
162 
163         for (i = 0; i < 6; i++)
164                 printk(" %2.2X", dev->dev_addr[i] = inb(ioaddr + 8 + i));
165 
166         /* Switch from the station address to the alternate register set and
167            read the useful registers there. */
168         outb(0x80 | reg4, ioaddr + 4);
169 
170         /* Enabled FINE16 mode to avoid BIOS ROM width mismatches @ reboot. */
171         outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);
172         piomode = inb(ioaddr + 0x8);
173         addr = inb(ioaddr + 0xb);
174         irqreg = inb(ioaddr + 0xd);
175 
176         /* Switch back to the station address register set so that the MS-DOS driver
177            can find the card after a warm boot. */
178         outb(reg4, ioaddr + 4);
179 
180         if (dev->irq < 2) {
181                 unsigned char irqmap[] = {0, 9, 3, 5, 7, 10, 11, 15};
182                 int irq;
183 
184                 /* The IRQ bits are split. */
185                 irq = irqmap[((irqreg & 0x40) >> 4) + ((irqreg & 0x0c) >> 2)];
186 
187                 if (irq == 0) {
188                         printk(", failed to detect IRQ line.\n");
189                         retval =  -EAGAIN;
190                         goto out;
191                 }
192                 dev->irq = irq;
193                 eeprom_irq = 1;
194         }
195 
196         /* Allocate dev->priv and fill in 8390 specific dev fields. */
197         if (ethdev_init(dev)) {
198                 printk (", no memory for dev->priv.\n");
199                 retval = -ENOMEM;
200                 goto out;
201         }
202 
203         /* The 8390 isn't at the base address, so fake the offset */
204         dev->base_addr = ioaddr+ULTRA_NIC_OFFSET;
205 
206         {
207                 int addr_tbl[4] = {0x0C0000, 0x0E0000, 0xFC0000, 0xFE0000};
208                 short num_pages_tbl[4] = {0x20, 0x40, 0x80, 0xff};
209 
210                 dev->mem_start = ((addr & 0x0f) << 13) + addr_tbl[(addr >> 6) & 3] ;
211                 num_pages = num_pages_tbl[(addr >> 4) & 3];
212         }
213 
214         ei_status.name = model_name;
215         ei_status.word16 = 1;
216         ei_status.tx_start_page = START_PG;
217         ei_status.rx_start_page = START_PG + TX_PAGES;
218         ei_status.stop_page = num_pages;
219 
220         dev->rmem_start = dev->mem_start + TX_PAGES*256;
221         dev->mem_end = dev->rmem_end
222                 = dev->mem_start + (ei_status.stop_page - START_PG)*256;
223 
224         if (piomode) {
225                 printk(",%s IRQ %d programmed-I/O mode.\n",
226                            eeprom_irq ? "EEPROM" : "assigned ", dev->irq);
227                 ei_status.block_input = &ultra_pio_input;
228                 ei_status.block_output = &ultra_pio_output;
229                 ei_status.get_8390_hdr = &ultra_pio_get_hdr;
230         } else {
231                 printk(",%s IRQ %d memory %#lx-%#lx.\n", eeprom_irq ? "" : "assigned ",
232                            dev->irq, dev->mem_start, dev->mem_end-1);
233                 ei_status.block_input = &ultra_block_input;
234                 ei_status.block_output = &ultra_block_output;
235                 ei_status.get_8390_hdr = &ultra_get_8390_hdr;
236         }
237         ei_status.reset_8390 = &ultra_reset_8390;
238         dev->open = &ultra_open;
239         dev->stop = &ultra_close_card;
240         NS8390_init(dev, 0);
241 
242         return 0;
243 out:
244         release_region(ioaddr, ULTRA_IO_EXTENT);
245         return retval;
246 }
247 
248 static int
249 ultra_open(struct net_device *dev)
250 {
251         int retval;
252         int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
253         unsigned char irq2reg[] = {0, 0, 0x04, 0x08, 0, 0x0C, 0, 0x40,
254                                    0, 0x04, 0x44, 0x48, 0, 0, 0, 0x4C, };
255 
256         retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev);
257         if (retval)
258                 return retval;
259 
260         outb(0x00, ioaddr);     /* Disable shared memory for safety. */
261         outb(0x80, ioaddr + 5);
262         /* Set the IRQ line. */
263         outb(inb(ioaddr + 4) | 0x80, ioaddr + 4);
264         outb((inb(ioaddr + 13) & ~0x4C) | irq2reg[dev->irq], ioaddr + 13);
265         outb(inb(ioaddr + 4) & 0x7f, ioaddr + 4);
266 
267         if (ei_status.block_input == &ultra_pio_input) {
268                 outb(0x11, ioaddr + 6);         /* Enable interrupts and PIO. */
269                 outb(0x01, ioaddr + 0x19);      /* Enable ring read auto-wrap. */
270         } else
271                 outb(0x01, ioaddr + 6);         /* Enable interrupts and memory. */
272         /* Set the early receive warning level in window 0 high enough not
273            to receive ERW interrupts. */
274         outb_p(E8390_NODMA+E8390_PAGE0, dev->base_addr);
275         outb(0xff, dev->base_addr + EN0_ERWCNT);
276         ei_open(dev);
277         return 0;
278 }
279 
280 static void
281 ultra_reset_8390(struct net_device *dev)
282 {
283         int cmd_port = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC base addr */
284 
285         outb(ULTRA_RESET, cmd_port);
286         if (ei_debug > 1) printk("resetting Ultra, t=%ld...", jiffies);
287         ei_status.txing = 0;
288 
289         outb(0x00, cmd_port);   /* Disable shared memory for safety. */
290         outb(0x80, cmd_port + 5);
291         if (ei_status.block_input == &ultra_pio_input)
292                 outb(0x11, cmd_port + 6);               /* Enable interrupts and PIO. */
293         else
294                 outb(0x01, cmd_port + 6);               /* Enable interrupts and memory. */
295 
296         if (ei_debug > 1) printk("reset done\n");
297         return;
298 }
299 
300 /* Grab the 8390 specific header. Similar to the block_input routine, but
301    we don't need to be concerned with ring wrap as the header will be at
302    the start of a page, so we optimize accordingly. */
303 
304 static void
305 ultra_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
306 {
307         unsigned long hdr_start = dev->mem_start + ((ring_page - START_PG)<<8);
308 
309         outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);  /* shmem on */
310 #ifdef notdef
311         /* Officially this is what we are doing, but the readl() is faster */
312         isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
313 #else
314         ((unsigned int*)hdr)[0] = isa_readl(hdr_start);
315 #endif
316         outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem off */
317 }
318 
319 /* Block input and output are easy on shared memory ethercards, the only
320    complication is when the ring buffer wraps. */
321 
322 static void
323 ultra_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
324 {
325         unsigned long xfer_start = dev->mem_start + ring_offset - (START_PG<<8);
326 
327         /* Enable shared memory. */
328         outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);
329 
330         if (xfer_start + count > dev->rmem_end) {
331                 /* We must wrap the input move. */
332                 int semi_count = dev->rmem_end - xfer_start;
333                 isa_memcpy_fromio(skb->data, xfer_start, semi_count);
334                 count -= semi_count;
335                 isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
336         } else {
337                 /* Packet is in one chunk -- we can copy + cksum. */
338                 isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
339         }
340 
341         outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET);  /* Disable memory. */
342 }
343 
344 static void
345 ultra_block_output(struct net_device *dev, int count, const unsigned char *buf,
346                                 int start_page)
347 {
348         unsigned long shmem = dev->mem_start + ((start_page - START_PG)<<8);
349 
350         /* Enable shared memory. */
351         outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);
352 
353         isa_memcpy_toio(shmem, buf, count);
354 
355         outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* Disable memory. */
356 }
357 
358 /* The identical operations for programmed I/O cards.
359    The PIO model is trivial to use: the 16 bit start address is written
360    byte-sequentially to IOPA, with no intervening I/O operations, and the
361    data is read or written to the IOPD data port.
362    The only potential complication is that the address register is shared
363    and must be always be rewritten between each read/write direction change.
364    This is no problem for us, as the 8390 code ensures that we are single
365    threaded. */
366 static void ultra_pio_get_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
367                                                 int ring_page)
368 {
369         int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
370         outb(0x00, ioaddr + IOPA);      /* Set the address, LSB first. */
371         outb(ring_page, ioaddr + IOPA);
372         insw(ioaddr + IOPD, hdr, sizeof(struct e8390_pkt_hdr)>>1);
373 }
374 
375 static void ultra_pio_input(struct net_device *dev, int count,
376                                                   struct sk_buff *skb, int ring_offset)
377 {
378         int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
379     char *buf = skb->data;
380 
381         /* For now set the address again, although it should already be correct. */
382         outb(ring_offset, ioaddr + IOPA);       /* Set the address, LSB first. */
383         outb(ring_offset >> 8, ioaddr + IOPA);
384         /* We know skbuffs are padded to at least word alignment. */
385         insw(ioaddr + IOPD, buf, (count+1)>>1);
386 }
387 
388 static void ultra_pio_output(struct net_device *dev, int count,
389                                                         const unsigned char *buf, const int start_page)
390 {
391         int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
392         outb(0x00, ioaddr + IOPA);      /* Set the address, LSB first. */
393         outb(start_page, ioaddr + IOPA);
394         /* An extra odd byte is OK here as well. */
395         outsw(ioaddr + IOPD, buf, (count+1)>>1);
396 }
397 
398 static int
399 ultra_close_card(struct net_device *dev)
400 {
401         int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* CMDREG */
402 
403         netif_stop_queue(dev);
404 
405         if (ei_debug > 1)
406                 printk("%s: Shutting down ethercard.\n", dev->name);
407 
408         outb(0x00, ioaddr + 6);         /* Disable interrupts. */
409         free_irq(dev->irq, dev);
410 
411         NS8390_init(dev, 0);
412 
413         /* We should someday disable shared memory and change to 8-bit mode
414            "just in case"... */
415 
416         return 0;
417 }
418 
419 
420 #ifdef MODULE
421 #define MAX_ULTRA_CARDS 4       /* Max number of Ultra cards per module */
422 static struct net_device dev_ultra[MAX_ULTRA_CARDS];
423 static int io[MAX_ULTRA_CARDS];
424 static int irq[MAX_ULTRA_CARDS];
425 
426 MODULE_PARM(io, "1-" __MODULE_STRING(MAX_ULTRA_CARDS) "i");
427 MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ULTRA_CARDS) "i");
428 
429 EXPORT_NO_SYMBOLS;
430 
431 /* This is set up so that only a single autoprobe takes place per call.
432 ISA device autoprobes on a running machine are not recommended. */
433 int
434 init_module(void)
435 {
436         int this_dev, found = 0;
437 
438         for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) {
439                 struct net_device *dev = &dev_ultra[this_dev];
440                 dev->irq = irq[this_dev];
441                 dev->base_addr = io[this_dev];
442                 dev->init = ultra_probe;
443                 if (io[this_dev] == 0)  {
444                         if (this_dev != 0) break; /* only autoprobe 1st one */
445                         printk(KERN_NOTICE "smc-ultra.c: Presently autoprobing (not recommended) for a single card.\n");
446                 }
447                 if (register_netdev(dev) != 0) {
448                         printk(KERN_WARNING "smc-ultra.c: No SMC Ultra card found (i/o = 0x%x).\n", io[this_dev]);
449                         if (found != 0) return 0;       /* Got at least one. */
450                         return -ENXIO;
451                 }
452                 found++;
453         }
454 
455         return 0;
456 }
457 
458 void
459 cleanup_module(void)
460 {
461         int this_dev;
462 
463         for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) {
464                 struct net_device *dev = &dev_ultra[this_dev];
465                 if (dev->priv != NULL) {
466                         /* NB: ultra_close_card() does free_irq */
467                         int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET;
468                         unregister_netdev(dev);
469                         release_region(ioaddr, ULTRA_IO_EXTENT);
470                         kfree(dev->priv);
471                 }
472         }
473 }
474 #endif /* MODULE */
475 
476 
477 /*
478  * Local variables:
479  *  compile-command: "gcc -D__KERNEL__ -Wall -O6 -I/usr/src/linux/net/inet -c smc-ultra.c"
480  *  version-control: t
481  *  kept-new-versions: 5
482  *  c-indent-level: 4
483  *  c-basic-offset: 4
484  *  tab-width: 4
485  * End:
486  */
487 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.