OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [net/] [smc-ultra.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.