]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * madgemc.c: Driver for the Madge Smart 16/4 MC16 MCA token ring card. | |
3 | * | |
4 | * Written 2000 by Adam Fritzler | |
5 | * | |
6 | * This software may be used and distributed according to the terms | |
7 | * of the GNU General Public License, incorporated herein by reference. | |
8 | * | |
9 | * This driver module supports the following cards: | |
10 | * - Madge Smart 16/4 Ringnode MC16 | |
11 | * - Madge Smart 16/4 Ringnode MC32 (??) | |
12 | * | |
13 | * Maintainer(s): | |
14 | * AF Adam Fritzler mid@auk.cx | |
15 | * | |
16 | * Modification History: | |
17 | * 16-Jan-00 AF Created | |
18 | * | |
19 | */ | |
20 | static const char version[] = "madgemc.c: v0.91 23/01/2000 by Adam Fritzler\n"; | |
21 | ||
22 | #include <linux/module.h> | |
23 | #include <linux/mca-legacy.h> | |
24 | #include <linux/kernel.h> | |
25 | #include <linux/errno.h> | |
26 | #include <linux/pci.h> | |
27 | #include <linux/init.h> | |
28 | #include <linux/netdevice.h> | |
29 | #include <linux/trdevice.h> | |
30 | ||
31 | #include <asm/system.h> | |
32 | #include <asm/io.h> | |
33 | #include <asm/irq.h> | |
34 | ||
35 | #include "tms380tr.h" | |
36 | #include "madgemc.h" /* Madge-specific constants */ | |
37 | ||
38 | #define MADGEMC_IO_EXTENT 32 | |
39 | #define MADGEMC_SIF_OFFSET 0x08 | |
40 | ||
41 | struct madgemc_card { | |
42 | struct net_device *dev; | |
43 | ||
44 | /* | |
45 | * These are read from the BIA ROM. | |
46 | */ | |
47 | unsigned int manid; | |
48 | unsigned int cardtype; | |
49 | unsigned int cardrev; | |
50 | unsigned int ramsize; | |
51 | ||
52 | /* | |
53 | * These are read from the MCA POS registers. | |
54 | */ | |
55 | unsigned int burstmode:2; | |
56 | unsigned int fairness:1; /* 0 = Fair, 1 = Unfair */ | |
57 | unsigned int arblevel:4; | |
58 | unsigned int ringspeed:2; /* 0 = 4mb, 1 = 16, 2 = Auto/none */ | |
59 | unsigned int cabletype:1; /* 0 = RJ45, 1 = DB9 */ | |
60 | ||
61 | struct madgemc_card *next; | |
62 | }; | |
63 | static struct madgemc_card *madgemc_card_list; | |
64 | ||
65 | ||
66 | static int madgemc_open(struct net_device *dev); | |
67 | static int madgemc_close(struct net_device *dev); | |
68 | static int madgemc_chipset_init(struct net_device *dev); | |
69 | static void madgemc_read_rom(struct madgemc_card *card); | |
70 | static unsigned short madgemc_setnselout_pins(struct net_device *dev); | |
71 | static void madgemc_setcabletype(struct net_device *dev, int type); | |
72 | ||
73 | static int madgemc_mcaproc(char *buf, int slot, void *d); | |
74 | ||
75 | static void madgemc_setregpage(struct net_device *dev, int page); | |
76 | static void madgemc_setsifsel(struct net_device *dev, int val); | |
77 | static void madgemc_setint(struct net_device *dev, int val); | |
78 | ||
79 | static irqreturn_t madgemc_interrupt(int irq, void *dev_id, struct pt_regs *regs); | |
80 | ||
81 | /* | |
82 | * These work around paging, however they don't guarentee you're on the | |
83 | * right page. | |
84 | */ | |
85 | #define SIFREADB(reg) (inb(dev->base_addr + ((reg<0x8)?reg:reg-0x8))) | |
86 | #define SIFWRITEB(val, reg) (outb(val, dev->base_addr + ((reg<0x8)?reg:reg-0x8))) | |
87 | #define SIFREADW(reg) (inw(dev->base_addr + ((reg<0x8)?reg:reg-0x8))) | |
88 | #define SIFWRITEW(val, reg) (outw(val, dev->base_addr + ((reg<0x8)?reg:reg-0x8))) | |
89 | ||
90 | /* | |
91 | * Read a byte-length value from the register. | |
92 | */ | |
93 | static unsigned short madgemc_sifreadb(struct net_device *dev, unsigned short reg) | |
94 | { | |
95 | unsigned short ret; | |
96 | if (reg<0x8) | |
97 | ret = SIFREADB(reg); | |
98 | else { | |
99 | madgemc_setregpage(dev, 1); | |
100 | ret = SIFREADB(reg); | |
101 | madgemc_setregpage(dev, 0); | |
102 | } | |
103 | return ret; | |
104 | } | |
105 | ||
106 | /* | |
107 | * Write a byte-length value to a register. | |
108 | */ | |
109 | static void madgemc_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg) | |
110 | { | |
111 | if (reg<0x8) | |
112 | SIFWRITEB(val, reg); | |
113 | else { | |
114 | madgemc_setregpage(dev, 1); | |
115 | SIFWRITEB(val, reg); | |
116 | madgemc_setregpage(dev, 0); | |
117 | } | |
118 | return; | |
119 | } | |
120 | ||
121 | /* | |
122 | * Read a word-length value from a register | |
123 | */ | |
124 | static unsigned short madgemc_sifreadw(struct net_device *dev, unsigned short reg) | |
125 | { | |
126 | unsigned short ret; | |
127 | if (reg<0x8) | |
128 | ret = SIFREADW(reg); | |
129 | else { | |
130 | madgemc_setregpage(dev, 1); | |
131 | ret = SIFREADW(reg); | |
132 | madgemc_setregpage(dev, 0); | |
133 | } | |
134 | return ret; | |
135 | } | |
136 | ||
137 | /* | |
138 | * Write a word-length value to a register. | |
139 | */ | |
140 | static void madgemc_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg) | |
141 | { | |
142 | if (reg<0x8) | |
143 | SIFWRITEW(val, reg); | |
144 | else { | |
145 | madgemc_setregpage(dev, 1); | |
146 | SIFWRITEW(val, reg); | |
147 | madgemc_setregpage(dev, 0); | |
148 | } | |
149 | return; | |
150 | } | |
151 | ||
152 | ||
153 | ||
154 | static int __init madgemc_probe(void) | |
155 | { | |
156 | static int versionprinted; | |
157 | struct net_device *dev; | |
158 | struct net_local *tp; | |
159 | struct madgemc_card *card; | |
160 | int i,slot = 0; | |
161 | __u8 posreg[4]; | |
162 | ||
163 | if (!MCA_bus) | |
164 | return -1; | |
165 | ||
166 | while (slot != MCA_NOTFOUND) { | |
167 | /* | |
168 | * Currently we only support the MC16/32 (MCA ID 002d) | |
169 | */ | |
170 | slot = mca_find_unused_adapter(0x002d, slot); | |
171 | if (slot == MCA_NOTFOUND) | |
172 | break; | |
173 | ||
174 | /* | |
175 | * If we get here, we have an adapter. | |
176 | */ | |
177 | if (versionprinted++ == 0) | |
178 | printk("%s", version); | |
179 | ||
180 | dev = alloc_trdev(sizeof(struct net_local)); | |
181 | if (dev == NULL) { | |
182 | printk("madgemc: unable to allocate dev space\n"); | |
183 | if (madgemc_card_list) | |
184 | return 0; | |
185 | return -1; | |
186 | } | |
187 | ||
188 | SET_MODULE_OWNER(dev); | |
189 | dev->dma = 0; | |
190 | ||
191 | /* | |
192 | * Fetch MCA config registers | |
193 | */ | |
194 | for(i=0;i<4;i++) | |
195 | posreg[i] = mca_read_stored_pos(slot, i+2); | |
196 | ||
197 | card = kmalloc(sizeof(struct madgemc_card), GFP_KERNEL); | |
198 | if (card==NULL) { | |
199 | printk("madgemc: unable to allocate card struct\n"); | |
200 | free_netdev(dev); | |
201 | if (madgemc_card_list) | |
202 | return 0; | |
203 | return -1; | |
204 | } | |
205 | card->dev = dev; | |
206 | ||
207 | /* | |
208 | * Parse configuration information. This all comes | |
209 | * directly from the publicly available @002d.ADF. | |
210 | * Get it from Madge or your local ADF library. | |
211 | */ | |
212 | ||
213 | /* | |
214 | * Base address | |
215 | */ | |
216 | dev->base_addr = 0x0a20 + | |
217 | ((posreg[2] & MC16_POS2_ADDR2)?0x0400:0) + | |
218 | ((posreg[0] & MC16_POS0_ADDR1)?0x1000:0) + | |
219 | ((posreg[3] & MC16_POS3_ADDR3)?0x2000:0); | |
220 | ||
221 | /* | |
222 | * Interrupt line | |
223 | */ | |
224 | switch(posreg[0] >> 6) { /* upper two bits */ | |
225 | case 0x1: dev->irq = 3; break; | |
226 | case 0x2: dev->irq = 9; break; /* IRQ 2 = IRQ 9 */ | |
227 | case 0x3: dev->irq = 10; break; | |
228 | default: dev->irq = 0; break; | |
229 | } | |
230 | ||
231 | if (dev->irq == 0) { | |
232 | printk("%s: invalid IRQ\n", dev->name); | |
233 | goto getout1; | |
234 | } | |
235 | ||
236 | if (!request_region(dev->base_addr, MADGEMC_IO_EXTENT, | |
237 | "madgemc")) { | |
238 | printk(KERN_INFO "madgemc: unable to setup Smart MC in slot %d because of I/O base conflict at 0x%04lx\n", slot, dev->base_addr); | |
239 | dev->base_addr += MADGEMC_SIF_OFFSET; | |
240 | goto getout1; | |
241 | } | |
242 | dev->base_addr += MADGEMC_SIF_OFFSET; | |
243 | ||
244 | /* | |
245 | * Arbitration Level | |
246 | */ | |
247 | card->arblevel = ((posreg[0] >> 1) & 0x7) + 8; | |
248 | ||
249 | /* | |
250 | * Burst mode and Fairness | |
251 | */ | |
252 | card->burstmode = ((posreg[2] >> 6) & 0x3); | |
253 | card->fairness = ((posreg[2] >> 4) & 0x1); | |
254 | ||
255 | /* | |
256 | * Ring Speed | |
257 | */ | |
258 | if ((posreg[1] >> 2)&0x1) | |
259 | card->ringspeed = 2; /* not selected */ | |
260 | else if ((posreg[2] >> 5) & 0x1) | |
261 | card->ringspeed = 1; /* 16Mb */ | |
262 | else | |
263 | card->ringspeed = 0; /* 4Mb */ | |
264 | ||
265 | /* | |
266 | * Cable type | |
267 | */ | |
268 | if ((posreg[1] >> 6)&0x1) | |
269 | card->cabletype = 1; /* STP/DB9 */ | |
270 | else | |
271 | card->cabletype = 0; /* UTP/RJ-45 */ | |
272 | ||
273 | ||
274 | /* | |
275 | * ROM Info. This requires us to actually twiddle | |
276 | * bits on the card, so we must ensure above that | |
277 | * the base address is free of conflict (request_region above). | |
278 | */ | |
279 | madgemc_read_rom(card); | |
280 | ||
281 | if (card->manid != 0x4d) { /* something went wrong */ | |
282 | printk(KERN_INFO "%s: Madge MC ROM read failed (unknown manufacturer ID %02x)\n", dev->name, card->manid); | |
283 | goto getout; | |
284 | } | |
285 | ||
286 | if ((card->cardtype != 0x08) && (card->cardtype != 0x0d)) { | |
287 | printk(KERN_INFO "%s: Madge MC ROM read failed (unknown card ID %02x)\n", dev->name, card->cardtype); | |
288 | goto getout; | |
289 | } | |
290 | ||
291 | /* All cards except Rev 0 and 1 MC16's have 256kb of RAM */ | |
292 | if ((card->cardtype == 0x08) && (card->cardrev <= 0x01)) | |
293 | card->ramsize = 128; | |
294 | else | |
295 | card->ramsize = 256; | |
296 | ||
297 | printk("%s: %s Rev %d at 0x%04lx IRQ %d\n", | |
298 | dev->name, | |
299 | (card->cardtype == 0x08)?MADGEMC16_CARDNAME: | |
300 | MADGEMC32_CARDNAME, card->cardrev, | |
301 | dev->base_addr, dev->irq); | |
302 | ||
303 | if (card->cardtype == 0x0d) | |
304 | printk("%s: Warning: MC32 support is experimental and highly untested\n", dev->name); | |
305 | ||
306 | if (card->ringspeed==2) { /* Unknown */ | |
307 | printk("%s: Warning: Ring speed not set in POS -- Please run the reference disk and set it!\n", dev->name); | |
308 | card->ringspeed = 1; /* default to 16mb */ | |
309 | } | |
310 | ||
311 | printk("%s: RAM Size: %dKB\n", dev->name, card->ramsize); | |
312 | ||
313 | printk("%s: Ring Speed: %dMb/sec on %s\n", dev->name, | |
314 | (card->ringspeed)?16:4, | |
315 | card->cabletype?"STP/DB9":"UTP/RJ-45"); | |
316 | printk("%s: Arbitration Level: %d\n", dev->name, | |
317 | card->arblevel); | |
318 | ||
319 | printk("%s: Burst Mode: ", dev->name); | |
320 | switch(card->burstmode) { | |
321 | case 0: printk("Cycle steal"); break; | |
322 | case 1: printk("Limited burst"); break; | |
323 | case 2: printk("Delayed release"); break; | |
324 | case 3: printk("Immediate release"); break; | |
325 | } | |
326 | printk(" (%s)\n", (card->fairness)?"Unfair":"Fair"); | |
327 | ||
328 | ||
329 | /* | |
330 | * Enable SIF before we assign the interrupt handler, | |
331 | * just in case we get spurious interrupts that need | |
332 | * handling. | |
333 | */ | |
334 | outb(0, dev->base_addr + MC_CONTROL_REG0); /* sanity */ | |
335 | madgemc_setsifsel(dev, 1); | |
336 | if (request_irq(dev->irq, madgemc_interrupt, SA_SHIRQ, | |
337 | "madgemc", dev)) | |
338 | goto getout; | |
339 | ||
340 | madgemc_chipset_init(dev); /* enables interrupts! */ | |
341 | madgemc_setcabletype(dev, card->cabletype); | |
342 | ||
343 | /* Setup MCA structures */ | |
344 | mca_set_adapter_name(slot, (card->cardtype == 0x08)?MADGEMC16_CARDNAME:MADGEMC32_CARDNAME); | |
345 | mca_set_adapter_procfn(slot, madgemc_mcaproc, dev); | |
346 | mca_mark_as_used(slot); | |
347 | ||
348 | printk("%s: Ring Station Address: ", dev->name); | |
349 | printk("%2.2x", dev->dev_addr[0]); | |
350 | for (i = 1; i < 6; i++) | |
351 | printk(":%2.2x", dev->dev_addr[i]); | |
352 | printk("\n"); | |
353 | ||
354 | /* XXX is ISA_MAX_ADDRESS correct here? */ | |
355 | if (tmsdev_init(dev, ISA_MAX_ADDRESS, NULL)) { | |
356 | printk("%s: unable to get memory for dev->priv.\n", | |
357 | dev->name); | |
358 | release_region(dev->base_addr-MADGEMC_SIF_OFFSET, | |
359 | MADGEMC_IO_EXTENT); | |
360 | ||
361 | kfree(card); | |
362 | tmsdev_term(dev); | |
363 | free_netdev(dev); | |
364 | if (madgemc_card_list) | |
365 | return 0; | |
366 | return -1; | |
367 | } | |
368 | tp = netdev_priv(dev); | |
369 | ||
370 | /* | |
371 | * The MC16 is physically a 32bit card. However, Madge | |
372 | * insists on calling it 16bit, so I'll assume here that | |
373 | * they know what they're talking about. Cut off DMA | |
374 | * at 16mb. | |
375 | */ | |
376 | tp->setnselout = madgemc_setnselout_pins; | |
377 | tp->sifwriteb = madgemc_sifwriteb; | |
378 | tp->sifreadb = madgemc_sifreadb; | |
379 | tp->sifwritew = madgemc_sifwritew; | |
380 | tp->sifreadw = madgemc_sifreadw; | |
381 | tp->DataRate = (card->ringspeed)?SPEED_16:SPEED_4; | |
382 | ||
383 | memcpy(tp->ProductID, "Madge MCA 16/4 ", PROD_ID_SIZE + 1); | |
384 | ||
385 | dev->open = madgemc_open; | |
386 | dev->stop = madgemc_close; | |
387 | ||
388 | if (register_netdev(dev) == 0) { | |
389 | /* Enlist in the card list */ | |
390 | card->next = madgemc_card_list; | |
391 | madgemc_card_list = card; | |
392 | slot++; | |
393 | continue; /* successful, try to find another */ | |
394 | } | |
395 | ||
396 | free_irq(dev->irq, dev); | |
397 | getout: | |
398 | release_region(dev->base_addr-MADGEMC_SIF_OFFSET, | |
399 | MADGEMC_IO_EXTENT); | |
400 | getout1: | |
401 | kfree(card); | |
402 | free_netdev(dev); | |
403 | slot++; | |
404 | } | |
405 | ||
406 | if (madgemc_card_list) | |
407 | return 0; | |
408 | return -1; | |
409 | } | |
410 | ||
411 | /* | |
412 | * Handle interrupts generated by the card | |
413 | * | |
414 | * The MicroChannel Madge cards need slightly more handling | |
415 | * after an interrupt than other TMS380 cards do. | |
416 | * | |
417 | * First we must make sure it was this card that generated the | |
418 | * interrupt (since interrupt sharing is allowed). Then, | |
419 | * because we're using level-triggered interrupts (as is | |
420 | * standard on MCA), we must toggle the interrupt line | |
421 | * on the card in order to claim and acknowledge the interrupt. | |
422 | * Once that is done, the interrupt should be handlable in | |
423 | * the normal tms380tr_interrupt() routine. | |
424 | * | |
425 | * There's two ways we can check to see if the interrupt is ours, | |
426 | * both with their own disadvantages... | |
427 | * | |
428 | * 1) Read in the SIFSTS register from the TMS controller. This | |
429 | * is guarenteed to be accurate, however, there's a fairly | |
430 | * large performance penalty for doing so: the Madge chips | |
431 | * must request the register from the Eagle, the Eagle must | |
432 | * read them from its internal bus, and then take the route | |
433 | * back out again, for a 16bit read. | |
434 | * | |
435 | * 2) Use the MC_CONTROL_REG0_SINTR bit from the Madge ASICs. | |
436 | * The major disadvantage here is that the accuracy of the | |
437 | * bit is in question. However, it cuts out the extra read | |
438 | * cycles it takes to read the Eagle's SIF, as its only an | |
439 | * 8bit read, and theoretically the Madge bit is directly | |
440 | * connected to the interrupt latch coming out of the Eagle | |
441 | * hardware (that statement is not verified). | |
442 | * | |
443 | * I can't determine which of these methods has the best win. For now, | |
444 | * we make a compromise. Use the Madge way for the first interrupt, | |
445 | * which should be the fast-path, and then once we hit the first | |
446 | * interrupt, keep on trying using the SIF method until we've | |
447 | * exhausted all contiguous interrupts. | |
448 | * | |
449 | */ | |
450 | static irqreturn_t madgemc_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |
451 | { | |
452 | int pending,reg1; | |
453 | struct net_device *dev; | |
454 | ||
455 | if (!dev_id) { | |
456 | printk("madgemc_interrupt: was not passed a dev_id!\n"); | |
457 | return IRQ_NONE; | |
458 | } | |
459 | ||
460 | dev = (struct net_device *)dev_id; | |
461 | ||
462 | /* Make sure its really us. -- the Madge way */ | |
463 | pending = inb(dev->base_addr + MC_CONTROL_REG0); | |
464 | if (!(pending & MC_CONTROL_REG0_SINTR)) | |
465 | return IRQ_NONE; /* not our interrupt */ | |
466 | ||
467 | /* | |
468 | * Since we're level-triggered, we may miss the rising edge | |
469 | * of the next interrupt while we're off handling this one, | |
470 | * so keep checking until the SIF verifies that it has nothing | |
471 | * left for us to do. | |
472 | */ | |
473 | pending = STS_SYSTEM_IRQ; | |
474 | do { | |
475 | if (pending & STS_SYSTEM_IRQ) { | |
476 | ||
477 | /* Toggle the interrupt to reset the latch on card */ | |
478 | reg1 = inb(dev->base_addr + MC_CONTROL_REG1); | |
479 | outb(reg1 ^ MC_CONTROL_REG1_SINTEN, | |
480 | dev->base_addr + MC_CONTROL_REG1); | |
481 | outb(reg1, dev->base_addr + MC_CONTROL_REG1); | |
482 | ||
483 | /* Continue handling as normal */ | |
484 | tms380tr_interrupt(irq, dev_id, regs); | |
485 | ||
486 | pending = SIFREADW(SIFSTS); /* restart - the SIF way */ | |
487 | ||
488 | } else | |
489 | return IRQ_HANDLED; | |
490 | } while (1); | |
491 | ||
492 | return IRQ_HANDLED; /* not reachable */ | |
493 | } | |
494 | ||
495 | /* | |
496 | * Set the card to the prefered ring speed. | |
497 | * | |
498 | * Unlike newer cards, the MC16/32 have their speed selection | |
499 | * circuit connected to the Madge ASICs and not to the TMS380 | |
500 | * NSELOUT pins. Set the ASIC bits correctly here, and return | |
501 | * zero to leave the TMS NSELOUT bits unaffected. | |
502 | * | |
503 | */ | |
504 | unsigned short madgemc_setnselout_pins(struct net_device *dev) | |
505 | { | |
506 | unsigned char reg1; | |
507 | struct net_local *tp = netdev_priv(dev); | |
508 | ||
509 | reg1 = inb(dev->base_addr + MC_CONTROL_REG1); | |
510 | ||
511 | if(tp->DataRate == SPEED_16) | |
512 | reg1 |= MC_CONTROL_REG1_SPEED_SEL; /* add for 16mb */ | |
513 | else if (reg1 & MC_CONTROL_REG1_SPEED_SEL) | |
514 | reg1 ^= MC_CONTROL_REG1_SPEED_SEL; /* remove for 4mb */ | |
515 | outb(reg1, dev->base_addr + MC_CONTROL_REG1); | |
516 | ||
517 | return 0; /* no change */ | |
518 | } | |
519 | ||
520 | /* | |
521 | * Set the register page. This equates to the SRSX line | |
522 | * on the TMS380Cx6. | |
523 | * | |
524 | * Register selection is normally done via three contiguous | |
525 | * bits. However, some boards (such as the MC16/32) use only | |
526 | * two bits, plus a separate bit in the glue chip. This | |
527 | * sets the SRSX bit (the top bit). See page 4-17 in the | |
528 | * Yellow Book for which registers are affected. | |
529 | * | |
530 | */ | |
531 | static void madgemc_setregpage(struct net_device *dev, int page) | |
532 | { | |
533 | static int reg1; | |
534 | ||
535 | reg1 = inb(dev->base_addr + MC_CONTROL_REG1); | |
536 | if ((page == 0) && (reg1 & MC_CONTROL_REG1_SRSX)) { | |
537 | outb(reg1 ^ MC_CONTROL_REG1_SRSX, | |
538 | dev->base_addr + MC_CONTROL_REG1); | |
539 | } | |
540 | else if (page == 1) { | |
541 | outb(reg1 | MC_CONTROL_REG1_SRSX, | |
542 | dev->base_addr + MC_CONTROL_REG1); | |
543 | } | |
544 | reg1 = inb(dev->base_addr + MC_CONTROL_REG1); | |
545 | ||
546 | return; | |
547 | } | |
548 | ||
549 | /* | |
550 | * The SIF registers are not mapped into register space by default | |
551 | * Set this to 1 to map them, 0 to map the BIA ROM. | |
552 | * | |
553 | */ | |
554 | static void madgemc_setsifsel(struct net_device *dev, int val) | |
555 | { | |
556 | unsigned int reg0; | |
557 | ||
558 | reg0 = inb(dev->base_addr + MC_CONTROL_REG0); | |
559 | if ((val == 0) && (reg0 & MC_CONTROL_REG0_SIFSEL)) { | |
560 | outb(reg0 ^ MC_CONTROL_REG0_SIFSEL, | |
561 | dev->base_addr + MC_CONTROL_REG0); | |
562 | } else if (val == 1) { | |
563 | outb(reg0 | MC_CONTROL_REG0_SIFSEL, | |
564 | dev->base_addr + MC_CONTROL_REG0); | |
565 | } | |
566 | reg0 = inb(dev->base_addr + MC_CONTROL_REG0); | |
567 | ||
568 | return; | |
569 | } | |
570 | ||
571 | /* | |
572 | * Enable SIF interrupts | |
573 | * | |
574 | * This does not enable interrupts in the SIF, but rather | |
575 | * enables SIF interrupts to be passed onto the host. | |
576 | * | |
577 | */ | |
578 | static void madgemc_setint(struct net_device *dev, int val) | |
579 | { | |
580 | unsigned int reg1; | |
581 | ||
582 | reg1 = inb(dev->base_addr + MC_CONTROL_REG1); | |
583 | if ((val == 0) && (reg1 & MC_CONTROL_REG1_SINTEN)) { | |
584 | outb(reg1 ^ MC_CONTROL_REG1_SINTEN, | |
585 | dev->base_addr + MC_CONTROL_REG1); | |
586 | } else if (val == 1) { | |
587 | outb(reg1 | MC_CONTROL_REG1_SINTEN, | |
588 | dev->base_addr + MC_CONTROL_REG1); | |
589 | } | |
590 | ||
591 | return; | |
592 | } | |
593 | ||
594 | /* | |
595 | * Cable type is set via control register 7. Bit zero high | |
596 | * for UTP, low for STP. | |
597 | */ | |
598 | static void madgemc_setcabletype(struct net_device *dev, int type) | |
599 | { | |
600 | outb((type==0)?MC_CONTROL_REG7_CABLEUTP:MC_CONTROL_REG7_CABLESTP, | |
601 | dev->base_addr + MC_CONTROL_REG7); | |
602 | } | |
603 | ||
604 | /* | |
605 | * Enable the functions of the Madge chipset needed for | |
606 | * full working order. | |
607 | */ | |
608 | static int madgemc_chipset_init(struct net_device *dev) | |
609 | { | |
610 | outb(0, dev->base_addr + MC_CONTROL_REG1); /* pull SRESET low */ | |
611 | tms380tr_wait(100); /* wait for card to reset */ | |
612 | ||
613 | /* bring back into normal operating mode */ | |
614 | outb(MC_CONTROL_REG1_NSRESET, dev->base_addr + MC_CONTROL_REG1); | |
615 | ||
616 | /* map SIF registers */ | |
617 | madgemc_setsifsel(dev, 1); | |
618 | ||
619 | /* enable SIF interrupts */ | |
620 | madgemc_setint(dev, 1); | |
621 | ||
622 | return 0; | |
623 | } | |
624 | ||
625 | /* | |
626 | * Disable the board, and put back into power-up state. | |
627 | */ | |
628 | void madgemc_chipset_close(struct net_device *dev) | |
629 | { | |
630 | /* disable interrupts */ | |
631 | madgemc_setint(dev, 0); | |
632 | /* unmap SIF registers */ | |
633 | madgemc_setsifsel(dev, 0); | |
634 | ||
635 | return; | |
636 | } | |
637 | ||
638 | /* | |
639 | * Read the card type (MC16 or MC32) from the card. | |
640 | * | |
641 | * The configuration registers are stored in two separate | |
642 | * pages. Pages are flipped by clearing bit 3 of CONTROL_REG0 (PAGE) | |
643 | * for page zero, or setting bit 3 for page one. | |
644 | * | |
645 | * Page zero contains the following data: | |
646 | * Byte 0: Manufacturer ID (0x4D -- ASCII "M") | |
647 | * Byte 1: Card type: | |
648 | * 0x08 for MC16 | |
649 | * 0x0D for MC32 | |
650 | * Byte 2: Card revision | |
651 | * Byte 3: Mirror of POS config register 0 | |
652 | * Byte 4: Mirror of POS 1 | |
653 | * Byte 5: Mirror of POS 2 | |
654 | * | |
655 | * Page one contains the following data: | |
656 | * Byte 0: Unused | |
657 | * Byte 1-6: BIA, MSB to LSB. | |
658 | * | |
659 | * Note that to read the BIA, we must unmap the SIF registers | |
660 | * by clearing bit 2 of CONTROL_REG0 (SIFSEL), as the data | |
661 | * will reside in the same logical location. For this reason, | |
662 | * _never_ read the BIA while the Eagle processor is running! | |
663 | * The SIF will be completely inaccessible until the BIA operation | |
664 | * is complete. | |
665 | * | |
666 | */ | |
667 | static void madgemc_read_rom(struct madgemc_card *card) | |
668 | { | |
669 | unsigned long ioaddr; | |
670 | unsigned char reg0, reg1, tmpreg0, i; | |
671 | ||
672 | ioaddr = card->dev->base_addr; | |
673 | ||
674 | reg0 = inb(ioaddr + MC_CONTROL_REG0); | |
675 | reg1 = inb(ioaddr + MC_CONTROL_REG1); | |
676 | ||
677 | /* Switch to page zero and unmap SIF */ | |
678 | tmpreg0 = reg0 & ~(MC_CONTROL_REG0_PAGE + MC_CONTROL_REG0_SIFSEL); | |
679 | outb(tmpreg0, ioaddr + MC_CONTROL_REG0); | |
680 | ||
681 | card->manid = inb(ioaddr + MC_ROM_MANUFACTURERID); | |
682 | card->cardtype = inb(ioaddr + MC_ROM_ADAPTERID); | |
683 | card->cardrev = inb(ioaddr + MC_ROM_REVISION); | |
684 | ||
685 | /* Switch to rom page one */ | |
686 | outb(tmpreg0 | MC_CONTROL_REG0_PAGE, ioaddr + MC_CONTROL_REG0); | |
687 | ||
688 | /* Read BIA */ | |
689 | card->dev->addr_len = 6; | |
690 | for (i = 0; i < 6; i++) | |
691 | card->dev->dev_addr[i] = inb(ioaddr + MC_ROM_BIA_START + i); | |
692 | ||
693 | /* Restore original register values */ | |
694 | outb(reg0, ioaddr + MC_CONTROL_REG0); | |
695 | outb(reg1, ioaddr + MC_CONTROL_REG1); | |
696 | ||
697 | return; | |
698 | } | |
699 | ||
700 | static int madgemc_open(struct net_device *dev) | |
701 | { | |
702 | /* | |
703 | * Go ahead and reinitialize the chipset again, just to | |
704 | * make sure we didn't get left in a bad state. | |
705 | */ | |
706 | madgemc_chipset_init(dev); | |
707 | tms380tr_open(dev); | |
708 | return 0; | |
709 | } | |
710 | ||
711 | static int madgemc_close(struct net_device *dev) | |
712 | { | |
713 | tms380tr_close(dev); | |
714 | madgemc_chipset_close(dev); | |
715 | return 0; | |
716 | } | |
717 | ||
718 | /* | |
719 | * Give some details available from /proc/mca/slotX | |
720 | */ | |
721 | static int madgemc_mcaproc(char *buf, int slot, void *d) | |
722 | { | |
723 | struct net_device *dev = (struct net_device *)d; | |
724 | struct madgemc_card *curcard = madgemc_card_list; | |
725 | int len = 0; | |
726 | ||
727 | while (curcard) { /* search for card struct */ | |
728 | if (curcard->dev == dev) | |
729 | break; | |
730 | curcard = curcard->next; | |
731 | } | |
732 | len += sprintf(buf+len, "-------\n"); | |
733 | if (curcard) { | |
734 | struct net_local *tp = netdev_priv(dev); | |
735 | int i; | |
736 | ||
737 | len += sprintf(buf+len, "Card Revision: %d\n", curcard->cardrev); | |
738 | len += sprintf(buf+len, "RAM Size: %dkb\n", curcard->ramsize); | |
739 | len += sprintf(buf+len, "Cable type: %s\n", (curcard->cabletype)?"STP/DB9":"UTP/RJ-45"); | |
740 | len += sprintf(buf+len, "Configured ring speed: %dMb/sec\n", (curcard->ringspeed)?16:4); | |
741 | len += sprintf(buf+len, "Running ring speed: %dMb/sec\n", (tp->DataRate==SPEED_16)?16:4); | |
742 | len += sprintf(buf+len, "Device: %s\n", dev->name); | |
743 | len += sprintf(buf+len, "IO Port: 0x%04lx\n", dev->base_addr); | |
744 | len += sprintf(buf+len, "IRQ: %d\n", dev->irq); | |
745 | len += sprintf(buf+len, "Arbitration Level: %d\n", curcard->arblevel); | |
746 | len += sprintf(buf+len, "Burst Mode: "); | |
747 | switch(curcard->burstmode) { | |
748 | case 0: len += sprintf(buf+len, "Cycle steal"); break; | |
749 | case 1: len += sprintf(buf+len, "Limited burst"); break; | |
750 | case 2: len += sprintf(buf+len, "Delayed release"); break; | |
751 | case 3: len += sprintf(buf+len, "Immediate release"); break; | |
752 | } | |
753 | len += sprintf(buf+len, " (%s)\n", (curcard->fairness)?"Unfair":"Fair"); | |
754 | ||
755 | len += sprintf(buf+len, "Ring Station Address: "); | |
756 | len += sprintf(buf+len, "%2.2x", dev->dev_addr[0]); | |
757 | for (i = 1; i < 6; i++) | |
758 | len += sprintf(buf+len, " %2.2x", dev->dev_addr[i]); | |
759 | len += sprintf(buf+len, "\n"); | |
760 | } else | |
761 | len += sprintf(buf+len, "Card not configured\n"); | |
762 | ||
763 | return len; | |
764 | } | |
765 | ||
766 | static void __exit madgemc_exit(void) | |
767 | { | |
768 | struct net_device *dev; | |
769 | struct madgemc_card *this_card; | |
770 | ||
771 | while (madgemc_card_list) { | |
772 | dev = madgemc_card_list->dev; | |
773 | unregister_netdev(dev); | |
774 | release_region(dev->base_addr-MADGEMC_SIF_OFFSET, MADGEMC_IO_EXTENT); | |
775 | free_irq(dev->irq, dev); | |
776 | tmsdev_term(dev); | |
777 | free_netdev(dev); | |
778 | this_card = madgemc_card_list; | |
779 | madgemc_card_list = this_card->next; | |
780 | kfree(this_card); | |
781 | } | |
782 | } | |
783 | ||
784 | module_init(madgemc_probe); | |
785 | module_exit(madgemc_exit); | |
786 | ||
787 | MODULE_LICENSE("GPL"); | |
788 | ||
789 | \f | |
790 | /* | |
791 | * Local variables: | |
792 | * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c madgemc.c" | |
793 | * alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c madgemc.c" | |
794 | * c-set-style "K&R" | |
795 | * c-indent-level: 8 | |
796 | * c-basic-offset: 8 | |
797 | * tab-width: 8 | |
798 | * End: | |
799 | */ | |
800 |