Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Amiga Linux/m68k and Linux/PPC Zorro NS8390 Ethernet Driver | |
3 | * | |
4 | * (C) Copyright 1998-2000 by some Elitist 680x0 Users(TM) | |
5 | * | |
6 | * --------------------------------------------------------------------------- | |
7 | * | |
8 | * This program is based on all the other NE2000 drivers for Linux | |
9 | * | |
10 | * --------------------------------------------------------------------------- | |
11 | * | |
12 | * This file is subject to the terms and conditions of the GNU General Public | |
13 | * License. See the file COPYING in the main directory of the Linux | |
14 | * distribution for more details. | |
15 | * | |
16 | * --------------------------------------------------------------------------- | |
17 | * | |
18 | * The Ariadne II and X-Surf are Zorro-II boards containing Realtek RTL8019AS | |
19 | * Ethernet Controllers. | |
20 | */ | |
21 | ||
572404ea JP |
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
23 | ||
1da177e4 LT |
24 | #include <linux/module.h> |
25 | #include <linux/kernel.h> | |
26 | #include <linux/errno.h> | |
27 | #include <linux/init.h> | |
28 | #include <linux/delay.h> | |
29 | #include <linux/netdevice.h> | |
30 | #include <linux/etherdevice.h> | |
31 | #include <linux/zorro.h> | |
ff5688ae | 32 | #include <linux/jiffies.h> |
1da177e4 LT |
33 | |
34 | #include <asm/system.h> | |
35 | #include <asm/irq.h> | |
36 | #include <asm/amigaints.h> | |
37 | #include <asm/amigahw.h> | |
38 | ||
572404ea JP |
39 | #define EI_SHIFT(x) (ei_local->reg_offset[x]) |
40 | #define ei_inb(port) in_8(port) | |
41 | #define ei_outb(val, port) out_8(port, val) | |
42 | #define ei_inb_p(port) in_8(port) | |
43 | #define ei_outb_p(val, port) out_8(port, val) | |
1da177e4 | 44 | |
8c6270f9 | 45 | static const char version[] = |
572404ea | 46 | "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; |
8c6270f9 AV |
47 | |
48 | #include "lib8390.c" | |
1da177e4 LT |
49 | |
50 | #define DRV_NAME "zorro8390" | |
51 | ||
52 | #define NE_BASE (dev->base_addr) | |
572404ea JP |
53 | #define NE_CMD (0x00 * 2) |
54 | #define NE_DATAPORT (0x10 * 2) /* NatSemi-defined port window offset */ | |
55 | #define NE_RESET (0x1f * 2) /* Issue a read to reset, | |
56 | * a write to clear. */ | |
57 | #define NE_IO_EXTENT (0x20 * 2) | |
58 | ||
59 | #define NE_EN0_ISR (0x07 * 2) | |
60 | #define NE_EN0_DCFG (0x0e * 2) | |
61 | ||
62 | #define NE_EN0_RSARLO (0x08 * 2) | |
63 | #define NE_EN0_RSARHI (0x09 * 2) | |
64 | #define NE_EN0_RCNTLO (0x0a * 2) | |
65 | #define NE_EN0_RXCR (0x0c * 2) | |
66 | #define NE_EN0_TXCR (0x0d * 2) | |
67 | #define NE_EN0_RCNTHI (0x0b * 2) | |
68 | #define NE_EN0_IMR (0x0f * 2) | |
1da177e4 LT |
69 | |
70 | #define NESM_START_PG 0x40 /* First page of TX buffer */ | |
71 | #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ | |
72 | ||
572404ea | 73 | #define WORDSWAP(a) ((((a) >> 8) & 0xff) | ((a) << 8)) |
1da177e4 LT |
74 | |
75 | static struct card_info { | |
572404ea JP |
76 | zorro_id id; |
77 | const char *name; | |
78 | unsigned int offset; | |
1da177e4 | 79 | } cards[] __devinitdata = { |
572404ea JP |
80 | { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, "Ariadne II", 0x0600 }, |
81 | { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, "X-Surf", 0x8600 }, | |
1da177e4 LT |
82 | }; |
83 | ||
572404ea JP |
84 | /* Hard reset the card. This used to pause for the same period that a |
85 | * 8390 reset command required, but that shouldn't be necessary. | |
86 | */ | |
87 | static void zorro8390_reset_8390(struct net_device *dev) | |
88 | { | |
89 | unsigned long reset_start_time = jiffies; | |
90 | ||
91 | if (ei_debug > 1) | |
92 | netdev_dbg(dev, "resetting - t=%ld...\n", jiffies); | |
93 | ||
94 | z_writeb(z_readb(NE_BASE + NE_RESET), NE_BASE + NE_RESET); | |
95 | ||
96 | ei_status.txing = 0; | |
97 | ei_status.dmaing = 0; | |
98 | ||
99 | /* This check _should_not_ be necessary, omit eventually. */ | |
100 | while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RESET) == 0) | |
101 | if (time_after(jiffies, reset_start_time + 2 * HZ / 100)) { | |
102 | netdev_warn(dev, "%s: did not complete\n", __func__); | |
103 | break; | |
104 | } | |
105 | z_writeb(ENISR_RESET, NE_BASE + NE_EN0_ISR); /* Ack intr */ | |
106 | } | |
107 | ||
108 | /* Grab the 8390 specific header. Similar to the block_input routine, but | |
109 | * we don't need to be concerned with ring wrap as the header will be at | |
110 | * the start of a page, so we optimize accordingly. | |
111 | */ | |
1da177e4 | 112 | static void zorro8390_get_8390_hdr(struct net_device *dev, |
572404ea JP |
113 | struct e8390_pkt_hdr *hdr, int ring_page) |
114 | { | |
115 | int nic_base = dev->base_addr; | |
116 | int cnt; | |
117 | short *ptrs; | |
118 | ||
119 | /* This *shouldn't* happen. | |
120 | * If it does, it's the last thing you'll see | |
121 | */ | |
122 | if (ei_status.dmaing) { | |
123 | netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n", | |
124 | __func__, ei_status.dmaing, ei_status.irqlock); | |
125 | return; | |
126 | } | |
127 | ||
128 | ei_status.dmaing |= 0x01; | |
129 | z_writeb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD); | |
130 | z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); | |
131 | z_writeb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO); | |
132 | z_writeb(0, nic_base + NE_EN0_RCNTHI); | |
133 | z_writeb(0, nic_base + NE_EN0_RSARLO); /* On page boundary */ | |
134 | z_writeb(ring_page, nic_base + NE_EN0_RSARHI); | |
135 | z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD); | |
136 | ||
137 | ptrs = (short *)hdr; | |
138 | for (cnt = 0; cnt < sizeof(struct e8390_pkt_hdr) >> 1; cnt++) | |
139 | *ptrs++ = z_readw(NE_BASE + NE_DATAPORT); | |
140 | ||
141 | z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr */ | |
142 | ||
143 | hdr->count = WORDSWAP(hdr->count); | |
144 | ||
145 | ei_status.dmaing &= ~0x01; | |
146 | } | |
147 | ||
148 | /* Block input and output, similar to the Crynwr packet driver. | |
149 | * If you are porting to a new ethercard, look at the packet driver source | |
150 | * for hints. The NEx000 doesn't share the on-board packet memory -- | |
151 | * you have to put the packet out through the "remote DMA" dataport | |
152 | * using z_writeb. | |
153 | */ | |
1da177e4 | 154 | static void zorro8390_block_input(struct net_device *dev, int count, |
572404ea JP |
155 | struct sk_buff *skb, int ring_offset) |
156 | { | |
157 | int nic_base = dev->base_addr; | |
158 | char *buf = skb->data; | |
159 | short *ptrs; | |
160 | int cnt; | |
161 | ||
162 | /* This *shouldn't* happen. | |
163 | * If it does, it's the last thing you'll see | |
164 | */ | |
165 | if (ei_status.dmaing) { | |
166 | netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n", | |
167 | __func__, ei_status.dmaing, ei_status.irqlock); | |
168 | return; | |
169 | } | |
170 | ei_status.dmaing |= 0x01; | |
171 | z_writeb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD); | |
172 | z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); | |
173 | z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO); | |
174 | z_writeb(count >> 8, nic_base + NE_EN0_RCNTHI); | |
175 | z_writeb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO); | |
176 | z_writeb(ring_offset >> 8, nic_base + NE_EN0_RSARHI); | |
177 | z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD); | |
178 | ptrs = (short *)buf; | |
179 | for (cnt = 0; cnt < count >> 1; cnt++) | |
180 | *ptrs++ = z_readw(NE_BASE + NE_DATAPORT); | |
181 | if (count & 0x01) | |
182 | buf[count - 1] = z_readb(NE_BASE + NE_DATAPORT); | |
183 | ||
184 | z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr */ | |
185 | ei_status.dmaing &= ~0x01; | |
186 | } | |
187 | ||
188 | static void zorro8390_block_output(struct net_device *dev, int count, | |
1da177e4 | 189 | const unsigned char *buf, |
572404ea JP |
190 | const int start_page) |
191 | { | |
192 | int nic_base = NE_BASE; | |
193 | unsigned long dma_start; | |
194 | short *ptrs; | |
195 | int cnt; | |
196 | ||
197 | /* Round the count up for word writes. Do we need to do this? | |
198 | * What effect will an odd byte count have on the 8390? | |
199 | * I should check someday. | |
200 | */ | |
201 | if (count & 0x01) | |
202 | count++; | |
203 | ||
204 | /* This *shouldn't* happen. | |
205 | * If it does, it's the last thing you'll see | |
206 | */ | |
207 | if (ei_status.dmaing) { | |
208 | netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n", | |
209 | __func__, ei_status.dmaing, ei_status.irqlock); | |
210 | return; | |
211 | } | |
212 | ei_status.dmaing |= 0x01; | |
213 | /* We should already be in page 0, but to be safe... */ | |
214 | z_writeb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD); | |
215 | ||
216 | z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); | |
217 | ||
218 | /* Now the normal output. */ | |
219 | z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO); | |
220 | z_writeb(count >> 8, nic_base + NE_EN0_RCNTHI); | |
221 | z_writeb(0x00, nic_base + NE_EN0_RSARLO); | |
222 | z_writeb(start_page, nic_base + NE_EN0_RSARHI); | |
223 | ||
224 | z_writeb(E8390_RWRITE + E8390_START, nic_base + NE_CMD); | |
225 | ptrs = (short *)buf; | |
226 | for (cnt = 0; cnt < count >> 1; cnt++) | |
227 | z_writew(*ptrs++, NE_BASE + NE_DATAPORT); | |
228 | ||
229 | dma_start = jiffies; | |
230 | ||
231 | while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0) | |
232 | if (time_after(jiffies, dma_start + 2 * HZ / 100)) { | |
233 | /* 20ms */ | |
234 | netdev_err(dev, "timeout waiting for Tx RDC\n"); | |
235 | zorro8390_reset_8390(dev); | |
236 | __NS8390_init(dev, 1); | |
237 | break; | |
238 | } | |
239 | ||
240 | z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr */ | |
241 | ei_status.dmaing &= ~0x01; | |
242 | } | |
1da177e4 | 243 | |
572404ea JP |
244 | static int zorro8390_open(struct net_device *dev) |
245 | { | |
246 | __ei_open(dev); | |
247 | return 0; | |
248 | } | |
1da177e4 | 249 | |
572404ea JP |
250 | static int zorro8390_close(struct net_device *dev) |
251 | { | |
252 | if (ei_debug > 1) | |
253 | netdev_dbg(dev, "Shutting down ethercard\n"); | |
254 | __ei_close(dev); | |
255 | return 0; | |
256 | } | |
1da177e4 | 257 | |
572404ea | 258 | static void __devexit zorro8390_remove_one(struct zorro_dev *z) |
1da177e4 | 259 | { |
572404ea JP |
260 | struct net_device *dev = zorro_get_drvdata(z); |
261 | ||
262 | unregister_netdev(dev); | |
263 | free_irq(IRQ_AMIGA_PORTS, dev); | |
264 | release_mem_region(ZTWO_PADDR(dev->base_addr), NE_IO_EXTENT * 2); | |
1da177e4 | 265 | free_netdev(dev); |
1da177e4 LT |
266 | } |
267 | ||
572404ea JP |
268 | static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = { |
269 | { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, }, | |
270 | { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, }, | |
271 | { 0 } | |
272 | }; | |
273 | MODULE_DEVICE_TABLE(zorro, zorro8390_zorro_tbl); | |
274 | ||
b6114794 SH |
275 | static const struct net_device_ops zorro8390_netdev_ops = { |
276 | .ndo_open = zorro8390_open, | |
277 | .ndo_stop = zorro8390_close, | |
cf7e032f GU |
278 | .ndo_start_xmit = __ei_start_xmit, |
279 | .ndo_tx_timeout = __ei_tx_timeout, | |
280 | .ndo_get_stats = __ei_get_stats, | |
281 | .ndo_set_multicast_list = __ei_set_multicast_list, | |
b6114794 | 282 | .ndo_validate_addr = eth_validate_addr, |
572404ea | 283 | .ndo_set_mac_address = eth_mac_addr, |
b6114794 SH |
284 | .ndo_change_mtu = eth_change_mtu, |
285 | #ifdef CONFIG_NET_POLL_CONTROLLER | |
cf7e032f | 286 | .ndo_poll_controller = __ei_poll, |
b6114794 SH |
287 | #endif |
288 | }; | |
289 | ||
1da177e4 LT |
290 | static int __devinit zorro8390_init(struct net_device *dev, |
291 | unsigned long board, const char *name, | |
292 | unsigned long ioaddr) | |
293 | { | |
572404ea JP |
294 | int i; |
295 | int err; | |
296 | unsigned char SA_prom[32]; | |
297 | int start_page, stop_page; | |
298 | static u32 zorro8390_offsets[16] = { | |
299 | 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, | |
300 | 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, | |
1da177e4 | 301 | }; |
1da177e4 | 302 | |
572404ea JP |
303 | /* Reset card. Who knows what dain-bramaged state it was left in. */ |
304 | { | |
305 | unsigned long reset_start_time = jiffies; | |
1da177e4 | 306 | |
572404ea | 307 | z_writeb(z_readb(ioaddr + NE_RESET), ioaddr + NE_RESET); |
1da177e4 | 308 | |
572404ea JP |
309 | while ((z_readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0) |
310 | if (time_after(jiffies, | |
311 | reset_start_time + 2 * HZ / 100)) { | |
312 | netdev_warn(dev, "not found (no reset ack)\n"); | |
313 | return -ENODEV; | |
314 | } | |
1da177e4 | 315 | |
572404ea JP |
316 | z_writeb(0xff, ioaddr + NE_EN0_ISR); /* Ack all intr. */ |
317 | } | |
1da177e4 | 318 | |
572404ea JP |
319 | /* Read the 16 bytes of station address PROM. |
320 | * We must first initialize registers, | |
321 | * similar to NS8390_init(eifdev, 0). | |
322 | * We can't reliably read the SAPROM address without this. | |
323 | * (I learned the hard way!). | |
324 | */ | |
325 | { | |
326 | static const struct { | |
327 | u32 value; | |
328 | u32 offset; | |
329 | } program_seq[] = { | |
330 | {E8390_NODMA + E8390_PAGE0 + E8390_STOP, NE_CMD}, | |
331 | /* Select page 0 */ | |
332 | {0x48, NE_EN0_DCFG}, /* 0x48: Set byte-wide access */ | |
333 | {0x00, NE_EN0_RCNTLO}, /* Clear the count regs */ | |
334 | {0x00, NE_EN0_RCNTHI}, | |
335 | {0x00, NE_EN0_IMR}, /* Mask completion irq */ | |
336 | {0xFF, NE_EN0_ISR}, | |
337 | {E8390_RXOFF, NE_EN0_RXCR}, /* 0x20 Set to monitor */ | |
338 | {E8390_TXOFF, NE_EN0_TXCR}, /* 0x02 and loopback mode */ | |
339 | {32, NE_EN0_RCNTLO}, | |
340 | {0x00, NE_EN0_RCNTHI}, | |
341 | {0x00, NE_EN0_RSARLO}, /* DMA starting at 0x0000 */ | |
342 | {0x00, NE_EN0_RSARHI}, | |
343 | {E8390_RREAD + E8390_START, NE_CMD}, | |
344 | }; | |
345 | for (i = 0; i < ARRAY_SIZE(program_seq); i++) | |
346 | z_writeb(program_seq[i].value, | |
347 | ioaddr + program_seq[i].offset); | |
348 | } | |
349 | for (i = 0; i < 16; i++) { | |
350 | SA_prom[i] = z_readb(ioaddr + NE_DATAPORT); | |
351 | (void)z_readb(ioaddr + NE_DATAPORT); | |
352 | } | |
1da177e4 | 353 | |
572404ea JP |
354 | /* We must set the 8390 for word mode. */ |
355 | z_writeb(0x49, ioaddr + NE_EN0_DCFG); | |
356 | start_page = NESM_START_PG; | |
357 | stop_page = NESM_STOP_PG; | |
1da177e4 | 358 | |
572404ea JP |
359 | dev->base_addr = ioaddr; |
360 | dev->irq = IRQ_AMIGA_PORTS; | |
1da177e4 | 361 | |
572404ea JP |
362 | /* Install the Interrupt handler */ |
363 | i = request_irq(IRQ_AMIGA_PORTS, __ei_interrupt, | |
364 | IRQF_SHARED, DRV_NAME, dev); | |
365 | if (i) | |
366 | return i; | |
1da177e4 | 367 | |
572404ea JP |
368 | for (i = 0; i < ETHER_ADDR_LEN; i++) |
369 | dev->dev_addr[i] = SA_prom[i]; | |
1da177e4 | 370 | |
572404ea | 371 | pr_debug("Found ethernet address: %pM\n", dev->dev_addr); |
1da177e4 | 372 | |
572404ea JP |
373 | ei_status.name = name; |
374 | ei_status.tx_start_page = start_page; | |
375 | ei_status.stop_page = stop_page; | |
376 | ei_status.word16 = 1; | |
1da177e4 | 377 | |
572404ea | 378 | ei_status.rx_start_page = start_page + TX_PAGES; |
1da177e4 | 379 | |
572404ea JP |
380 | ei_status.reset_8390 = zorro8390_reset_8390; |
381 | ei_status.block_input = zorro8390_block_input; | |
382 | ei_status.block_output = zorro8390_block_output; | |
383 | ei_status.get_8390_hdr = zorro8390_get_8390_hdr; | |
384 | ei_status.reg_offset = zorro8390_offsets; | |
1da177e4 | 385 | |
572404ea JP |
386 | dev->netdev_ops = &zorro8390_netdev_ops; |
387 | __NS8390_init(dev, 0); | |
388 | err = register_netdev(dev); | |
389 | if (err) { | |
390 | free_irq(IRQ_AMIGA_PORTS, dev); | |
391 | return err; | |
1da177e4 | 392 | } |
1da177e4 | 393 | |
572404ea JP |
394 | netdev_info(dev, "%s at 0x%08lx, Ethernet Address %pM\n", |
395 | name, board, dev->dev_addr); | |
1da177e4 | 396 | |
572404ea | 397 | return 0; |
1da177e4 LT |
398 | } |
399 | ||
572404ea JP |
400 | static int __devinit zorro8390_init_one(struct zorro_dev *z, |
401 | const struct zorro_device_id *ent) | |
1da177e4 | 402 | { |
572404ea JP |
403 | struct net_device *dev; |
404 | unsigned long board, ioaddr; | |
405 | int err, i; | |
406 | ||
407 | for (i = ARRAY_SIZE(cards) - 1; i >= 0; i--) | |
408 | if (z->id == cards[i].id) | |
409 | break; | |
410 | if (i < 0) | |
411 | return -ENODEV; | |
1da177e4 | 412 | |
572404ea JP |
413 | board = z->resource.start; |
414 | ioaddr = board + cards[i].offset; | |
415 | dev = ____alloc_ei_netdev(0); | |
416 | if (!dev) | |
417 | return -ENOMEM; | |
418 | if (!request_mem_region(ioaddr, NE_IO_EXTENT * 2, DRV_NAME)) { | |
419 | free_netdev(dev); | |
420 | return -EBUSY; | |
1da177e4 | 421 | } |
572404ea JP |
422 | err = zorro8390_init(dev, board, cards[i].name, ZTWO_VADDR(ioaddr)); |
423 | if (err) { | |
424 | release_mem_region(ioaddr, NE_IO_EXTENT * 2); | |
425 | free_netdev(dev); | |
426 | return err; | |
427 | } | |
428 | zorro_set_drvdata(z, dev); | |
429 | return 0; | |
1da177e4 LT |
430 | } |
431 | ||
572404ea JP |
432 | static struct zorro_driver zorro8390_driver = { |
433 | .name = "zorro8390", | |
434 | .id_table = zorro8390_zorro_tbl, | |
435 | .probe = zorro8390_init_one, | |
436 | .remove = __devexit_p(zorro8390_remove_one), | |
437 | }; | |
1da177e4 LT |
438 | |
439 | static int __init zorro8390_init_module(void) | |
440 | { | |
572404ea | 441 | return zorro_register_driver(&zorro8390_driver); |
1da177e4 LT |
442 | } |
443 | ||
444 | static void __exit zorro8390_cleanup_module(void) | |
445 | { | |
572404ea | 446 | zorro_unregister_driver(&zorro8390_driver); |
1da177e4 LT |
447 | } |
448 | ||
449 | module_init(zorro8390_init_module); | |
450 | module_exit(zorro8390_cleanup_module); | |
451 | ||
452 | MODULE_LICENSE("GPL"); |