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  */
22 static 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. */
45 static 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. */
54 static 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. */
60 static int dmalist[] __initdata = {
61 	5, 6, 7,
62 	0
63 };
64 
65 static char cardname[] = "Proteon 1392\0";
66 static u64 dma_mask = ISA_MAX_ADDRESS;
67 static int proteon_open(struct net_device *dev);
68 static void proteon_read_eeprom(struct net_device *dev);
69 static unsigned short proteon_setnselout_pins(struct net_device *dev);
70 
proteon_sifreadb(struct net_device * dev,unsigned short reg)71 static unsigned short proteon_sifreadb(struct net_device *dev, unsigned short reg)
72 {
73 	return inb(dev->base_addr + reg);
74 }
75 
proteon_sifreadw(struct net_device * dev,unsigned short reg)76 static unsigned short proteon_sifreadw(struct net_device *dev, unsigned short reg)
77 {
78 	return inw(dev->base_addr + reg);
79 }
80 
proteon_sifwriteb(struct net_device * dev,unsigned short val,unsigned short reg)81 static void proteon_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg)
82 {
83 	outb(val, dev->base_addr + reg);
84 }
85 
proteon_sifwritew(struct net_device * dev,unsigned short val,unsigned short reg)86 static void proteon_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg)
87 {
88 	outw(val, dev->base_addr + reg);
89 }
90 
proteon_probe1(struct net_device * dev,int ioaddr)91 static 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;
114 nodev:
115 	release_region(ioaddr, PROTEON_IO_EXTENT);
116 	return -ENODEV;
117 }
118 
119 static struct net_device_ops proteon_netdev_ops __read_mostly;
120 
setup_card(struct net_device * dev,struct device * pdev)121 static 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;
252 out:
253 	free_dma(dev->dma);
254 out2:
255 	free_irq(dev->irq, dev);
256 out3:
257 	tmsdev_term(dev);
258 out4:
259 	release_region(dev->base_addr, PROTEON_IO_EXTENT);
260 out5:
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  */
proteon_read_eeprom(struct net_device * dev)273 static 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 
proteon_setnselout_pins(struct net_device * dev)287 static unsigned short proteon_setnselout_pins(struct net_device *dev)
288 {
289 	return 0;
290 }
291 
proteon_open(struct net_device * dev)292 static 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 
332 static int io[ISATR_MAX_ADAPTERS];
333 static int irq[ISATR_MAX_ADAPTERS];
334 static int dma[ISATR_MAX_ADAPTERS];
335 
336 MODULE_LICENSE("GPL");
337 
338 module_param_array(io, int, NULL, 0);
339 module_param_array(irq, int, NULL, 0);
340 module_param_array(dma, int, NULL, 0);
341 
342 static struct platform_device *proteon_dev[ISATR_MAX_ADAPTERS];
343 
344 static struct platform_driver proteon_driver = {
345 	.driver		= {
346 		.name	= "proteon",
347 	},
348 };
349 
proteon_init(void)350 static 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 
proteon_cleanup(void)399 static 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 
422 module_init(proteon_init);
423 module_exit(proteon_cleanup);
424