1 /* e2100.c: A Cabletron E2100 series ethernet driver for linux. */ 2 /* 3 Written 1993 by Donald Becker. 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 Cabletron E2100 series ethercards. 10
11 The Author may be reached as becker@cesdis.gsfc.nasa.gov, or 12 C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 13
14 The E2100 series ethercard is a fairly generic shared memory 8390 15 implementation. The only unusual aspect is the way the shared memory 16 registers are set: first you do an inb() in what is normally the 17 station address region, and the low four bits of next outb() is used 18 as the write value for that register. Either someone wasn't too used 19 to dem bit en bites, or they were trying to obfusicate the programming 20 interface. 21
22 There is an additional complication when setting the window on the packet 23 buffer. You must first do a read into the packet buffer region with the 24 low 8 address bits the address setting the page for the start of the packet 25 buffer window, and then do the above operation. See mem_on() for details. 26
27 One bug on the chip is that even a hard reset won't disable the memory 28 window, usually resulting in a hung machine if mem_off() isn't called. 29 If this happens, you must power down the machine for about 30 seconds. 30 */ 31
32 staticchar *version =
33 "e2100.c:v0.01 11/21/93 Donald Becker (becker@super.org)\n";
34
35 #include <linux/config.h>
36 #include <linux/kernel.h>
37 #include <linux/sched.h>
38 #include <linux/errno.h>
39 #include <linux/string.h>
40 #include <asm/io.h>
41 #include <asm/system.h>
42 #ifndef PRE_PL13
43 #include <linux/ioport.h> /* Delete if your kernel doesn't have it. */ 44 #endif 45
46 #include <linux/netdevice.h>
47 #include "8390.h"
48
49 /* Compatibility definitions for earlier kernel versions. */ 50 #ifndefHAVE_PORTRESERVE 51 #definecheck_region(ioaddr, size) 0
52 #definesnarf_region(ioaddr, size); do ; while (0)
53 #endif 54 #ifndefHAVE_AUTOIRQ 55 /* From auto_irq.c, in ioport.h for later versions. */ 56 externvoidautoirq_setup(intwaittime);
57 externintautoirq_report(intwaittime);
58 /* The map from IRQ number (as passed to the interrupt handler) to 59 'struct device'. */ 60 externstructdevice *irq2dev_map[16];
61 #endif 62
63 /* Offsets from the base_addr. 64 Read from the ASIC register, and the low 3(?) bits of the next outb() address 65 is used to set the cooresponding register. */ 66 #define E21_NIC_OFFSET 0 /* Offset to the 8390 NIC. */ 67 #defineE21_ASIC 0x10
68 #defineE21_MEM_ENABLE 0x10
69 #defineE21_MEM_ON 0x05 /* Enable memory in 16 bit mode. */ 70 #define E21_MEM_ON_8 0x07 /* Enable memory in 8 bit mode. */ 71 #defineE21_MEM_BASE 0x11
72 #defineE21_IRQ_LOW 0x12 /* The low three bits of the IRQ number. */ 73 #defineE21_IRQ_HIGH 0x14 /* The high IRQ bit, and ... */ 74 #defineE21_ALT_IFPORT 0x02 /* Set to use the other (BNC,AUI) port. */ 75 #define E21_BIG_MEM 0x04 /* Use a bigger (64K) buffer (we don't) */ 76 #defineE21_SAPROM 0x10 /* Offset to station address data. */ 77 #defineETHERCARD_TOTAL_SIZE 0x20
78
79 externinlinevoidmem_on(shortport, volatilechar *mem_base,
/* */ 80 unsignedcharstart_page )
81 { 82 /* This is a little weird: set the shared memory window by doing a 83 read. The low address bits specify the starting page. */ 84 mem_base[start_page];
85 inb(port + E21_MEM_ENABLE);
86 outb(E21_MEM_ON, port + E21_MEM_ENABLE + E21_MEM_ON);
87 } 88
89 externinlinevoidmem_off(shortport)
/* */ 90 { 91 inb(port + E21_MEM_ENABLE);
92 outb(0x00, port + E21_MEM_ENABLE);
93 } 94
95 /* In other drivers I put the TX pages first, but the E2100 window circuitry 96 is designed to have a 4K Tx region last. The windowing circuitry wraps the 97 window at 0x2fff->0x0000 so that the packets at e.g. 0x2f00 in the RX ring 98 appear contiguously in the window. */ 99 #defineE21_RX_START_PG 0x00 /* First page of RX buffer */ 100 #defineE21_RX_STOP_PG 0x30 /* Last page +1 of RX ring */ 101 #define E21_BIG_RX_STOP_PG 0xF0 /* Last page +1 of RX ring */ 102 #defineE21_TX_START_PGE21_RX_STOP_PG/* First page of TX buffer */ 103
104 inte2100_probe(structdevice *dev);
105 inte21_probe1(structdevice *dev, intioaddr);
106
107 staticinte21_open(structdevice *dev);
108 staticvoide21_reset_8390(structdevice *dev);
109 staticinte21_block_input(structdevice *dev, intcount,
110 char *buf, intring_offset);
111 staticvoide21_block_output(structdevice *dev, intcount,
112 constunsignedchar *buf, conststart_page);
113 staticinte21_close(structdevice *dev);
114
115
116 /* Probe for the E2100 series ethercards. These cards have an 8390 at the 117 base address and the station address at both offset 0x10 and 0x18. I read 118 the station address from offset 0x18 to avoid the dataport of NE2000 119 ethercards, and look for Ctron's unique ID (first three octets of the 120 station address). 121 */ 122
123 inte2100_probe(structdevice *dev)
/* */ 124 { 125 int *port, ports[] = {0x300, 0x280, 0x380, 0x220, 0};
126 shortbase_addr = dev->base_addr;
127
128 if (base_addr > 0x1ff) /* Check a single specified location. */ 129 returne21_probe1(dev, base_addr);
130 elseif (base_addr > 0) /* Don't probe at all. */ 131 returnENXIO;
132
133 for (port = &ports[0]; *port; port++) { 134 ushortioaddr = *port;
135
136 if (check_region(ioaddr, ETHERCARD_TOTAL_SIZE))
137 continue;
138 if (inb(ioaddr + E21_SAPROM + 0) == 0x00
139 && inb(ioaddr + E21_SAPROM + 1) == 0x00
140 && inb(ioaddr + E21_SAPROM + 2) == 0x1d
141 && e21_probe1(dev, ioaddr) == 0)
142 return 0;
143 } 144 return -ENODEV;
145 } 146
147 inte21_probe1(structdevice *dev, intioaddr)
/* */ 148 { 149 inti, status;
150 unsignedchar *station_addr = dev->dev_addr;
151
152 /* We've already checked the station address prefix, now verify by making 153 certain that there is a 8390 at the expected location. */ 154 outb(E8390_NODMA + E8390_STOP, ioaddr);
155 SLOW_DOWN_IO;
156 status = inb(ioaddr);
157 if (status != 0x21 && status != 0x23)
158 return -ENODEV;
159
160 #ifdef testing_only
161 printk("%s: E21xx at %#3x (PAXI backwards): ", dev->name, ioaddr);
162 for (i = 0; i < 16; i++)
163 printk(" %02X", inb(ioaddr + 0x1f - i));
164 printk("\n");
165 #endif 166
167 /* Read the station address PROM. */ 168 for (i = 0; i < 6; i++)
169 station_addr[i] = inb(ioaddr + E21_SAPROM + i);
170
171 /* Grab the region so we can find another board if needed . */ 172 snarf_region(ioaddr, ETHERCARD_TOTAL_SIZE);
173
174 printk("%s: E21xx at %#3x, ", dev->name, ioaddr);
175 for (i = 0; i < 6; i++)
176 printk(" %02X", station_addr[i]);
177
178 if (dev->irq < 2) { 179 intirqlist[] = {15,11,10,12,5,9,3,4}, i;
180 for (i = 0; i < 8; i++)
181 if (request_irq (irqlist[i], NULL) != -EBUSY) { 182 dev->irq = irqlist[i];
183 break;
184 } 185 }elseif (dev->irq == 2) /* Fixup bogosity: IRQ2 is really IRQ9 */ 186 dev->irq = 9;
187
188 /* Snarf the interrupt now. */ 189 if (irqaction (dev->irq, &ei_sigaction)) { 190 printk (" unable to get IRQ %d.\n", dev->irq);
191 return -EBUSY;
192 } 193
194 /* The 8390 is at the base address. */ 195 dev->base_addr = ioaddr;
196
197 ethdev_init(dev);
198
199 ei_status.name = "E2100";
200 ei_status.word16 = 1;
201 ei_status.tx_start_page = E21_TX_START_PG;
202 ei_status.rx_start_page = E21_RX_START_PG;
203 ei_status.stop_page = E21_RX_STOP_PG;
204
205 /* Check the media port used. The port can be passed in on the 206 low mem_end bits. */ 207 if (dev->mem_end & 15)
208 dev->if_port = dev->mem_end & 7;
209 else{ 210 dev->if_port = 0;
211 inb_p(ioaddr + E21_IRQ_HIGH); /* Select if_port detect. */ 212 for(i = 0; i < 6; i++)
213 if (station_addr[i] != inb(ioaddr + E21_SAPROM))
214 dev->if_port = 1;
215 } 216
217 /* Never map in the E21 shared memory unless you are actively using it. 218 Also, the shared memory has effective only one setting -- spread all 219 over the 128K region! */ 220 if (dev->mem_start == 0)
221 dev->mem_start = 0xd0000;
222
223 #ifdef notdef
224 /* These values are unused. The E2100 has a 2K window into the packet 225 buffer. The window can be set to start on any page boundary. */ 226 dev->rmem_start = dev->mem_start + TX_PAGES*256;
227 dev->mem_end = dev->rmem_end = dev->mem_start + 2*1024;
228 #endif 229
230 printk(" IRQ %d, %s interface, memory at %#x-%#x.\n", dev->irq,
231 dev->if_port ? "secondary" : "primary", dev->mem_start,
232 dev->mem_start + 2*1024 - 1);
233
234 if (ei_debug > 0)
235 printk(version);
236
237 ei_status.reset_8390 = &e21_reset_8390;
238 ei_status.block_input = &e21_block_input;
239 ei_status.block_output = &e21_block_output;
240 dev->open = &e21_open;
241 dev->stop = &e21_close;
242 NS8390_init(dev, 0);
243
244 return 0;
245 } 246
247 staticint 248 e21_open(structdevice *dev)
/* */ 249 { 250 shortioaddr = dev->base_addr;
251
252 /* Set the interrupt line and memory base on the hardware. */ 253 inb_p(ioaddr + E21_IRQ_LOW);
254 outb_p(0, ioaddr + E21_ASIC + (dev->irq & 7));
255 inb_p(ioaddr + E21_IRQ_HIGH); /* High IRQ bit, and if_port. */ 256 outb_p(0, ioaddr + E21_ASIC + (dev->irq > 7 ? 1:0)
257 + (dev->if_port ? E21_ALT_IFPORT : 0));
258 inb_p(ioaddr + E21_MEM_BASE);
259 outb_p(0, ioaddr + E21_ASIC + ((dev->mem_start >> 17) & 7));
260
261 returnei_open(dev);
262 } 263
264 staticvoid 265 e21_reset_8390(structdevice *dev)
/* */ 266 { 267 shortioaddr = dev->base_addr;
268
269 outb(0x01, ioaddr);
270 if (ei_debug > 1) printk("resetting the E2180x3 t=%d...", jiffies);
271 ei_status.txing = 0;
272
273 /* Set up the ASIC registers, just in case something changed them. */ 274
275 if (ei_debug > 1) printk("reset done\n");
276 return;
277 } 278
279 /* Block input and output are easy on shared memory ethercards. The E21xx makes 280 block_input() especially easy by wrapping the top ring buffer to the bottom 281 automatically. */ 282 staticint 283 e21_block_input(structdevice *dev, intcount, char *buf, intring_offset)
/* */ 284 { 285 shortioaddr = dev->base_addr;
286 char *shared_mem = (char *)dev->mem_start;
287 intstart_page = (ring_offset>>8);
288
289 mem_on(ioaddr, shared_mem, start_page);
290
291 /* We'll always get a 4 byte header read first. */ 292 if (count == 4)
293 ((int*)buf)[0] = ((int*)shared_mem)[0];
294 else 295 memcpy(buf, shared_mem + (ring_offset & 0xff), count);
296
297 /* Turn off memory access: we would need to reprogram the window anyway. */ 298 mem_off(ioaddr);
299
300 return 0;
301 } 302
303 staticvoid 304 e21_block_output(structdevice *dev, intcount, constunsignedchar *buf,
/* */ 305 intstart_page)
306 { 307 shortioaddr = dev->base_addr;
308 volatilechar *shared_mem = (char *)dev->mem_start;
309
310 /* Set the shared memory window start by doing a read, with the low address 311 bits specifing the starting page. */ 312 *(shared_mem + start_page);
313 mem_on(ioaddr, shared_mem, start_page);
314
315 memcpy((char*)shared_mem, buf, count);
316 mem_off(ioaddr);
317 } 318
319 staticint 320 e21_close(structdevice *dev)
/* */ 321 { 322 shortioaddr = dev->base_addr;
323
324 if (ei_debug > 1)
325 printk("%s: Shutting down ethercard.\n", dev->name);
326 NS8390_init(dev, 0);
327
328 mem_off(ioaddr);
329
330 return 0;
331 } 332
333
334 /* 335 * Local variables: 336 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c e2100.c" 337 * version-control: t 338 * tab-width: 4 339 * kept-new-versions: 5 340 * End: 341 */