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