|
|
1.1 root 1: /* ac3200.c: A driver for the Ansel Communications EISA ethernet adaptor. */
2: /*
3: Written 1993, 1994 by Donald Becker.
4: Copyright 1993 United States Government as represented by the Director,
5: National Security Agency. This software may only be used and distributed
6: according to the terms of the GNU Public License as modified by SRC,
7: incorporated herein by reference.
8:
9: The author may be reached as [email protected], or
10: C/O Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
11:
12: This is driver for the Ansel Communications Model 3200 EISA Ethernet LAN
13: Adapter. The programming information is from the users manual, as related
14: by [email protected].
15: */
16:
17: static const char *version =
18: "ac3200.c:v1.01 7/1/94 Donald Becker ([email protected])\n";
19:
20: #include <linux/module.h>
21:
22: #include <linux/kernel.h>
23: #include <linux/sched.h>
24: #include <linux/errno.h>
25: #include <linux/string.h>
26: #include <linux/netdevice.h>
27: #include <linux/etherdevice.h>
28:
29: #include <asm/system.h>
30: #include <asm/io.h>
31:
32: #include "8390.h"
33:
34: /* Offsets from the base address. */
35: #define AC_NIC_BASE 0x00
36: #define AC_SA_PROM 0x16 /* The station address PROM. */
37: #define AC_ADDR0 0x00 /* Prefix station address values. */
38: #define AC_ADDR1 0x40 /* !!!!These are just guesses!!!! */
39: #define AC_ADDR2 0x90
40: #define AC_ID_PORT 0xC80
41: #define AC_EISA_ID 0x0110d305
42: #define AC_RESET_PORT 0xC84
43: #define AC_RESET 0x00
44: #define AC_ENABLE 0x01
45: #define AC_CONFIG 0xC90 /* The configuration port. */
46:
47: #define AC_IO_EXTENT 0x10 /* IS THIS REALLY TRUE ??? */
48: /* Actually accessed is:
49: * AC_NIC_BASE (0-15)
50: * AC_SA_PROM (0-5)
51: * AC_ID_PORT (0-3)
52: * AC_RESET_PORT
53: * AC_CONFIG
54: */
55:
56: /* Decoding of the configuration register. */
57: static unsigned char config2irqmap[8] = {15, 12, 11, 10, 9, 7, 5, 3};
58: static int addrmap[8] =
59: {0xFF0000, 0xFE0000, 0xFD0000, 0xFFF0000, 0xFFE0000, 0xFFC0000, 0xD0000, 0 };
60: static const char *port_name[4] = { "10baseT", "invalid", "AUI", "10base2"};
61:
62: #define config2irq(configval) config2irqmap[((configval) >> 3) & 7]
63: #define config2mem(configval) addrmap[(configval) & 7]
64: #define config2name(configval) port_name[((configval) >> 6) & 3]
65:
66: /* First and last 8390 pages. */
67: #define AC_START_PG 0x00 /* First page of 8390 TX buffer */
68: #define AC_STOP_PG 0x80 /* Last page +1 of the 8390 RX ring */
69:
70: int ac3200_probe(struct device *dev);
71: static int ac_probe1(int ioaddr, struct device *dev);
72:
73: static int ac_open(struct device *dev);
74: static void ac_reset_8390(struct device *dev);
75: static void ac_block_input(struct device *dev, int count,
76: struct sk_buff *skb, int ring_offset);
77: static void ac_block_output(struct device *dev, const int count,
78: const unsigned char *buf, const int start_page);
79: static void ac_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
80: int ring_page);
81:
82: static int ac_close_card(struct device *dev);
83:
84:
85: /* Probe for the AC3200.
86:
87: The AC3200 can be identified by either the EISA configuration registers,
88: or the unique value in the station address PROM.
89: */
90:
91: int ac3200_probe(struct device *dev)
92: {
93: unsigned short ioaddr = dev->base_addr;
94:
95: if (ioaddr > 0x1ff) /* Check a single specified location. */
96: return ac_probe1(ioaddr, dev);
97: else if (ioaddr > 0) /* Don't probe at all. */
98: return ENXIO;
99:
100: /* If you have a pre 0.99pl15 machine you should delete this line. */
101: if ( ! EISA_bus)
102: return ENXIO;
103:
104: for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
105: if (check_region(ioaddr, AC_IO_EXTENT))
106: continue;
107: if (ac_probe1(ioaddr, dev) == 0)
108: return 0;
109: }
110:
111: return ENODEV;
112: }
113:
114: static int ac_probe1(int ioaddr, struct device *dev)
115: {
116: int i;
117:
118: #ifndef final_version
119: printk("AC3200 ethercard probe at %#3x:", ioaddr);
120:
121: for(i = 0; i < 6; i++)
122: printk(" %02x", inb(ioaddr + AC_SA_PROM + i));
123: #endif
124:
125: /* !!!!The values of AC_ADDRn (see above) should be corrected when we
126: find out the correct station address prefix!!!! */
127: if (inb(ioaddr + AC_SA_PROM + 0) != AC_ADDR0
128: || inb(ioaddr + AC_SA_PROM + 1) != AC_ADDR1
129: || inb(ioaddr + AC_SA_PROM + 2) != AC_ADDR2 ) {
130: #ifndef final_version
131: printk(" not found (invalid prefix).\n");
132: #endif
133: return ENODEV;
134: }
135:
136: /* The correct probe method is to check the EISA ID. */
137: for (i = 0; i < 4; i++)
138: if (inl(ioaddr + AC_ID_PORT) != AC_EISA_ID) {
139: printk("EISA ID mismatch, %8x vs %8x.\n",
140: inl(ioaddr + AC_ID_PORT), AC_EISA_ID);
141: return ENODEV;
142: }
143:
144:
145: /* We should have a "dev" from Space.c or the static module table. */
146: if (dev == NULL) {
147: printk("ac3200.c: Passed a NULL device.\n");
148: dev = init_etherdev(0, 0);
149: }
150:
151: for(i = 0; i < ETHER_ADDR_LEN; i++)
152: dev->dev_addr[i] = inb(ioaddr + AC_SA_PROM + i);
153:
154: #ifndef final_version
155: printk("\nAC3200 ethercard configuration register is %#02x,"
156: " EISA ID %02x %02x %02x %02x.\n", inb(ioaddr + AC_CONFIG),
157: inb(ioaddr + AC_ID_PORT + 0), inb(ioaddr + AC_ID_PORT + 1),
158: inb(ioaddr + AC_ID_PORT + 2), inb(ioaddr + AC_ID_PORT + 3));
159: #endif
160:
161: /* Assign and allocate the interrupt now. */
162: if (dev->irq == 0)
163: dev->irq = config2irq(inb(ioaddr + AC_CONFIG));
164: else if (dev->irq == 2)
165: dev->irq = 9;
166:
167: if (request_irq(dev->irq, ei_interrupt, 0, "ac3200", NULL)) {
168: printk (" unable to get IRQ %d.\n", dev->irq);
169: return EAGAIN;
170: }
171:
172: /* Allocate dev->priv and fill in 8390 specific dev fields. */
173: if (ethdev_init(dev)) {
174: printk (" unable to allocate memory for dev->priv.\n");
175: free_irq(dev->irq, NULL);
176: return -ENOMEM;
177: }
178:
179: request_region(ioaddr, AC_IO_EXTENT, "ac3200");
180:
181: dev->base_addr = ioaddr;
182:
183: #ifdef notyet
184: if (dev->mem_start) { /* Override the value from the board. */
185: for (i = 0; i < 7; i++)
186: if (addrmap[i] == dev->mem_start)
187: break;
188: if (i >= 7)
189: i = 0;
190: outb((inb(ioaddr + AC_CONFIG) & ~7) | i, ioaddr + AC_CONFIG);
191: }
192: #endif
193:
194: dev->if_port = inb(ioaddr + AC_CONFIG) >> 6;
195: dev->mem_start = config2mem(inb(ioaddr + AC_CONFIG));
196: dev->rmem_start = dev->mem_start + TX_PAGES*256;
197: dev->mem_end = dev->rmem_end = dev->mem_start
198: + (AC_STOP_PG - AC_START_PG)*256;
199:
200: ei_status.name = "AC3200";
201: ei_status.tx_start_page = AC_START_PG;
202: ei_status.rx_start_page = AC_START_PG + TX_PAGES;
203: ei_status.stop_page = AC_STOP_PG;
204: ei_status.word16 = 1;
205:
206: printk("\n%s: AC3200 at %#x, IRQ %d, %s port, shared memory %#lx-%#lx.\n",
207: dev->name, ioaddr, dev->irq, port_name[dev->if_port],
208: dev->mem_start, dev->mem_end-1);
209:
210: if (ei_debug > 0)
1.1.1.2 ! root 211: printk("%s", version);
1.1 root 212:
213: ei_status.reset_8390 = &ac_reset_8390;
214: ei_status.block_input = &ac_block_input;
215: ei_status.block_output = &ac_block_output;
216: ei_status.get_8390_hdr = &ac_get_8390_hdr;
217:
218: dev->open = &ac_open;
219: dev->stop = &ac_close_card;
220: NS8390_init(dev, 0);
221: return 0;
222: }
223:
224: static int ac_open(struct device *dev)
225: {
226: #ifdef notyet
227: /* Someday we may enable the IRQ and shared memory here. */
228: int ioaddr = dev->base_addr;
229:
230: if (request_irq(dev->irq, ei_interrupt, 0, "ac3200", NULL))
231: return -EAGAIN;
232: #endif
233:
234: ei_open(dev);
235:
236: MOD_INC_USE_COUNT;
237:
238: return 0;
239: }
240:
241: static void ac_reset_8390(struct device *dev)
242: {
243: ushort ioaddr = dev->base_addr;
244:
245: outb(AC_RESET, ioaddr + AC_RESET_PORT);
246: if (ei_debug > 1) printk("resetting AC3200, t=%ld...", jiffies);
247:
248: ei_status.txing = 0;
249: outb(AC_ENABLE, ioaddr + AC_RESET_PORT);
250: if (ei_debug > 1) printk("reset done\n");
251:
252: return;
253: }
254:
255: /* Grab the 8390 specific header. Similar to the block_input routine, but
256: we don't need to be concerned with ring wrap as the header will be at
257: the start of a page, so we optimize accordingly. */
258:
259: static void
260: ac_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
261: {
262: unsigned long hdr_start = dev->mem_start + ((ring_page - AC_START_PG)<<8);
263: memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
264: }
265:
266: /* Block input and output are easy on shared memory ethercards, the only
267: complication is when the ring buffer wraps. */
268:
269: static void ac_block_input(struct device *dev, int count, struct sk_buff *skb,
270: int ring_offset)
271: {
272: unsigned long xfer_start = dev->mem_start + ring_offset - (AC_START_PG<<8);
273:
274: if (xfer_start + count > dev->rmem_end) {
275: /* We must wrap the input move. */
276: int semi_count = dev->rmem_end - xfer_start;
277: memcpy_fromio(skb->data, xfer_start, semi_count);
278: count -= semi_count;
279: memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
280: } else {
281: /* Packet is in one chunk -- we can copy + cksum. */
282: eth_io_copy_and_sum(skb, xfer_start, count, 0);
283: }
284: }
285:
286: static void ac_block_output(struct device *dev, int count,
287: const unsigned char *buf, int start_page)
288: {
289: unsigned long shmem = dev->mem_start + ((start_page - AC_START_PG)<<8);
290:
291: memcpy_toio(shmem, buf, count);
292: }
293:
294: static int ac_close_card(struct device *dev)
295: {
296: dev->start = 0;
297: dev->tbusy = 1;
298:
299: if (ei_debug > 1)
300: printk("%s: Shutting down ethercard.\n", dev->name);
301:
302: #ifdef notyet
303: /* We should someday disable shared memory and interrupts. */
304: outb(0x00, ioaddr + 6); /* Disable interrupts. */
305: free_irq(dev->irq, NULL);
306: irq2dev_map[dev->irq] = 0;
307: #endif
308:
309: ei_close(dev);
310:
311: MOD_DEC_USE_COUNT;
312:
313: return 0;
314: }
315:
316: #ifdef MODULE
317: #define MAX_AC32_CARDS 4 /* Max number of AC32 cards per module */
318: #define NAMELEN 8 /* # of chars for storing dev->name */
319: static char namelist[NAMELEN * MAX_AC32_CARDS] = { 0, };
320: static struct device dev_ac32[MAX_AC32_CARDS] = {
321: {
322: NULL, /* assign a chunk of namelist[] below */
323: 0, 0, 0, 0,
324: 0, 0,
325: 0, 0, 0, NULL, NULL
326: },
327: };
328:
329: static int io[MAX_AC32_CARDS] = { 0, };
330: static int irq[MAX_AC32_CARDS] = { 0, };
331: static int mem[MAX_AC32_CARDS] = { 0, };
332:
333: int
334: init_module(void)
335: {
336: int this_dev, found = 0;
337:
338: for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
339: struct device *dev = &dev_ac32[this_dev];
340: dev->name = namelist+(NAMELEN*this_dev);
341: dev->irq = irq[this_dev];
342: dev->base_addr = io[this_dev];
343: dev->mem_start = mem[this_dev]; /* Currently ignored by driver */
344: dev->init = ac3200_probe;
345: /* Default is to only install one card. */
346: if (io[this_dev] == 0 && this_dev != 0) break;
347: if (register_netdev(dev) != 0) {
348: printk(KERN_WARNING "ac3200.c: No ac3200 card found (i/o = 0x%x).\n", io[this_dev]);
349: if (found != 0) return 0; /* Got at least one. */
350: return -ENXIO;
351: }
352: found++;
353: }
354:
355: return 0;
356: }
357:
358: void
359: cleanup_module(void)
360: {
361: int this_dev;
362:
363: for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
364: struct device *dev = &dev_ac32[this_dev];
365: if (dev->priv != NULL) {
366: kfree(dev->priv);
367: dev->priv = NULL;
368: /* Someday free_irq + irq2dev may be in ac_close_card() */
369: free_irq(dev->irq, NULL);
370: irq2dev_map[dev->irq] = NULL;
371: release_region(dev->base_addr, AC_IO_EXTENT);
372: unregister_netdev(dev);
373: }
374: }
375: }
376: #endif /* MODULE */
377:
378: /*
379: * Local variables:
380: * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c ac3200.c"
381: * version-control: t
382: * kept-new-versions: 5
383: * tab-width: 4
384: * End:
385: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.