• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/net/tokenring/
1/*
2 *  proteon.c: A network driver for Proteon ISA token ring cards.
3 *
4 *  Based on tmspci written 1999 by Adam Fritzler
5 *
6 *  Written 2003 by Jochen Friedrich
7 *
8 *  This software may be used and distributed according to the terms
9 *  of the GNU General Public License, incorporated herein by reference.
10 *
11 *  This driver module supports the following cards:
12 *	- Proteon 1392, 1392+
13 *
14 *  Maintainer(s):
15 *    AF        Adam Fritzler
16 *    JF	Jochen Friedrich	jochen@scram.de
17 *
18 *  Modification History:
19 *	02-Jan-03	JF	Created
20 *
21 */
22static const char version[] = "proteon.c: v1.00 02/01/2003 by Jochen Friedrich\n";
23
24#include <linux/module.h>
25#include <linux/kernel.h>
26#include <linux/delay.h>
27#include <linux/errno.h>
28#include <linux/pci.h>
29#include <linux/init.h>
30#include <linux/netdevice.h>
31#include <linux/trdevice.h>
32#include <linux/platform_device.h>
33
34#include <asm/system.h>
35#include <asm/io.h>
36#include <asm/irq.h>
37#include <asm/pci.h>
38#include <asm/dma.h>
39
40#include "tms380tr.h"
41
42#define PROTEON_IO_EXTENT 32
43
44/* A zero-terminated list of I/O addresses to be probed. */
45static unsigned int portlist[] __initdata = {
46	0x0A20, 0x0E20, 0x1A20, 0x1E20, 0x2A20, 0x2E20, 0x3A20, 0x3E20,// Prot.
47	0x4A20, 0x4E20, 0x5A20, 0x5E20, 0x6A20, 0x6E20, 0x7A20, 0x7E20,// Prot.
48	0x8A20, 0x8E20, 0x9A20, 0x9E20, 0xAA20, 0xAE20, 0xBA20, 0xBE20,// Prot.
49	0xCA20, 0xCE20, 0xDA20, 0xDE20, 0xEA20, 0xEE20, 0xFA20, 0xFE20,// Prot.
50	0
51};
52
53/* A zero-terminated list of IRQs to be probed. */
54static unsigned short irqlist[] = {
55	7, 6, 5, 4, 3, 12, 11, 10, 9,
56	0
57};
58
59/* A zero-terminated list of DMAs to be probed. */
60static int dmalist[] __initdata = {
61	5, 6, 7,
62	0
63};
64
65static char cardname[] = "Proteon 1392\0";
66static u64 dma_mask = ISA_MAX_ADDRESS;
67static int proteon_open(struct net_device *dev);
68static void proteon_read_eeprom(struct net_device *dev);
69static unsigned short proteon_setnselout_pins(struct net_device *dev);
70
71static unsigned short proteon_sifreadb(struct net_device *dev, unsigned short reg)
72{
73	return inb(dev->base_addr + reg);
74}
75
76static unsigned short proteon_sifreadw(struct net_device *dev, unsigned short reg)
77{
78	return inw(dev->base_addr + reg);
79}
80
81static void proteon_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg)
82{
83	outb(val, dev->base_addr + reg);
84}
85
86static void proteon_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg)
87{
88	outw(val, dev->base_addr + reg);
89}
90
91static int __init proteon_probe1(struct net_device *dev, int ioaddr)
92{
93	unsigned char chk1, chk2;
94	int i;
95
96	if (!request_region(ioaddr, PROTEON_IO_EXTENT, cardname))
97		return -ENODEV;
98
99
100	chk1 = inb(ioaddr + 0x1f);      /* Get Proteon ID reg 1 */
101	if (chk1 != 0x1f)
102		goto nodev;
103
104	chk1 = inb(ioaddr + 0x1e) & 0x07;       /* Get Proteon ID reg 0 */
105	for (i=0; i<16; i++) {
106		chk2 = inb(ioaddr + 0x1e) & 0x07;
107		if (((chk1 + 1) & 0x07) != chk2)
108			goto nodev;
109		chk1 = chk2;
110	}
111
112	dev->base_addr = ioaddr;
113	return (0);
114nodev:
115	release_region(ioaddr, PROTEON_IO_EXTENT);
116	return -ENODEV;
117}
118
119static struct net_device_ops proteon_netdev_ops __read_mostly;
120
121static int __init setup_card(struct net_device *dev, struct device *pdev)
122{
123	struct net_local *tp;
124        static int versionprinted;
125	const unsigned *port;
126	int j,err = 0;
127
128	if (!dev)
129		return -ENOMEM;
130
131	if (dev->base_addr)	/* probe specific location */
132		err = proteon_probe1(dev, dev->base_addr);
133	else {
134		for (port = portlist; *port; port++) {
135			err = proteon_probe1(dev, *port);
136			if (!err)
137				break;
138		}
139	}
140	if (err)
141		goto out5;
142
143	/* At this point we have found a valid card. */
144
145	if (versionprinted++ == 0)
146		printk(KERN_DEBUG "%s", version);
147
148	err = -EIO;
149	pdev->dma_mask = &dma_mask;
150	if (tmsdev_init(dev, pdev))
151		goto out4;
152
153	dev->base_addr &= ~3;
154
155	proteon_read_eeprom(dev);
156
157	printk(KERN_DEBUG "proteon.c:    Ring Station Address: %pM\n",
158	       dev->dev_addr);
159
160	tp = netdev_priv(dev);
161	tp->setnselout = proteon_setnselout_pins;
162
163	tp->sifreadb = proteon_sifreadb;
164	tp->sifreadw = proteon_sifreadw;
165	tp->sifwriteb = proteon_sifwriteb;
166	tp->sifwritew = proteon_sifwritew;
167
168	memcpy(tp->ProductID, cardname, PROD_ID_SIZE + 1);
169
170	tp->tmspriv = NULL;
171
172	dev->netdev_ops = &proteon_netdev_ops;
173
174	if (dev->irq == 0)
175	{
176		for(j = 0; irqlist[j] != 0; j++)
177		{
178			dev->irq = irqlist[j];
179			if (!request_irq(dev->irq, tms380tr_interrupt, 0,
180				cardname, dev))
181				break;
182                }
183
184                if(irqlist[j] == 0)
185                {
186                        printk(KERN_INFO "proteon.c: AutoSelect no IRQ available\n");
187			goto out3;
188		}
189	}
190	else
191	{
192		for(j = 0; irqlist[j] != 0; j++)
193			if (irqlist[j] == dev->irq)
194				break;
195		if (irqlist[j] == 0)
196		{
197			printk(KERN_INFO "proteon.c: Illegal IRQ %d specified\n",
198				dev->irq);
199			goto out3;
200		}
201		if (request_irq(dev->irq, tms380tr_interrupt, 0,
202			cardname, dev))
203		{
204                        printk(KERN_INFO "proteon.c: Selected IRQ %d not available\n",
205				dev->irq);
206			goto out3;
207		}
208	}
209
210	if (dev->dma == 0)
211	{
212		for(j = 0; dmalist[j] != 0; j++)
213		{
214			dev->dma = dmalist[j];
215                        if (!request_dma(dev->dma, cardname))
216				break;
217		}
218
219		if(dmalist[j] == 0)
220		{
221			printk(KERN_INFO "proteon.c: AutoSelect no DMA available\n");
222			goto out2;
223		}
224	}
225	else
226	{
227		for(j = 0; dmalist[j] != 0; j++)
228			if (dmalist[j] == dev->dma)
229				break;
230		if (dmalist[j] == 0)
231		{
232                        printk(KERN_INFO "proteon.c: Illegal DMA %d specified\n",
233				dev->dma);
234			goto out2;
235		}
236		if (request_dma(dev->dma, cardname))
237		{
238                        printk(KERN_INFO "proteon.c: Selected DMA %d not available\n",
239				dev->dma);
240			goto out2;
241		}
242	}
243
244	err = register_netdev(dev);
245	if (err)
246		goto out;
247
248	printk(KERN_DEBUG "%s:    IO: %#4lx  IRQ: %d  DMA: %d\n",
249	       dev->name, dev->base_addr, dev->irq, dev->dma);
250
251	return 0;
252out:
253	free_dma(dev->dma);
254out2:
255	free_irq(dev->irq, dev);
256out3:
257	tmsdev_term(dev);
258out4:
259	release_region(dev->base_addr, PROTEON_IO_EXTENT);
260out5:
261	return err;
262}
263
264/*
265 * Reads MAC address from adapter RAM, which should've read it from
266 * the onboard ROM.
267 *
268 * Calling this on a board that does not support it can be a very
269 * dangerous thing.  The Madge board, for instance, will lock your
270 * machine hard when this is called.  Luckily, its supported in a
271 * separate driver.  --ASF
272 */
273static void proteon_read_eeprom(struct net_device *dev)
274{
275	int i;
276
277	/* Address: 0000:0000 */
278	proteon_sifwritew(dev, 0, SIFADX);
279	proteon_sifwritew(dev, 0, SIFADR);
280
281	/* Read six byte MAC address data */
282	dev->addr_len = 6;
283	for(i = 0; i < 6; i++)
284		dev->dev_addr[i] = proteon_sifreadw(dev, SIFINC) >> 8;
285}
286
287static unsigned short proteon_setnselout_pins(struct net_device *dev)
288{
289	return 0;
290}
291
292static int proteon_open(struct net_device *dev)
293{
294	struct net_local *tp = netdev_priv(dev);
295	unsigned short val = 0;
296	int i;
297
298	/* Proteon reset sequence */
299	outb(0, dev->base_addr + 0x11);
300	mdelay(20);
301	outb(0x04, dev->base_addr + 0x11);
302	mdelay(20);
303	outb(0, dev->base_addr + 0x11);
304	mdelay(100);
305
306	/* set control/status reg */
307	val = inb(dev->base_addr + 0x11);
308	val |= 0x78;
309	val &= 0xf9;
310	if(tp->DataRate == SPEED_4)
311		val |= 0x20;
312	else
313		val &= ~0x20;
314
315	outb(val, dev->base_addr + 0x11);
316	outb(0xff, dev->base_addr + 0x12);
317	for(i = 0; irqlist[i] != 0; i++)
318	{
319		if(irqlist[i] == dev->irq)
320			break;
321	}
322	val = i;
323	i = (7 - dev->dma) << 4;
324	val |= i;
325	outb(val, dev->base_addr + 0x13);
326
327	return tms380tr_open(dev);
328}
329
330#define ISATR_MAX_ADAPTERS 3
331
332static int io[ISATR_MAX_ADAPTERS];
333static int irq[ISATR_MAX_ADAPTERS];
334static int dma[ISATR_MAX_ADAPTERS];
335
336MODULE_LICENSE("GPL");
337
338module_param_array(io, int, NULL, 0);
339module_param_array(irq, int, NULL, 0);
340module_param_array(dma, int, NULL, 0);
341
342static struct platform_device *proteon_dev[ISATR_MAX_ADAPTERS];
343
344static struct platform_driver proteon_driver = {
345	.driver		= {
346		.name	= "proteon",
347	},
348};
349
350static int __init proteon_init(void)
351{
352	struct net_device *dev;
353	struct platform_device *pdev;
354	int i, num = 0, err = 0;
355
356	proteon_netdev_ops = tms380tr_netdev_ops;
357	proteon_netdev_ops.ndo_open = proteon_open;
358	proteon_netdev_ops.ndo_stop = tms380tr_close;
359
360	err = platform_driver_register(&proteon_driver);
361	if (err)
362		return err;
363
364	for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {
365		dev = alloc_trdev(sizeof(struct net_local));
366		if (!dev)
367			continue;
368
369		dev->base_addr = io[i];
370		dev->irq = irq[i];
371		dev->dma = dma[i];
372		pdev = platform_device_register_simple("proteon",
373			i, NULL, 0);
374		if (IS_ERR(pdev)) {
375			free_netdev(dev);
376			continue;
377		}
378		err = setup_card(dev, &pdev->dev);
379		if (!err) {
380			proteon_dev[i] = pdev;
381			platform_set_drvdata(pdev, dev);
382			++num;
383		} else {
384			platform_device_unregister(pdev);
385			free_netdev(dev);
386		}
387	}
388
389	printk(KERN_NOTICE "proteon.c: %d cards found.\n", num);
390	/* Probe for cards. */
391	if (num == 0) {
392		printk(KERN_NOTICE "proteon.c: No cards found.\n");
393		platform_driver_unregister(&proteon_driver);
394		return -ENODEV;
395	}
396	return 0;
397}
398
399static void __exit proteon_cleanup(void)
400{
401	struct net_device *dev;
402	int i;
403
404	for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {
405		struct platform_device *pdev = proteon_dev[i];
406
407		if (!pdev)
408			continue;
409		dev = platform_get_drvdata(pdev);
410		unregister_netdev(dev);
411		release_region(dev->base_addr, PROTEON_IO_EXTENT);
412		free_irq(dev->irq, dev);
413		free_dma(dev->dma);
414		tmsdev_term(dev);
415		free_netdev(dev);
416		platform_set_drvdata(pdev, NULL);
417		platform_device_unregister(pdev);
418	}
419	platform_driver_unregister(&proteon_driver);
420}
421
422module_init(proteon_init);
423module_exit(proteon_cleanup);
424