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 */ 22static 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. */ 44static 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 */ 52static 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. */ 58static int dmalist[] __initdata = { 59 5, 6, 7, 60 0 61}; 62 63static char isa_cardname[] = "SK NET TR 4/16 ISA\0"; 64 65int tms_isa_probe(struct net_device *dev); 66static int tms_isa_open(struct net_device *dev); 67static int tms_isa_close(struct net_device *dev); 68static void tms_isa_read_eeprom(struct net_device *dev); 69static unsigned short tms_isa_setnselout_pins(struct net_device *dev); 70 71static unsigned short tms_isa_sifreadb(struct net_device *dev, unsigned short reg) 72{ 73 return inb(dev->base_addr + reg); 74} 75 76static unsigned short tms_isa_sifreadw(struct net_device *dev, unsigned short reg) 77{ 78 return inw(dev->base_addr + reg); 79} 80 81static void tms_isa_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg) 82{ 83 outb(val, dev->base_addr + reg); 84} 85 86static void tms_isa_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg) 87{ 88 outw(val, dev->base_addr + reg); 89} 90 91struct tms_isa_card { 92 struct net_device *dev; 93 struct tms_isa_card *next; 94}; 95 96static struct tms_isa_card *tms_isa_card_list; 97 98static 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 130int __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 */ 308static 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 322unsigned short tms_isa_setnselout_pins(struct net_device *dev) 323{ 324 return 0; 325} 326 327static 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 360static 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 371static int io[ISATR_MAX_ADAPTERS]; 372static int irq[ISATR_MAX_ADAPTERS]; 373static int dma[ISATR_MAX_ADAPTERS]; 374 375MODULE_LICENSE("GPL"); 376 377MODULE_PARM(io, "1-" __MODULE_STRING(ISATR_MAX_ADAPTERS) "i"); 378MODULE_PARM(irq, "1-" __MODULE_STRING(ISATR_MAX_ADAPTERS) "i"); 379MODULE_PARM(dma, "1-" __MODULE_STRING(ISATR_MAX_ADAPTERS) "i"); 380 381int 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 443void 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