Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.18 557 lines 14 kB view raw
1/* 2 * This software may be used and distributed according to the terms 3 * of the GNU General Public License, incorporated herein by reference. 4 * 5 */ 6 7#include <linux/module.h> 8#include <linux/init.h> 9#include <linux/interrupt.h> 10#include <linux/delay.h> 11#include "includes.h" 12#include "hardware.h" 13#include "card.h" 14 15MODULE_DESCRIPTION("ISDN4Linux: Driver for Spellcaster card"); 16MODULE_AUTHOR("Spellcaster Telecommunications Inc."); 17MODULE_LICENSE("GPL"); 18 19board *sc_adapter[MAX_CARDS]; 20int cinst; 21 22static char devname[] = "scX"; 23static const char version[] = "2.0b1"; 24 25static const char *boardname[] = { "DataCommute/BRI", "DataCommute/PRI", "TeleCommute/BRI" }; 26 27/* insmod set parameters */ 28static unsigned int io[] = {0,0,0,0}; 29static unsigned char irq[] = {0,0,0,0}; 30static unsigned long ram[] = {0,0,0,0}; 31static int do_reset = 0; 32 33module_param_array(io, int, NULL, 0); 34module_param_array(irq, int, NULL, 0); 35module_param_array(ram, int, NULL, 0); 36module_param(do_reset, bool, 0); 37 38extern irqreturn_t interrupt_handler(int, void *, struct pt_regs *); 39extern int sndpkt(int, int, int, struct sk_buff *); 40extern int command(isdn_ctrl *); 41extern int indicate_status(int, int, ulong, char*); 42extern int reset(int); 43 44static int identify_board(unsigned long, unsigned int); 45 46static int __init sc_init(void) 47{ 48 int b = -1; 49 int i, j; 50 int status = -ENODEV; 51 52 unsigned long memsize = 0; 53 unsigned long features = 0; 54 isdn_if *interface; 55 unsigned char channels; 56 unsigned char pgport; 57 unsigned long magic; 58 int model; 59 int last_base = IOBASE_MIN; 60 int probe_exhasted = 0; 61 62#ifdef MODULE 63 pr_info("SpellCaster ISA ISDN Adapter Driver rev. %s Loaded\n", version); 64#else 65 pr_info("SpellCaster ISA ISDN Adapter Driver rev. %s\n", version); 66#endif 67 pr_info("Copyright (C) 1996 SpellCaster Telecommunications Inc.\n"); 68 69 while(b++ < MAX_CARDS - 1) { 70 pr_debug("Probing for adapter #%d\n", b); 71 /* 72 * Initialize reusable variables 73 */ 74 model = -1; 75 magic = 0; 76 channels = 0; 77 pgport = 0; 78 79 /* 80 * See if we should probe for IO base 81 */ 82 pr_debug("I/O Base for board %d is 0x%x, %s probe\n", b, io[b], 83 io[b] == 0 ? "will" : "won't"); 84 if(io[b]) { 85 /* 86 * No, I/O Base has been provided 87 */ 88 for (i = 0 ; i < MAX_IO_REGS - 1 ; i++) { 89 if(!request_region(io[b] + i * 0x400, 1, "sc test")) { 90 pr_debug("request_region for 0x%x failed\n", io[b] + i * 0x400); 91 io[b] = 0; 92 break; 93 } else 94 release_region(io[b] + i * 0x400, 1); 95 } 96 97 /* 98 * Confirm the I/O Address with a test 99 */ 100 if(io[b] == 0) { 101 pr_debug("I/O Address 0x%x is in use.\n"); 102 continue; 103 } 104 105 outb(0x18, io[b] + 0x400 * EXP_PAGE0); 106 if(inb(io[b] + 0x400 * EXP_PAGE0) != 0x18) { 107 pr_debug("I/O Base 0x%x fails test\n"); 108 continue; 109 } 110 } 111 else { 112 /* 113 * Yes, probe for I/O Base 114 */ 115 if(probe_exhasted) { 116 pr_debug("All probe addresses exhasted, skipping\n"); 117 continue; 118 } 119 pr_debug("Probing for I/O...\n"); 120 for (i = last_base ; i <= IOBASE_MAX ; i += IOBASE_OFFSET) { 121 int found_io = 1; 122 if (i == IOBASE_MAX) { 123 probe_exhasted = 1; /* No more addresses to probe */ 124 pr_debug("End of Probes\n"); 125 } 126 last_base = i + IOBASE_OFFSET; 127 pr_debug(" checking 0x%x...", i); 128 for ( j = 0 ; j < MAX_IO_REGS - 1 ; j++) { 129 if(!request_region(i + j * 0x400, 1, "sc test")) { 130 pr_debug("Failed\n"); 131 found_io = 0; 132 break; 133 } else 134 release_region(i + j * 0x400, 1); 135 } 136 137 if(found_io) { 138 io[b] = i; 139 outb(0x18, io[b] + 0x400 * EXP_PAGE0); 140 if(inb(io[b] + 0x400 * EXP_PAGE0) != 0x18) { 141 pr_debug("Failed by test\n"); 142 continue; 143 } 144 pr_debug("Passed\n"); 145 break; 146 } 147 } 148 if(probe_exhasted) { 149 continue; 150 } 151 } 152 153 /* 154 * See if we should probe for shared RAM 155 */ 156 if(do_reset) { 157 pr_debug("Doing a SAFE probe reset\n"); 158 outb(0xFF, io[b] + RESET_OFFSET); 159 msleep_interruptible(10000); 160 } 161 pr_debug("RAM Base for board %d is 0x%x, %s probe\n", b, ram[b], 162 ram[b] == 0 ? "will" : "won't"); 163 164 if(ram[b]) { 165 /* 166 * No, the RAM base has been provided 167 * Just look for a signature and ID the 168 * board model 169 */ 170 if(request_region(ram[b], SRAM_PAGESIZE, "sc test")) { 171 pr_debug("request_region for RAM base 0x%x succeeded\n", ram[b]); 172 model = identify_board(ram[b], io[b]); 173 release_region(ram[b], SRAM_PAGESIZE); 174 } 175 } 176 else { 177 /* 178 * Yes, probe for free RAM and look for 179 * a signature and id the board model 180 */ 181 for (i = SRAM_MIN ; i < SRAM_MAX ; i += SRAM_PAGESIZE) { 182 pr_debug("Checking RAM address 0x%x...\n", i); 183 if(request_region(i, SRAM_PAGESIZE, "sc test")) { 184 pr_debug(" request_region succeeded\n"); 185 model = identify_board(i, io[b]); 186 release_region(i, SRAM_PAGESIZE); 187 if (model >= 0) { 188 pr_debug(" Identified a %s\n", 189 boardname[model]); 190 ram[b] = i; 191 break; 192 } 193 pr_debug(" Unidentifed or inaccessible\n"); 194 continue; 195 } 196 pr_debug(" request failed\n"); 197 } 198 } 199 /* 200 * See if we found free RAM and the board model 201 */ 202 if(!ram[b] || model < 0) { 203 /* 204 * Nope, there was no place in RAM for the 205 * board, or it couldn't be identified 206 */ 207 pr_debug("Failed to find an adapter at 0x%x\n", ram[b]); 208 continue; 209 } 210 211 /* 212 * Set the board's magic number, memory size and page register 213 */ 214 switch(model) { 215 case PRI_BOARD: 216 channels = 23; 217 magic = 0x20000; 218 memsize = 0x100000; 219 features = PRI_FEATURES; 220 break; 221 222 case BRI_BOARD: 223 case POTS_BOARD: 224 channels = 2; 225 magic = 0x60000; 226 memsize = 0x10000; 227 features = BRI_FEATURES; 228 break; 229 } 230 switch(ram[b] >> 12 & 0x0F) { 231 case 0x0: 232 pr_debug("RAM Page register set to EXP_PAGE0\n"); 233 pgport = EXP_PAGE0; 234 break; 235 236 case 0x4: 237 pr_debug("RAM Page register set to EXP_PAGE1\n"); 238 pgport = EXP_PAGE1; 239 break; 240 241 case 0x8: 242 pr_debug("RAM Page register set to EXP_PAGE2\n"); 243 pgport = EXP_PAGE2; 244 break; 245 246 case 0xC: 247 pr_debug("RAM Page register set to EXP_PAGE3\n"); 248 pgport = EXP_PAGE3; 249 break; 250 251 default: 252 pr_debug("RAM base address doesn't fall on 16K boundary\n"); 253 continue; 254 } 255 256 pr_debug("current IRQ: %d b: %d\n",irq[b],b); 257 258 /* 259 * Make sure we got an IRQ 260 */ 261 if(!irq[b]) { 262 /* 263 * No interrupt could be used 264 */ 265 pr_debug("Failed to acquire an IRQ line\n"); 266 continue; 267 } 268 269 /* 270 * Horray! We found a board, Make sure we can register 271 * it with ISDN4Linux 272 */ 273 interface = kmalloc(sizeof(isdn_if), GFP_KERNEL); 274 if (interface == NULL) { 275 /* 276 * Oops, can't malloc isdn_if 277 */ 278 continue; 279 } 280 memset(interface, 0, sizeof(isdn_if)); 281 282 interface->owner = THIS_MODULE; 283 interface->hl_hdrlen = 0; 284 interface->channels = channels; 285 interface->maxbufsize = BUFFER_SIZE; 286 interface->features = features; 287 interface->writebuf_skb = sndpkt; 288 interface->writecmd = NULL; 289 interface->command = command; 290 strcpy(interface->id, devname); 291 interface->id[2] = '0' + cinst; 292 293 /* 294 * Allocate the board structure 295 */ 296 sc_adapter[cinst] = kmalloc(sizeof(board), GFP_KERNEL); 297 if (sc_adapter[cinst] == NULL) { 298 /* 299 * Oops, can't alloc memory for the board 300 */ 301 kfree(interface); 302 continue; 303 } 304 memset(sc_adapter[cinst], 0, sizeof(board)); 305 spin_lock_init(&sc_adapter[cinst]->lock); 306 307 if(!register_isdn(interface)) { 308 /* 309 * Oops, couldn't register for some reason 310 */ 311 kfree(interface); 312 kfree(sc_adapter[cinst]); 313 continue; 314 } 315 316 sc_adapter[cinst]->card = interface; 317 sc_adapter[cinst]->driverId = interface->channels; 318 strcpy(sc_adapter[cinst]->devicename, interface->id); 319 sc_adapter[cinst]->nChannels = channels; 320 sc_adapter[cinst]->ramsize = memsize; 321 sc_adapter[cinst]->shmem_magic = magic; 322 sc_adapter[cinst]->shmem_pgport = pgport; 323 sc_adapter[cinst]->StartOnReset = 1; 324 325 /* 326 * Allocate channels status structures 327 */ 328 sc_adapter[cinst]->channel = kmalloc(sizeof(bchan) * channels, GFP_KERNEL); 329 if (sc_adapter[cinst]->channel == NULL) { 330 /* 331 * Oops, can't alloc memory for the channels 332 */ 333 indicate_status(cinst, ISDN_STAT_UNLOAD, 0, NULL); /* Fix me */ 334 kfree(interface); 335 kfree(sc_adapter[cinst]); 336 continue; 337 } 338 memset(sc_adapter[cinst]->channel, 0, sizeof(bchan) * channels); 339 340 /* 341 * Lock down the hardware resources 342 */ 343 sc_adapter[cinst]->interrupt = irq[b]; 344 if (request_irq(sc_adapter[cinst]->interrupt, interrupt_handler, 345 IRQF_DISABLED, interface->id, NULL)) 346 { 347 kfree(sc_adapter[cinst]->channel); 348 indicate_status(cinst, ISDN_STAT_UNLOAD, 0, NULL); /* Fix me */ 349 kfree(interface); 350 kfree(sc_adapter[cinst]); 351 continue; 352 353 } 354 sc_adapter[cinst]->iobase = io[b]; 355 for(i = 0 ; i < MAX_IO_REGS - 1 ; i++) { 356 sc_adapter[cinst]->ioport[i] = io[b] + i * 0x400; 357 request_region(sc_adapter[cinst]->ioport[i], 1, 358 interface->id); 359 pr_debug("Requesting I/O Port %#x\n", 360 sc_adapter[cinst]->ioport[i]); 361 } 362 sc_adapter[cinst]->ioport[IRQ_SELECT] = io[b] + 0x2; 363 request_region(sc_adapter[cinst]->ioport[IRQ_SELECT], 1, 364 interface->id); 365 pr_debug("Requesting I/O Port %#x\n", 366 sc_adapter[cinst]->ioport[IRQ_SELECT]); 367 sc_adapter[cinst]->rambase = ram[b]; 368 request_region(sc_adapter[cinst]->rambase, SRAM_PAGESIZE, 369 interface->id); 370 371 pr_info(" %s (%d) - %s %d channels IRQ %d, I/O Base 0x%x, RAM Base 0x%lx\n", 372 sc_adapter[cinst]->devicename, 373 sc_adapter[cinst]->driverId, 374 boardname[model], channels, irq[b], io[b], ram[b]); 375 376 /* 377 * reset the adapter to put things in motion 378 */ 379 reset(cinst); 380 381 cinst++; 382 status = 0; 383 } 384 if (status) 385 pr_info("Failed to find any adapters, driver unloaded\n"); 386 return status; 387} 388 389static void __exit sc_exit(void) 390{ 391 int i, j; 392 393 for(i = 0 ; i < cinst ; i++) { 394 pr_debug("Cleaning up after adapter %d\n", i); 395 /* 396 * kill the timers 397 */ 398 del_timer(&(sc_adapter[i]->reset_timer)); 399 del_timer(&(sc_adapter[i]->stat_timer)); 400 401 /* 402 * Tell I4L we're toast 403 */ 404 indicate_status(i, ISDN_STAT_STOP, 0, NULL); 405 indicate_status(i, ISDN_STAT_UNLOAD, 0, NULL); 406 407 /* 408 * Release shared RAM 409 */ 410 release_region(sc_adapter[i]->rambase, SRAM_PAGESIZE); 411 412 /* 413 * Release the IRQ 414 */ 415 FREE_IRQ(sc_adapter[i]->interrupt, NULL); 416 417 /* 418 * Reset for a clean start 419 */ 420 outb(0xFF, sc_adapter[i]->ioport[SFT_RESET]); 421 422 /* 423 * Release the I/O Port regions 424 */ 425 for(j = 0 ; j < MAX_IO_REGS - 1; j++) { 426 release_region(sc_adapter[i]->ioport[j], 1); 427 pr_debug("Releasing I/O Port %#x\n", 428 sc_adapter[i]->ioport[j]); 429 } 430 release_region(sc_adapter[i]->ioport[IRQ_SELECT], 1); 431 pr_debug("Releasing I/O Port %#x\n", 432 sc_adapter[i]->ioport[IRQ_SELECT]); 433 434 /* 435 * Release any memory we alloced 436 */ 437 kfree(sc_adapter[i]->channel); 438 kfree(sc_adapter[i]->card); 439 kfree(sc_adapter[i]); 440 } 441 pr_info("SpellCaster ISA ISDN Adapter Driver Unloaded.\n"); 442} 443 444static int identify_board(unsigned long rambase, unsigned int iobase) 445{ 446 unsigned int pgport; 447 unsigned long sig; 448 DualPortMemory *dpm; 449 RspMessage rcvmsg; 450 ReqMessage sndmsg; 451 HWConfig_pl hwci; 452 int x; 453 454 pr_debug("Attempting to identify adapter @ 0x%x io 0x%x\n", 455 rambase, iobase); 456 457 /* 458 * Enable the base pointer 459 */ 460 outb(rambase >> 12, iobase + 0x2c00); 461 462 switch(rambase >> 12 & 0x0F) { 463 case 0x0: 464 pgport = iobase + PG0_OFFSET; 465 pr_debug("Page Register offset is 0x%x\n", PG0_OFFSET); 466 break; 467 468 case 0x4: 469 pgport = iobase + PG1_OFFSET; 470 pr_debug("Page Register offset is 0x%x\n", PG1_OFFSET); 471 break; 472 473 case 0x8: 474 pgport = iobase + PG2_OFFSET; 475 pr_debug("Page Register offset is 0x%x\n", PG2_OFFSET); 476 break; 477 478 case 0xC: 479 pgport = iobase + PG3_OFFSET; 480 pr_debug("Page Register offset is 0x%x\n", PG3_OFFSET); 481 break; 482 default: 483 pr_debug("Invalid rambase 0x%lx\n", rambase); 484 return -1; 485 } 486 487 /* 488 * Try to identify a PRI card 489 */ 490 outb(PRI_BASEPG_VAL, pgport); 491 msleep_interruptible(1000); 492 sig = readl(rambase + SIG_OFFSET); 493 pr_debug("Looking for a signature, got 0x%x\n", sig); 494 if(sig == SIGNATURE) 495 return PRI_BOARD; 496 497 /* 498 * Try to identify a PRI card 499 */ 500 outb(BRI_BASEPG_VAL, pgport); 501 msleep_interruptible(1000); 502 sig = readl(rambase + SIG_OFFSET); 503 pr_debug("Looking for a signature, got 0x%x\n", sig); 504 if(sig == SIGNATURE) 505 return BRI_BOARD; 506 507 return -1; 508 509 /* 510 * Try to spot a card 511 */ 512 sig = readl(rambase + SIG_OFFSET); 513 pr_debug("Looking for a signature, got 0x%x\n", sig); 514 if(sig != SIGNATURE) 515 return -1; 516 517 dpm = (DualPortMemory *) rambase; 518 519 memset(&sndmsg, 0, MSG_LEN); 520 sndmsg.msg_byte_cnt = 3; 521 sndmsg.type = cmReqType1; 522 sndmsg.class = cmReqClass0; 523 sndmsg.code = cmReqHWConfig; 524 memcpy_toio(&(dpm->req_queue[dpm->req_head++]), &sndmsg, MSG_LEN); 525 outb(0, iobase + 0x400); 526 pr_debug("Sent HWConfig message\n"); 527 /* 528 * Wait for the response 529 */ 530 x = 0; 531 while((inb(iobase + FIFOSTAT_OFFSET) & RF_HAS_DATA) && x < 100) { 532 schedule_timeout_interruptible(1); 533 x++; 534 } 535 if(x == 100) { 536 pr_debug("Timeout waiting for response\n"); 537 return -1; 538 } 539 540 memcpy_fromio(&rcvmsg, &(dpm->rsp_queue[dpm->rsp_tail]), MSG_LEN); 541 pr_debug("Got HWConfig response, status = 0x%x\n", rcvmsg.rsp_status); 542 memcpy(&hwci, &(rcvmsg.msg_data.HWCresponse), sizeof(HWConfig_pl)); 543 pr_debug("Hardware Config: Interface: %s, RAM Size: %d, Serial: %s\n" 544 " Part: %s, Rev: %s\n", 545 hwci.st_u_sense ? "S/T" : "U", hwci.ram_size, 546 hwci.serial_no, hwci.part_no, hwci.rev_no); 547 548 if(!strncmp(PRI_PARTNO, hwci.part_no, 6)) 549 return PRI_BOARD; 550 if(!strncmp(BRI_PARTNO, hwci.part_no, 6)) 551 return BRI_BOARD; 552 553 return -1; 554} 555 556module_init(sc_init); 557module_exit(sc_exit);