diff options
author | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-04-02 09:20:12 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-08-10 22:54:25 -0400 |
commit | 644570b830266ff33ff5f3542b9c838f93a55ea6 (patch) | |
tree | b19c680ce1b1e4cd15465c74aa335459068c033f /drivers/net/ethernet/8390/apne.c | |
parent | b955f6ca776f3bab3d1e2c5fb1d247b203cbda14 (diff) |
8390: Move the 8390 related drivers
Moves the drivers for the National Semi-conductor 8390 chipset into
drivers/net/ethernet/8390/ and the necessary Kconfig and Makefile
changes.
CC: Donald Becker <becker@scyld.com>
CC: Paul Gortmaker <paul.gortmaker@windriver.com>
CC: Alain Malek <alain.malek@cryogen.com>
CC: Peter De Schrijver <p2@mind.be>
CC: "David Huggins-Daines" <dhd@debian.org>
CC: Wim Dumon <wimpie@kotnet.org>
CC: Yoshinori Sato <ysato@users.sourceforge.jp>
CC: David Hinds <dahinds@users.sourceforge.net>
CC: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/8390/apne.c')
-rw-r--r-- | drivers/net/ethernet/8390/apne.c | 620 |
1 files changed, 620 insertions, 0 deletions
diff --git a/drivers/net/ethernet/8390/apne.c b/drivers/net/ethernet/8390/apne.c new file mode 100644 index 000000000000..547737340cbb --- /dev/null +++ b/drivers/net/ethernet/8390/apne.c | |||
@@ -0,0 +1,620 @@ | |||
1 | /* | ||
2 | * Amiga Linux/68k 8390 based PCMCIA Ethernet Driver for the Amiga 1200 | ||
3 | * | ||
4 | * (C) Copyright 1997 Alain Malek | ||
5 | * (Alain.Malek@cryogen.com) | ||
6 | * | ||
7 | * ---------------------------------------------------------------------------- | ||
8 | * | ||
9 | * This program is based on | ||
10 | * | ||
11 | * ne.c: A general non-shared-memory NS8390 ethernet driver for linux | ||
12 | * Written 1992-94 by Donald Becker. | ||
13 | * | ||
14 | * 8390.c: A general NS8390 ethernet driver core for linux. | ||
15 | * Written 1992-94 by Donald Becker. | ||
16 | * | ||
17 | * cnetdevice: A Sana-II ethernet driver for AmigaOS | ||
18 | * Written by Bruce Abbott (bhabbott@inhb.co.nz) | ||
19 | * | ||
20 | * ---------------------------------------------------------------------------- | ||
21 | * | ||
22 | * This file is subject to the terms and conditions of the GNU General Public | ||
23 | * License. See the file COPYING in the main directory of the Linux | ||
24 | * distribution for more details. | ||
25 | * | ||
26 | * ---------------------------------------------------------------------------- | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | |||
31 | #include <linux/module.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/errno.h> | ||
34 | #include <linux/pci.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/delay.h> | ||
37 | #include <linux/netdevice.h> | ||
38 | #include <linux/etherdevice.h> | ||
39 | #include <linux/interrupt.h> | ||
40 | #include <linux/jiffies.h> | ||
41 | |||
42 | #include <asm/system.h> | ||
43 | #include <asm/io.h> | ||
44 | #include <asm/setup.h> | ||
45 | #include <asm/amigaints.h> | ||
46 | #include <asm/amigahw.h> | ||
47 | #include <asm/amigayle.h> | ||
48 | #include <asm/amipcmcia.h> | ||
49 | |||
50 | #include "8390.h" | ||
51 | |||
52 | /* ---- No user-serviceable parts below ---- */ | ||
53 | |||
54 | #define DRV_NAME "apne" | ||
55 | |||
56 | #define NE_BASE (dev->base_addr) | ||
57 | #define NE_CMD 0x00 | ||
58 | #define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */ | ||
59 | #define NE_RESET 0x1f /* Issue a read to reset, a write to clear. */ | ||
60 | #define NE_IO_EXTENT 0x20 | ||
61 | |||
62 | #define NE_EN0_ISR 0x07 | ||
63 | #define NE_EN0_DCFG 0x0e | ||
64 | |||
65 | #define NE_EN0_RSARLO 0x08 | ||
66 | #define NE_EN0_RSARHI 0x09 | ||
67 | #define NE_EN0_RCNTLO 0x0a | ||
68 | #define NE_EN0_RXCR 0x0c | ||
69 | #define NE_EN0_TXCR 0x0d | ||
70 | #define NE_EN0_RCNTHI 0x0b | ||
71 | #define NE_EN0_IMR 0x0f | ||
72 | |||
73 | #define NE1SM_START_PG 0x20 /* First page of TX buffer */ | ||
74 | #define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */ | ||
75 | #define NESM_START_PG 0x40 /* First page of TX buffer */ | ||
76 | #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ | ||
77 | |||
78 | |||
79 | struct net_device * __init apne_probe(int unit); | ||
80 | static int apne_probe1(struct net_device *dev, int ioaddr); | ||
81 | |||
82 | static void apne_reset_8390(struct net_device *dev); | ||
83 | static void apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, | ||
84 | int ring_page); | ||
85 | static void apne_block_input(struct net_device *dev, int count, | ||
86 | struct sk_buff *skb, int ring_offset); | ||
87 | static void apne_block_output(struct net_device *dev, const int count, | ||
88 | const unsigned char *buf, const int start_page); | ||
89 | static irqreturn_t apne_interrupt(int irq, void *dev_id); | ||
90 | |||
91 | static int init_pcmcia(void); | ||
92 | |||
93 | /* IO base address used for nic */ | ||
94 | |||
95 | #define IOBASE 0x300 | ||
96 | |||
97 | /* | ||
98 | use MANUAL_CONFIG and MANUAL_OFFSET for enabling IO by hand | ||
99 | you can find the values to use by looking at the cnet.device | ||
100 | config file example (the default values are for the CNET40BC card) | ||
101 | */ | ||
102 | |||
103 | /* | ||
104 | #define MANUAL_CONFIG 0x20 | ||
105 | #define MANUAL_OFFSET 0x3f8 | ||
106 | |||
107 | #define MANUAL_HWADDR0 0x00 | ||
108 | #define MANUAL_HWADDR1 0x12 | ||
109 | #define MANUAL_HWADDR2 0x34 | ||
110 | #define MANUAL_HWADDR3 0x56 | ||
111 | #define MANUAL_HWADDR4 0x78 | ||
112 | #define MANUAL_HWADDR5 0x9a | ||
113 | */ | ||
114 | |||
115 | static const char version[] = | ||
116 | "apne.c:v1.1 7/10/98 Alain Malek (Alain.Malek@cryogen.ch)\n"; | ||
117 | |||
118 | static int apne_owned; /* signal if card already owned */ | ||
119 | |||
120 | struct net_device * __init apne_probe(int unit) | ||
121 | { | ||
122 | struct net_device *dev; | ||
123 | #ifndef MANUAL_CONFIG | ||
124 | char tuple[8]; | ||
125 | #endif | ||
126 | int err; | ||
127 | |||
128 | if (!MACH_IS_AMIGA) | ||
129 | return ERR_PTR(-ENODEV); | ||
130 | |||
131 | if (apne_owned) | ||
132 | return ERR_PTR(-ENODEV); | ||
133 | |||
134 | if ( !(AMIGAHW_PRESENT(PCMCIA)) ) | ||
135 | return ERR_PTR(-ENODEV); | ||
136 | |||
137 | printk("Looking for PCMCIA ethernet card : "); | ||
138 | |||
139 | /* check if a card is inserted */ | ||
140 | if (!(PCMCIA_INSERTED)) { | ||
141 | printk("NO PCMCIA card inserted\n"); | ||
142 | return ERR_PTR(-ENODEV); | ||
143 | } | ||
144 | |||
145 | dev = alloc_ei_netdev(); | ||
146 | if (!dev) | ||
147 | return ERR_PTR(-ENOMEM); | ||
148 | if (unit >= 0) { | ||
149 | sprintf(dev->name, "eth%d", unit); | ||
150 | netdev_boot_setup_check(dev); | ||
151 | } | ||
152 | |||
153 | /* disable pcmcia irq for readtuple */ | ||
154 | pcmcia_disable_irq(); | ||
155 | |||
156 | #ifndef MANUAL_CONFIG | ||
157 | if ((pcmcia_copy_tuple(CISTPL_FUNCID, tuple, 8) < 3) || | ||
158 | (tuple[2] != CISTPL_FUNCID_NETWORK)) { | ||
159 | printk("not an ethernet card\n"); | ||
160 | /* XXX: shouldn't we re-enable irq here? */ | ||
161 | free_netdev(dev); | ||
162 | return ERR_PTR(-ENODEV); | ||
163 | } | ||
164 | #endif | ||
165 | |||
166 | printk("ethernet PCMCIA card inserted\n"); | ||
167 | |||
168 | if (!init_pcmcia()) { | ||
169 | /* XXX: shouldn't we re-enable irq here? */ | ||
170 | free_netdev(dev); | ||
171 | return ERR_PTR(-ENODEV); | ||
172 | } | ||
173 | |||
174 | if (!request_region(IOBASE, 0x20, DRV_NAME)) { | ||
175 | free_netdev(dev); | ||
176 | return ERR_PTR(-EBUSY); | ||
177 | } | ||
178 | |||
179 | err = apne_probe1(dev, IOBASE); | ||
180 | if (err) { | ||
181 | release_region(IOBASE, 0x20); | ||
182 | free_netdev(dev); | ||
183 | return ERR_PTR(err); | ||
184 | } | ||
185 | err = register_netdev(dev); | ||
186 | if (!err) | ||
187 | return dev; | ||
188 | |||
189 | pcmcia_disable_irq(); | ||
190 | free_irq(IRQ_AMIGA_PORTS, dev); | ||
191 | pcmcia_reset(); | ||
192 | release_region(IOBASE, 0x20); | ||
193 | free_netdev(dev); | ||
194 | return ERR_PTR(err); | ||
195 | } | ||
196 | |||
197 | static int __init apne_probe1(struct net_device *dev, int ioaddr) | ||
198 | { | ||
199 | int i; | ||
200 | unsigned char SA_prom[32]; | ||
201 | int wordlength = 2; | ||
202 | const char *name = NULL; | ||
203 | int start_page, stop_page; | ||
204 | #ifndef MANUAL_HWADDR0 | ||
205 | int neX000, ctron; | ||
206 | #endif | ||
207 | static unsigned version_printed; | ||
208 | |||
209 | if (ei_debug && version_printed++ == 0) | ||
210 | printk(version); | ||
211 | |||
212 | printk("PCMCIA NE*000 ethercard probe"); | ||
213 | |||
214 | /* Reset card. Who knows what dain-bramaged state it was left in. */ | ||
215 | { unsigned long reset_start_time = jiffies; | ||
216 | |||
217 | outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET); | ||
218 | |||
219 | while ((inb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0) | ||
220 | if (time_after(jiffies, reset_start_time + 2*HZ/100)) { | ||
221 | printk(" not found (no reset ack).\n"); | ||
222 | return -ENODEV; | ||
223 | } | ||
224 | |||
225 | outb(0xff, ioaddr + NE_EN0_ISR); /* Ack all intr. */ | ||
226 | } | ||
227 | |||
228 | #ifndef MANUAL_HWADDR0 | ||
229 | |||
230 | /* Read the 16 bytes of station address PROM. | ||
231 | We must first initialize registers, similar to NS8390_init(eifdev, 0). | ||
232 | We can't reliably read the SAPROM address without this. | ||
233 | (I learned the hard way!). */ | ||
234 | { | ||
235 | struct {unsigned long value, offset; } program_seq[] = { | ||
236 | {E8390_NODMA+E8390_PAGE0+E8390_STOP, NE_CMD}, /* Select page 0*/ | ||
237 | {0x48, NE_EN0_DCFG}, /* Set byte-wide (0x48) access. */ | ||
238 | {0x00, NE_EN0_RCNTLO}, /* Clear the count regs. */ | ||
239 | {0x00, NE_EN0_RCNTHI}, | ||
240 | {0x00, NE_EN0_IMR}, /* Mask completion irq. */ | ||
241 | {0xFF, NE_EN0_ISR}, | ||
242 | {E8390_RXOFF, NE_EN0_RXCR}, /* 0x20 Set to monitor */ | ||
243 | {E8390_TXOFF, NE_EN0_TXCR}, /* 0x02 and loopback mode. */ | ||
244 | {32, NE_EN0_RCNTLO}, | ||
245 | {0x00, NE_EN0_RCNTHI}, | ||
246 | {0x00, NE_EN0_RSARLO}, /* DMA starting at 0x0000. */ | ||
247 | {0x00, NE_EN0_RSARHI}, | ||
248 | {E8390_RREAD+E8390_START, NE_CMD}, | ||
249 | }; | ||
250 | for (i = 0; i < ARRAY_SIZE(program_seq); i++) { | ||
251 | outb(program_seq[i].value, ioaddr + program_seq[i].offset); | ||
252 | } | ||
253 | |||
254 | } | ||
255 | for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) { | ||
256 | SA_prom[i] = inb(ioaddr + NE_DATAPORT); | ||
257 | SA_prom[i+1] = inb(ioaddr + NE_DATAPORT); | ||
258 | if (SA_prom[i] != SA_prom[i+1]) | ||
259 | wordlength = 1; | ||
260 | } | ||
261 | |||
262 | /* At this point, wordlength *only* tells us if the SA_prom is doubled | ||
263 | up or not because some broken PCI cards don't respect the byte-wide | ||
264 | request in program_seq above, and hence don't have doubled up values. | ||
265 | These broken cards would otherwise be detected as an ne1000. */ | ||
266 | |||
267 | if (wordlength == 2) | ||
268 | for (i = 0; i < 16; i++) | ||
269 | SA_prom[i] = SA_prom[i+i]; | ||
270 | |||
271 | if (wordlength == 2) { | ||
272 | /* We must set the 8390 for word mode. */ | ||
273 | outb(0x49, ioaddr + NE_EN0_DCFG); | ||
274 | start_page = NESM_START_PG; | ||
275 | stop_page = NESM_STOP_PG; | ||
276 | } else { | ||
277 | start_page = NE1SM_START_PG; | ||
278 | stop_page = NE1SM_STOP_PG; | ||
279 | } | ||
280 | |||
281 | neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57); | ||
282 | ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d); | ||
283 | |||
284 | /* Set up the rest of the parameters. */ | ||
285 | if (neX000) { | ||
286 | name = (wordlength == 2) ? "NE2000" : "NE1000"; | ||
287 | } else if (ctron) { | ||
288 | name = (wordlength == 2) ? "Ctron-8" : "Ctron-16"; | ||
289 | start_page = 0x01; | ||
290 | stop_page = (wordlength == 2) ? 0x40 : 0x20; | ||
291 | } else { | ||
292 | printk(" not found.\n"); | ||
293 | return -ENXIO; | ||
294 | |||
295 | } | ||
296 | |||
297 | #else | ||
298 | wordlength = 2; | ||
299 | /* We must set the 8390 for word mode. */ | ||
300 | outb(0x49, ioaddr + NE_EN0_DCFG); | ||
301 | start_page = NESM_START_PG; | ||
302 | stop_page = NESM_STOP_PG; | ||
303 | |||
304 | SA_prom[0] = MANUAL_HWADDR0; | ||
305 | SA_prom[1] = MANUAL_HWADDR1; | ||
306 | SA_prom[2] = MANUAL_HWADDR2; | ||
307 | SA_prom[3] = MANUAL_HWADDR3; | ||
308 | SA_prom[4] = MANUAL_HWADDR4; | ||
309 | SA_prom[5] = MANUAL_HWADDR5; | ||
310 | name = "NE2000"; | ||
311 | #endif | ||
312 | |||
313 | dev->base_addr = ioaddr; | ||
314 | dev->irq = IRQ_AMIGA_PORTS; | ||
315 | dev->netdev_ops = &ei_netdev_ops; | ||
316 | |||
317 | /* Install the Interrupt handler */ | ||
318 | i = request_irq(dev->irq, apne_interrupt, IRQF_SHARED, DRV_NAME, dev); | ||
319 | if (i) return i; | ||
320 | |||
321 | for(i = 0; i < ETHER_ADDR_LEN; i++) | ||
322 | dev->dev_addr[i] = SA_prom[i]; | ||
323 | |||
324 | printk(" %pM\n", dev->dev_addr); | ||
325 | |||
326 | printk("%s: %s found.\n", dev->name, name); | ||
327 | |||
328 | ei_status.name = name; | ||
329 | ei_status.tx_start_page = start_page; | ||
330 | ei_status.stop_page = stop_page; | ||
331 | ei_status.word16 = (wordlength == 2); | ||
332 | |||
333 | ei_status.rx_start_page = start_page + TX_PAGES; | ||
334 | |||
335 | ei_status.reset_8390 = &apne_reset_8390; | ||
336 | ei_status.block_input = &apne_block_input; | ||
337 | ei_status.block_output = &apne_block_output; | ||
338 | ei_status.get_8390_hdr = &apne_get_8390_hdr; | ||
339 | |||
340 | NS8390_init(dev, 0); | ||
341 | |||
342 | pcmcia_ack_int(pcmcia_get_intreq()); /* ack PCMCIA int req */ | ||
343 | pcmcia_enable_irq(); | ||
344 | |||
345 | apne_owned = 1; | ||
346 | |||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | /* Hard reset the card. This used to pause for the same period that a | ||
351 | 8390 reset command required, but that shouldn't be necessary. */ | ||
352 | static void | ||
353 | apne_reset_8390(struct net_device *dev) | ||
354 | { | ||
355 | unsigned long reset_start_time = jiffies; | ||
356 | |||
357 | init_pcmcia(); | ||
358 | |||
359 | if (ei_debug > 1) printk("resetting the 8390 t=%ld...", jiffies); | ||
360 | |||
361 | outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET); | ||
362 | |||
363 | ei_status.txing = 0; | ||
364 | ei_status.dmaing = 0; | ||
365 | |||
366 | /* This check _should_not_ be necessary, omit eventually. */ | ||
367 | while ((inb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0) | ||
368 | if (time_after(jiffies, reset_start_time + 2*HZ/100)) { | ||
369 | printk("%s: ne_reset_8390() did not complete.\n", dev->name); | ||
370 | break; | ||
371 | } | ||
372 | outb(ENISR_RESET, NE_BASE + NE_EN0_ISR); /* Ack intr. */ | ||
373 | } | ||
374 | |||
375 | /* Grab the 8390 specific header. Similar to the block_input routine, but | ||
376 | we don't need to be concerned with ring wrap as the header will be at | ||
377 | the start of a page, so we optimize accordingly. */ | ||
378 | |||
379 | static void | ||
380 | apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) | ||
381 | { | ||
382 | |||
383 | int nic_base = dev->base_addr; | ||
384 | int cnt; | ||
385 | char *ptrc; | ||
386 | short *ptrs; | ||
387 | |||
388 | /* This *shouldn't* happen. If it does, it's the last thing you'll see */ | ||
389 | if (ei_status.dmaing) { | ||
390 | printk("%s: DMAing conflict in ne_get_8390_hdr " | ||
391 | "[DMAstat:%d][irqlock:%d][intr:%d].\n", | ||
392 | dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq); | ||
393 | return; | ||
394 | } | ||
395 | |||
396 | ei_status.dmaing |= 0x01; | ||
397 | outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); | ||
398 | outb(ENISR_RDC, nic_base + NE_EN0_ISR); | ||
399 | outb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO); | ||
400 | outb(0, nic_base + NE_EN0_RCNTHI); | ||
401 | outb(0, nic_base + NE_EN0_RSARLO); /* On page boundary */ | ||
402 | outb(ring_page, nic_base + NE_EN0_RSARHI); | ||
403 | outb(E8390_RREAD+E8390_START, nic_base + NE_CMD); | ||
404 | |||
405 | if (ei_status.word16) { | ||
406 | ptrs = (short*)hdr; | ||
407 | for(cnt = 0; cnt < (sizeof(struct e8390_pkt_hdr)>>1); cnt++) | ||
408 | *ptrs++ = inw(NE_BASE + NE_DATAPORT); | ||
409 | } else { | ||
410 | ptrc = (char*)hdr; | ||
411 | for(cnt = 0; cnt < sizeof(struct e8390_pkt_hdr); cnt++) | ||
412 | *ptrc++ = inb(NE_BASE + NE_DATAPORT); | ||
413 | } | ||
414 | |||
415 | outb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr. */ | ||
416 | ei_status.dmaing &= ~0x01; | ||
417 | |||
418 | le16_to_cpus(&hdr->count); | ||
419 | } | ||
420 | |||
421 | /* Block input and output, similar to the Crynwr packet driver. If you | ||
422 | are porting to a new ethercard, look at the packet driver source for hints. | ||
423 | The NEx000 doesn't share the on-board packet memory -- you have to put | ||
424 | the packet out through the "remote DMA" dataport using outb. */ | ||
425 | |||
426 | static void | ||
427 | apne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) | ||
428 | { | ||
429 | int nic_base = dev->base_addr; | ||
430 | char *buf = skb->data; | ||
431 | char *ptrc; | ||
432 | short *ptrs; | ||
433 | int cnt; | ||
434 | |||
435 | /* This *shouldn't* happen. If it does, it's the last thing you'll see */ | ||
436 | if (ei_status.dmaing) { | ||
437 | printk("%s: DMAing conflict in ne_block_input " | ||
438 | "[DMAstat:%d][irqlock:%d][intr:%d].\n", | ||
439 | dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq); | ||
440 | return; | ||
441 | } | ||
442 | ei_status.dmaing |= 0x01; | ||
443 | outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); | ||
444 | outb(ENISR_RDC, nic_base + NE_EN0_ISR); | ||
445 | outb(count & 0xff, nic_base + NE_EN0_RCNTLO); | ||
446 | outb(count >> 8, nic_base + NE_EN0_RCNTHI); | ||
447 | outb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO); | ||
448 | outb(ring_offset >> 8, nic_base + NE_EN0_RSARHI); | ||
449 | outb(E8390_RREAD+E8390_START, nic_base + NE_CMD); | ||
450 | if (ei_status.word16) { | ||
451 | ptrs = (short*)buf; | ||
452 | for (cnt = 0; cnt < (count>>1); cnt++) | ||
453 | *ptrs++ = inw(NE_BASE + NE_DATAPORT); | ||
454 | if (count & 0x01) { | ||
455 | buf[count-1] = inb(NE_BASE + NE_DATAPORT); | ||
456 | } | ||
457 | } else { | ||
458 | ptrc = (char*)buf; | ||
459 | for (cnt = 0; cnt < count; cnt++) | ||
460 | *ptrc++ = inb(NE_BASE + NE_DATAPORT); | ||
461 | } | ||
462 | |||
463 | outb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr. */ | ||
464 | ei_status.dmaing &= ~0x01; | ||
465 | } | ||
466 | |||
467 | static void | ||
468 | apne_block_output(struct net_device *dev, int count, | ||
469 | const unsigned char *buf, const int start_page) | ||
470 | { | ||
471 | int nic_base = NE_BASE; | ||
472 | unsigned long dma_start; | ||
473 | char *ptrc; | ||
474 | short *ptrs; | ||
475 | int cnt; | ||
476 | |||
477 | /* Round the count up for word writes. Do we need to do this? | ||
478 | What effect will an odd byte count have on the 8390? | ||
479 | I should check someday. */ | ||
480 | if (ei_status.word16 && (count & 0x01)) | ||
481 | count++; | ||
482 | |||
483 | /* This *shouldn't* happen. If it does, it's the last thing you'll see */ | ||
484 | if (ei_status.dmaing) { | ||
485 | printk("%s: DMAing conflict in ne_block_output." | ||
486 | "[DMAstat:%d][irqlock:%d][intr:%d]\n", | ||
487 | dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq); | ||
488 | return; | ||
489 | } | ||
490 | ei_status.dmaing |= 0x01; | ||
491 | /* We should already be in page 0, but to be safe... */ | ||
492 | outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD); | ||
493 | |||
494 | outb(ENISR_RDC, nic_base + NE_EN0_ISR); | ||
495 | |||
496 | /* Now the normal output. */ | ||
497 | outb(count & 0xff, nic_base + NE_EN0_RCNTLO); | ||
498 | outb(count >> 8, nic_base + NE_EN0_RCNTHI); | ||
499 | outb(0x00, nic_base + NE_EN0_RSARLO); | ||
500 | outb(start_page, nic_base + NE_EN0_RSARHI); | ||
501 | |||
502 | outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD); | ||
503 | if (ei_status.word16) { | ||
504 | ptrs = (short*)buf; | ||
505 | for (cnt = 0; cnt < count>>1; cnt++) | ||
506 | outw(*ptrs++, NE_BASE+NE_DATAPORT); | ||
507 | } else { | ||
508 | ptrc = (char*)buf; | ||
509 | for (cnt = 0; cnt < count; cnt++) | ||
510 | outb(*ptrc++, NE_BASE + NE_DATAPORT); | ||
511 | } | ||
512 | |||
513 | dma_start = jiffies; | ||
514 | |||
515 | while ((inb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0) | ||
516 | if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */ | ||
517 | printk("%s: timeout waiting for Tx RDC.\n", dev->name); | ||
518 | apne_reset_8390(dev); | ||
519 | NS8390_init(dev,1); | ||
520 | break; | ||
521 | } | ||
522 | |||
523 | outb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr. */ | ||
524 | ei_status.dmaing &= ~0x01; | ||
525 | } | ||
526 | |||
527 | static irqreturn_t apne_interrupt(int irq, void *dev_id) | ||
528 | { | ||
529 | unsigned char pcmcia_intreq; | ||
530 | |||
531 | if (!(gayle.inten & GAYLE_IRQ_IRQ)) | ||
532 | return IRQ_NONE; | ||
533 | |||
534 | pcmcia_intreq = pcmcia_get_intreq(); | ||
535 | |||
536 | if (!(pcmcia_intreq & GAYLE_IRQ_IRQ)) { | ||
537 | pcmcia_ack_int(pcmcia_intreq); | ||
538 | return IRQ_NONE; | ||
539 | } | ||
540 | if (ei_debug > 3) | ||
541 | printk("pcmcia intreq = %x\n", pcmcia_intreq); | ||
542 | pcmcia_disable_irq(); /* to get rid of the sti() within ei_interrupt */ | ||
543 | ei_interrupt(irq, dev_id); | ||
544 | pcmcia_ack_int(pcmcia_get_intreq()); | ||
545 | pcmcia_enable_irq(); | ||
546 | return IRQ_HANDLED; | ||
547 | } | ||
548 | |||
549 | #ifdef MODULE | ||
550 | static struct net_device *apne_dev; | ||
551 | |||
552 | static int __init apne_module_init(void) | ||
553 | { | ||
554 | apne_dev = apne_probe(-1); | ||
555 | if (IS_ERR(apne_dev)) | ||
556 | return PTR_ERR(apne_dev); | ||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | static void __exit apne_module_exit(void) | ||
561 | { | ||
562 | unregister_netdev(apne_dev); | ||
563 | |||
564 | pcmcia_disable_irq(); | ||
565 | |||
566 | free_irq(IRQ_AMIGA_PORTS, apne_dev); | ||
567 | |||
568 | pcmcia_reset(); | ||
569 | |||
570 | release_region(IOBASE, 0x20); | ||
571 | |||
572 | free_netdev(apne_dev); | ||
573 | } | ||
574 | module_init(apne_module_init); | ||
575 | module_exit(apne_module_exit); | ||
576 | #endif | ||
577 | |||
578 | static int init_pcmcia(void) | ||
579 | { | ||
580 | u_char config; | ||
581 | #ifndef MANUAL_CONFIG | ||
582 | u_char tuple[32]; | ||
583 | int offset_len; | ||
584 | #endif | ||
585 | u_long offset; | ||
586 | |||
587 | pcmcia_reset(); | ||
588 | pcmcia_program_voltage(PCMCIA_0V); | ||
589 | pcmcia_access_speed(PCMCIA_SPEED_250NS); | ||
590 | pcmcia_write_enable(); | ||
591 | |||
592 | #ifdef MANUAL_CONFIG | ||
593 | config = MANUAL_CONFIG; | ||
594 | #else | ||
595 | /* get and write config byte to enable IO port */ | ||
596 | |||
597 | if (pcmcia_copy_tuple(CISTPL_CFTABLE_ENTRY, tuple, 32) < 3) | ||
598 | return 0; | ||
599 | |||
600 | config = tuple[2] & 0x3f; | ||
601 | #endif | ||
602 | #ifdef MANUAL_OFFSET | ||
603 | offset = MANUAL_OFFSET; | ||
604 | #else | ||
605 | if (pcmcia_copy_tuple(CISTPL_CONFIG, tuple, 32) < 6) | ||
606 | return 0; | ||
607 | |||
608 | offset_len = (tuple[2] & 0x3) + 1; | ||
609 | offset = 0; | ||
610 | while(offset_len--) { | ||
611 | offset = (offset << 8) | tuple[4+offset_len]; | ||
612 | } | ||
613 | #endif | ||
614 | |||
615 | out_8(GAYLE_ATTRIBUTE+offset, config); | ||
616 | |||
617 | return 1; | ||
618 | } | ||
619 | |||
620 | MODULE_LICENSE("GPL"); | ||