1 /*
2 * tmsisa.c: A generic network driver for TMS380-based ISA token ring cards.
3 *
4 * Based on tmspci written 1999 by Adam Fritzler
5 *
6 * Written 2000 by Jochen Friedrich
7 * Dedicated to my girlfriend Steffi Bopp
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
12 * This driver module supports the following cards:
13 * - SysKonnect TR4/16(+) ISA (SK-4190)
14 *
15 * Maintainer(s):
16 * AF Adam Fritzler mid@auk.cx
17 * JF Jochen Friedrich jochen@scram.de
18 *
19 * TODO:
20 * 1. Add support for Proteon TR ISA adapters (1392, 1392+)
21 */
22 static const char version[] = "tmsisa.c: v1.00 14/01/2001 by Jochen Friedrich\n";
23
24 #include <linux/module.h>
25 #include <linux/kernel.h>
26 #include <linux/sched.h>
27 #include <linux/errno.h>
28 #include <linux/pci.h>
29 #include <linux/init.h>
30
31 #include <asm/system.h>
32 #include <asm/io.h>
33 #include <asm/irq.h>
34 #include <asm/pci.h>
35 #include <asm/dma.h>
36
37 #include <linux/netdevice.h>
38 #include <linux/trdevice.h>
39 #include "tms380tr.h"
40
41 #define TMS_ISA_IO_EXTENT 32
42
43 /* A zero-terminated list of I/O addresses to be probed. */
44 static unsigned int portlist[] __initdata = {
45 0x0A20, 0x1A20, 0x0B20, 0x1B20, 0x0980, 0x1980, 0x0900, 0x1900,// SK
46 0
47 };
48
49 /* A zero-terminated list of IRQs to be probed.
50 * Used again after initial probe for sktr_chipset_init, called from sktr_open.
51 */
52 static unsigned short irqlist[] = {
53 3, 5, 9, 10, 11, 12, 15,
54 0
55 };
56
57 /* A zero-terminated list of DMAs to be probed. */
58 static int dmalist[] __initdata = {
59 5, 6, 7,
60 0
61 };
62
63 static char isa_cardname[] = "SK NET TR 4/16 ISA\0";
64
65 int tms_isa_probe(struct net_device *dev);
66 static int tms_isa_open(struct net_device *dev);
67 static int tms_isa_close(struct net_device *dev);
68 static void tms_isa_read_eeprom(struct net_device *dev);
69 static unsigned short tms_isa_setnselout_pins(struct net_device *dev);
70
tms_isa_sifreadb(struct net_device * dev,unsigned short reg)71 static unsigned short tms_isa_sifreadb(struct net_device *dev, unsigned short reg)
72 {
73 return inb(dev->base_addr + reg);
74 }
75
tms_isa_sifreadw(struct net_device * dev,unsigned short reg)76 static unsigned short tms_isa_sifreadw(struct net_device *dev, unsigned short reg)
77 {
78 return inw(dev->base_addr + reg);
79 }
80
tms_isa_sifwriteb(struct net_device * dev,unsigned short val,unsigned short reg)81 static void tms_isa_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg)
82 {
83 outb(val, dev->base_addr + reg);
84 }
85
tms_isa_sifwritew(struct net_device * dev,unsigned short val,unsigned short reg)86 static void tms_isa_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg)
87 {
88 outw(val, dev->base_addr + reg);
89 }
90
91 struct tms_isa_card {
92 struct net_device *dev;
93 struct tms_isa_card *next;
94 };
95
96 static struct tms_isa_card *tms_isa_card_list;
97
tms_isa_probe1(int ioaddr)98 static int __init tms_isa_probe1(int ioaddr)
99 {
100 unsigned char old, chk1, chk2;
101
102 old = inb(ioaddr + SIFADR); /* Get the old SIFADR value */
103
104 chk1 = 0; /* Begin with check value 0 */
105 do {
106 /* Write new SIFADR value */
107 outb(chk1, ioaddr + SIFADR);
108
109 /* Read, invert and write */
110 chk2 = inb(ioaddr + SIFADD);
111 chk2 ^= 0x0FE;
112 outb(chk2, ioaddr + SIFADR);
113
114 /* Read, invert and compare */
115 chk2 = inb(ioaddr + SIFADD);
116 chk2 ^= 0x0FE;
117
118 if(chk1 != chk2)
119 return (-1); /* No adapter */
120
121 chk1 -= 2;
122 } while(chk1 != 0); /* Repeat 128 times (all byte values) */
123
124 /* Restore the SIFADR value */
125 outb(old, ioaddr + SIFADR);
126
127 return (0);
128 }
129
tms_isa_probe(struct net_device * dev)130 int __init tms_isa_probe(struct net_device *dev)
131 {
132 static int versionprinted;
133 struct net_local *tp;
134 int j;
135 struct tms_isa_card *card;
136
137 if(check_region(dev->base_addr, TMS_ISA_IO_EXTENT))
138 return -1;
139
140 if(tms_isa_probe1(dev->base_addr))
141 return -1;
142
143 if (versionprinted++ == 0)
144 printk("%s", version);
145
146 /* At this point we have found a valid card. */
147
148 if (!request_region(dev->base_addr, TMS_ISA_IO_EXTENT, isa_cardname))
149 return -1;
150
151 if (tmsdev_init(dev, ISA_MAX_ADDRESS, NULL))
152 {
153 release_region(dev->base_addr, TMS_ISA_IO_EXTENT);
154 return -1;
155 }
156
157 dev->base_addr &= ~3;
158
159 tms_isa_read_eeprom(dev);
160
161 printk("%s: Ring Station Address: ", dev->name);
162 printk("%2.2x", dev->dev_addr[0]);
163 for (j = 1; j < 6; j++)
164 printk(":%2.2x", dev->dev_addr[j]);
165 printk("\n");
166
167 tp = (struct net_local *)dev->priv;
168 tp->setnselout = tms_isa_setnselout_pins;
169
170 tp->sifreadb = tms_isa_sifreadb;
171 tp->sifreadw = tms_isa_sifreadw;
172 tp->sifwriteb = tms_isa_sifwriteb;
173 tp->sifwritew = tms_isa_sifwritew;
174
175 memcpy(tp->ProductID, isa_cardname, PROD_ID_SIZE + 1);
176
177 tp->tmspriv = NULL;
178
179 dev->open = tms_isa_open;
180 dev->stop = tms_isa_close;
181
182 if (dev->irq == 0)
183 {
184 for(j = 0; irqlist[j] != 0; j++)
185 {
186 dev->irq = irqlist[j];
187 if (!request_irq(dev->irq, tms380tr_interrupt, 0,
188 isa_cardname, dev))
189 break;
190 }
191
192 if(irqlist[j] == 0)
193 {
194 printk("%s: AutoSelect no IRQ available\n", dev->name);
195 release_region(dev->base_addr, TMS_ISA_IO_EXTENT);
196 tmsdev_term(dev);
197 return -1;
198 }
199 }
200 else
201 {
202 for(j = 0; irqlist[j] != 0; j++)
203 if (irqlist[j] == dev->irq)
204 break;
205 if (irqlist[j] == 0)
206 {
207 printk("%s: Illegal IRQ %d specified\n",
208 dev->name, dev->irq);
209 release_region(dev->base_addr, TMS_ISA_IO_EXTENT);
210 tmsdev_term(dev);
211 return -1;
212 }
213 if (request_irq(dev->irq, tms380tr_interrupt, 0,
214 isa_cardname, dev))
215 {
216 printk("%s: Selected IRQ %d not available\n",
217 dev->name, dev->irq);
218 release_region(dev->base_addr, TMS_ISA_IO_EXTENT);
219 tmsdev_term(dev);
220 return -1;
221 }
222 }
223
224 if (dev->dma == 0)
225 {
226 for(j = 0; dmalist[j] != 0; j++)
227 {
228 dev->dma = dmalist[j];
229 if (!request_dma(dev->dma, isa_cardname))
230 break;
231 }
232
233 if(dmalist[j] == 0)
234 {
235 printk("%s: AutoSelect no DMA available\n", dev->name);
236 release_region(dev->base_addr, TMS_ISA_IO_EXTENT);
237 free_irq(dev->irq, dev);
238 tmsdev_term(dev);
239 return -1;
240 }
241 }
242 else
243 {
244 for(j = 0; dmalist[j] != 0; j++)
245 if (dmalist[j] == dev->dma)
246 break;
247 if (dmalist[j] == 0)
248 {
249 printk("%s: Illegal DMA %d specified\n",
250 dev->name, dev->dma);
251 release_region(dev->base_addr, TMS_ISA_IO_EXTENT);
252 free_irq(dev->irq, dev);
253 tmsdev_term(dev);
254 return -1;
255 }
256 if (request_dma(dev->dma, isa_cardname))
257 {
258 printk("%s: Selected DMA %d not available\n",
259 dev->name, dev->dma);
260 release_region(dev->base_addr, TMS_ISA_IO_EXTENT);
261 free_irq(dev->irq, dev);
262 tmsdev_term(dev);
263 return -1;
264 }
265 }
266
267 printk("%s: IO: %#4lx IRQ: %d DMA: %d\n",
268 dev->name, dev->base_addr, dev->irq, dev->dma);
269
270 if (register_trdev(dev) == 0)
271 {
272 /* Enlist in the card list */
273 card = kmalloc(sizeof(struct tms_isa_card), GFP_KERNEL);
274 if (!card) {
275 unregister_trdev(dev);
276 release_region(dev->base_addr, TMS_ISA_IO_EXTENT);
277 free_irq(dev->irq, dev);
278 free_dma(dev->dma);
279 tmsdev_term(dev);
280 return -1;
281 }
282 card->next = tms_isa_card_list;
283 tms_isa_card_list = card;
284 card->dev = dev;
285 }
286 else
287 {
288 printk("%s: register_trdev() returned non-zero.\n", dev->name);
289 release_region(dev->base_addr, TMS_ISA_IO_EXTENT);
290 free_irq(dev->irq, dev);
291 free_dma(dev->dma);
292 tmsdev_term(dev);
293 return -1;
294 }
295
296 return 0;
297 }
298
299 /*
300 * Reads MAC address from adapter RAM, which should've read it from
301 * the onboard ROM.
302 *
303 * Calling this on a board that does not support it can be a very
304 * dangerous thing. The Madge board, for instance, will lock your
305 * machine hard when this is called. Luckily, its supported in a
306 * seperate driver. --ASF
307 */
tms_isa_read_eeprom(struct net_device * dev)308 static void tms_isa_read_eeprom(struct net_device *dev)
309 {
310 int i;
311
312 /* Address: 0000:0000 */
313 tms_isa_sifwritew(dev, 0, SIFADX);
314 tms_isa_sifwritew(dev, 0, SIFADR);
315
316 /* Read six byte MAC address data */
317 dev->addr_len = 6;
318 for(i = 0; i < 6; i++)
319 dev->dev_addr[i] = tms_isa_sifreadw(dev, SIFINC) >> 8;
320 }
321
tms_isa_setnselout_pins(struct net_device * dev)322 unsigned short tms_isa_setnselout_pins(struct net_device *dev)
323 {
324 return 0;
325 }
326
tms_isa_open(struct net_device * dev)327 static int tms_isa_open(struct net_device *dev)
328 {
329 struct net_local *tp = (struct net_local *)dev->priv;
330 unsigned short val = 0;
331 unsigned short oldval;
332 int i;
333
334 val = 0;
335 for(i = 0; irqlist[i] != 0; i++)
336 {
337 if(irqlist[i] == dev->irq)
338 break;
339 }
340
341 val |= CYCLE_TIME << 2;
342 val |= i << 4;
343 i = dev->dma - 5;
344 val |= i;
345 if(tp->DataRate == SPEED_4)
346 val |= LINE_SPEED_BIT;
347 else
348 val &= ~LINE_SPEED_BIT;
349 oldval = tms_isa_sifreadb(dev, POSREG);
350 /* Leave cycle bits alone */
351 oldval |= 0xf3;
352 val &= oldval;
353 tms_isa_sifwriteb(dev, val, POSREG);
354
355 tms380tr_open(dev);
356 MOD_INC_USE_COUNT;
357 return 0;
358 }
359
tms_isa_close(struct net_device * dev)360 static int tms_isa_close(struct net_device *dev)
361 {
362 tms380tr_close(dev);
363 MOD_DEC_USE_COUNT;
364 return 0;
365 }
366
367 #ifdef MODULE
368
369 #define ISATR_MAX_ADAPTERS 3
370
371 static int io[ISATR_MAX_ADAPTERS];
372 static int irq[ISATR_MAX_ADAPTERS];
373 static int dma[ISATR_MAX_ADAPTERS];
374
375 MODULE_LICENSE("GPL");
376
377 MODULE_PARM(io, "1-" __MODULE_STRING(ISATR_MAX_ADAPTERS) "i");
378 MODULE_PARM(irq, "1-" __MODULE_STRING(ISATR_MAX_ADAPTERS) "i");
379 MODULE_PARM(dma, "1-" __MODULE_STRING(ISATR_MAX_ADAPTERS) "i");
380
init_module(void)381 int init_module(void)
382 {
383 int i, num;
384 struct net_device *dev;
385
386 num = 0;
387 if (io[0])
388 { /* Only probe addresses from command line */
389 for (i = 0; i < ISATR_MAX_ADAPTERS; i++)
390 {
391 if (io[i] == 0)
392 continue;
393
394 dev = init_trdev(NULL, 0);
395 if (!dev)
396 return (-ENOMEM);
397
398 dev->base_addr = io[i];
399 dev->irq = irq[i];
400 dev->dma = dma[i];
401
402 if (tms_isa_probe(dev))
403 {
404 unregister_netdev(dev);
405 kfree(dev);
406 }
407 else
408 num++;
409 }
410 }
411 else
412 {
413 for(i = 0; portlist[i]; i++)
414 {
415 if (num >= ISATR_MAX_ADAPTERS)
416 continue;
417
418 dev = init_trdev(NULL, 0);
419 if (!dev)
420 return (-ENOMEM);
421
422 dev->base_addr = portlist[i];
423 dev->irq = irq[num];
424 dev->dma = dma[num];
425
426 if (tms_isa_probe(dev))
427 {
428 unregister_netdev(dev);
429 kfree(dev);
430 }
431 else
432 num++;
433 }
434 }
435 printk(KERN_NOTICE "tmsisa.c: %d cards found.\n", num);
436 /* Probe for cards. */
437 if (num == 0) {
438 printk(KERN_NOTICE "tmsisa.c: No cards found.\n");
439 }
440 return (0);
441 }
442
cleanup_module(void)443 void cleanup_module(void)
444 {
445 struct net_device *dev;
446 struct tms_isa_card *this_card;
447
448 while (tms_isa_card_list) {
449 dev = tms_isa_card_list->dev;
450
451 unregister_netdev(dev);
452 release_region(dev->base_addr, TMS_ISA_IO_EXTENT);
453 free_irq(dev->irq, dev);
454 free_dma(dev->dma);
455 tmsdev_term(dev);
456 kfree(dev);
457 this_card = tms_isa_card_list;
458 tms_isa_card_list = this_card->next;
459 kfree(this_card);
460 }
461 }
462 #endif /* MODULE */
463
464
465 /*
466 * Local variables:
467 * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tmsisa.c"
468 * alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tmsisa.c"
469 * c-set-style "K&R"
470 * c-indent-level: 8
471 * c-basic-offset: 8
472 * tab-width: 8
473 * End:
474 */
475