diff options
Diffstat (limited to 'drivers/char/ip2/ip2main.c')
-rw-r--r-- | drivers/char/ip2/ip2main.c | 550 |
1 files changed, 286 insertions, 264 deletions
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 689f9dcd3b86..6774572d3759 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c | |||
@@ -150,15 +150,12 @@ static int ip2_read_proc(char *, char **, off_t, int, int *, void * ); | |||
150 | /*************/ | 150 | /*************/ |
151 | 151 | ||
152 | /* String constants to identify ourselves */ | 152 | /* String constants to identify ourselves */ |
153 | static char *pcName = "Computone IntelliPort Plus multiport driver"; | 153 | static const char pcName[] = "Computone IntelliPort Plus multiport driver"; |
154 | static char *pcVersion = "1.2.14"; | 154 | static const char pcVersion[] = "1.2.14"; |
155 | 155 | ||
156 | /* String constants for port names */ | 156 | /* String constants for port names */ |
157 | static char *pcDriver_name = "ip2"; | 157 | static const char pcDriver_name[] = "ip2"; |
158 | static char *pcIpl = "ip2ipl"; | 158 | static const char pcIpl[] = "ip2ipl"; |
159 | |||
160 | // cheezy kludge or genius - you decide? | ||
161 | int ip2_loadmain(int *, int *); | ||
162 | 159 | ||
163 | /***********************/ | 160 | /***********************/ |
164 | /* Function Prototypes */ | 161 | /* Function Prototypes */ |
@@ -240,8 +237,8 @@ static const struct file_operations ip2_ipl = { | |||
240 | .open = ip2_ipl_open, | 237 | .open = ip2_ipl_open, |
241 | }; | 238 | }; |
242 | 239 | ||
243 | static unsigned long irq_counter = 0; | 240 | static unsigned long irq_counter; |
244 | static unsigned long bh_counter = 0; | 241 | static unsigned long bh_counter; |
245 | 242 | ||
246 | // Use immediate queue to service interrupts | 243 | // Use immediate queue to service interrupts |
247 | #define USE_IQI | 244 | #define USE_IQI |
@@ -252,7 +249,6 @@ static unsigned long bh_counter = 0; | |||
252 | */ | 249 | */ |
253 | #define POLL_TIMEOUT (jiffies + 1) | 250 | #define POLL_TIMEOUT (jiffies + 1) |
254 | static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0); | 251 | static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0); |
255 | static char TimerOn; | ||
256 | 252 | ||
257 | #ifdef IP2DEBUG_TRACE | 253 | #ifdef IP2DEBUG_TRACE |
258 | /* Trace (debug) buffer data */ | 254 | /* Trace (debug) buffer data */ |
@@ -268,8 +264,8 @@ static int tracewrap; | |||
268 | /**********/ | 264 | /**********/ |
269 | 265 | ||
270 | #if defined(MODULE) && defined(IP2DEBUG_OPEN) | 266 | #if defined(MODULE) && defined(IP2DEBUG_OPEN) |
271 | #define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, ttyc=%d, modc=%x -> %s\n", \ | 267 | #define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \ |
272 | tty->name,(pCh->flags),ip2_tty_driver->refcount, \ | 268 | tty->name,(pCh->flags), \ |
273 | tty->count,/*GET_USE_COUNT(module)*/0,s) | 269 | tty->count,/*GET_USE_COUNT(module)*/0,s) |
274 | #else | 270 | #else |
275 | #define DBG_CNT(s) | 271 | #define DBG_CNT(s) |
@@ -287,8 +283,9 @@ static int tracewrap; | |||
287 | 283 | ||
288 | MODULE_AUTHOR("Doug McNash"); | 284 | MODULE_AUTHOR("Doug McNash"); |
289 | MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); | 285 | MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); |
286 | MODULE_LICENSE("GPL"); | ||
290 | 287 | ||
291 | static int poll_only = 0; | 288 | static int poll_only; |
292 | 289 | ||
293 | static int Eisa_irq; | 290 | static int Eisa_irq; |
294 | static int Eisa_slot; | 291 | static int Eisa_slot; |
@@ -297,34 +294,46 @@ static int iindx; | |||
297 | static char rirqs[IP2_MAX_BOARDS]; | 294 | static char rirqs[IP2_MAX_BOARDS]; |
298 | static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0}; | 295 | static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0}; |
299 | 296 | ||
297 | /* Note: Add compiled in defaults to these arrays, not to the structure | ||
298 | in ip2.h any longer. That structure WILL get overridden | ||
299 | by these values, or command line values, or insmod values!!! =mhw= | ||
300 | */ | ||
301 | static int io[IP2_MAX_BOARDS]; | ||
302 | static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 }; | ||
303 | |||
304 | MODULE_AUTHOR("Doug McNash"); | ||
305 | MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); | ||
306 | module_param_array(irq, int, NULL, 0); | ||
307 | MODULE_PARM_DESC(irq, "Interrupts for IntelliPort Cards"); | ||
308 | module_param_array(io, int, NULL, 0); | ||
309 | MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards"); | ||
310 | module_param(poll_only, bool, 0); | ||
311 | MODULE_PARM_DESC(poll_only, "Do not use card interrupts"); | ||
312 | |||
300 | /* for sysfs class support */ | 313 | /* for sysfs class support */ |
301 | static struct class *ip2_class; | 314 | static struct class *ip2_class; |
302 | 315 | ||
303 | // Some functions to keep track of what irq's we have | 316 | /* Some functions to keep track of what irqs we have */ |
304 | 317 | ||
305 | static int | 318 | static int __init is_valid_irq(int irq) |
306 | is_valid_irq(int irq) | ||
307 | { | 319 | { |
308 | int *i = Valid_Irqs; | 320 | int *i = Valid_Irqs; |
309 | 321 | ||
310 | while ((*i != 0) && (*i != irq)) { | 322 | while (*i != 0 && *i != irq) |
311 | i++; | 323 | i++; |
312 | } | 324 | |
313 | return (*i); | 325 | return *i; |
314 | } | 326 | } |
315 | 327 | ||
316 | static void | 328 | static void __init mark_requested_irq(char irq) |
317 | mark_requested_irq( char irq ) | ||
318 | { | 329 | { |
319 | rirqs[iindx++] = irq; | 330 | rirqs[iindx++] = irq; |
320 | } | 331 | } |
321 | 332 | ||
322 | #ifdef MODULE | 333 | static int __exit clear_requested_irq(char irq) |
323 | static int | ||
324 | clear_requested_irq( char irq ) | ||
325 | { | 334 | { |
326 | int i; | 335 | int i; |
327 | for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 336 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { |
328 | if (rirqs[i] == irq) { | 337 | if (rirqs[i] == irq) { |
329 | rirqs[i] = 0; | 338 | rirqs[i] = 0; |
330 | return 1; | 339 | return 1; |
@@ -332,17 +341,15 @@ clear_requested_irq( char irq ) | |||
332 | } | 341 | } |
333 | return 0; | 342 | return 0; |
334 | } | 343 | } |
335 | #endif | ||
336 | 344 | ||
337 | static int | 345 | static int have_requested_irq(char irq) |
338 | have_requested_irq( char irq ) | ||
339 | { | 346 | { |
340 | // array init to zeros so 0 irq will not be requested as a side effect | 347 | /* array init to zeros so 0 irq will not be requested as a side |
348 | * effect */ | ||
341 | int i; | 349 | int i; |
342 | for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 350 | for (i = 0; i < IP2_MAX_BOARDS; ++i) |
343 | if (rirqs[i] == irq) | 351 | if (rirqs[i] == irq) |
344 | return 1; | 352 | return 1; |
345 | } | ||
346 | return 0; | 353 | return 0; |
347 | } | 354 | } |
348 | 355 | ||
@@ -361,53 +368,45 @@ have_requested_irq( char irq ) | |||
361 | /* handle subsequent installations of the driver. All memory allocated by the */ | 368 | /* handle subsequent installations of the driver. All memory allocated by the */ |
362 | /* driver should be returned since it may be unloaded from memory. */ | 369 | /* driver should be returned since it may be unloaded from memory. */ |
363 | /******************************************************************************/ | 370 | /******************************************************************************/ |
364 | #ifdef MODULE | 371 | static void __exit ip2_cleanup_module(void) |
365 | void __exit | ||
366 | ip2_cleanup_module(void) | ||
367 | { | 372 | { |
368 | int err; | 373 | int err; |
369 | int i; | 374 | int i; |
370 | 375 | ||
371 | #ifdef IP2DEBUG_INIT | 376 | del_timer_sync(&PollTimer); |
372 | printk (KERN_DEBUG "Unloading %s: version %s\n", pcName, pcVersion ); | ||
373 | #endif | ||
374 | /* Stop poll timer if we had one. */ | ||
375 | if ( TimerOn ) { | ||
376 | del_timer ( &PollTimer ); | ||
377 | TimerOn = 0; | ||
378 | } | ||
379 | 377 | ||
380 | /* Reset the boards we have. */ | 378 | /* Reset the boards we have. */ |
381 | for( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 379 | for (i = 0; i < IP2_MAX_BOARDS; i++) |
382 | if ( i2BoardPtrTable[i] ) { | 380 | if (i2BoardPtrTable[i]) |
383 | iiReset( i2BoardPtrTable[i] ); | 381 | iiReset(i2BoardPtrTable[i]); |
384 | } | ||
385 | } | ||
386 | 382 | ||
387 | /* The following is done at most once, if any boards were installed. */ | 383 | /* The following is done at most once, if any boards were installed. */ |
388 | for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 384 | for (i = 0; i < IP2_MAX_BOARDS; i++) { |
389 | if ( i2BoardPtrTable[i] ) { | 385 | if (i2BoardPtrTable[i]) { |
390 | iiResetDelay( i2BoardPtrTable[i] ); | 386 | iiResetDelay(i2BoardPtrTable[i]); |
391 | /* free io addresses and Tibet */ | 387 | /* free io addresses and Tibet */ |
392 | release_region( ip2config.addr[i], 8 ); | 388 | release_region(ip2config.addr[i], 8); |
393 | device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i)); | 389 | device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i)); |
394 | device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1)); | 390 | device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, |
391 | 4 * i + 1)); | ||
395 | } | 392 | } |
396 | /* Disable and remove interrupt handler. */ | 393 | /* Disable and remove interrupt handler. */ |
397 | if ( (ip2config.irq[i] > 0) && have_requested_irq(ip2config.irq[i]) ) { | 394 | if (ip2config.irq[i] > 0 && |
398 | free_irq ( ip2config.irq[i], (void *)&pcName); | 395 | have_requested_irq(ip2config.irq[i])) { |
399 | clear_requested_irq( ip2config.irq[i]); | 396 | free_irq(ip2config.irq[i], (void *)&pcName); |
397 | clear_requested_irq(ip2config.irq[i]); | ||
400 | } | 398 | } |
401 | } | 399 | } |
402 | class_destroy(ip2_class); | 400 | class_destroy(ip2_class); |
403 | if ( ( err = tty_unregister_driver ( ip2_tty_driver ) ) ) { | 401 | err = tty_unregister_driver(ip2_tty_driver); |
404 | printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err); | 402 | if (err) |
405 | } | 403 | printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", |
404 | err); | ||
406 | put_tty_driver(ip2_tty_driver); | 405 | put_tty_driver(ip2_tty_driver); |
407 | unregister_chrdev(IP2_IPL_MAJOR, pcIpl); | 406 | unregister_chrdev(IP2_IPL_MAJOR, pcIpl); |
408 | remove_proc_entry("ip2mem", NULL); | 407 | remove_proc_entry("ip2mem", NULL); |
409 | 408 | ||
410 | // free memory | 409 | /* free memory */ |
411 | for (i = 0; i < IP2_MAX_BOARDS; i++) { | 410 | for (i = 0; i < IP2_MAX_BOARDS; i++) { |
412 | void *pB; | 411 | void *pB; |
413 | #ifdef CONFIG_PCI | 412 | #ifdef CONFIG_PCI |
@@ -417,24 +416,18 @@ ip2_cleanup_module(void) | |||
417 | ip2config.pci_dev[i] = NULL; | 416 | ip2config.pci_dev[i] = NULL; |
418 | } | 417 | } |
419 | #endif | 418 | #endif |
420 | if ((pB = i2BoardPtrTable[i]) != 0 ) { | 419 | pB = i2BoardPtrTable[i]; |
421 | kfree ( pB ); | 420 | if (pB != NULL) { |
421 | kfree(pB); | ||
422 | i2BoardPtrTable[i] = NULL; | 422 | i2BoardPtrTable[i] = NULL; |
423 | } | 423 | } |
424 | if ((DevTableMem[i]) != NULL ) { | 424 | if (DevTableMem[i] != NULL) { |
425 | kfree ( DevTableMem[i] ); | 425 | kfree(DevTableMem[i]); |
426 | DevTableMem[i] = NULL; | 426 | DevTableMem[i] = NULL; |
427 | } | 427 | } |
428 | } | 428 | } |
429 | |||
430 | /* Cleanup the iiEllis subsystem. */ | ||
431 | iiEllisCleanup(); | ||
432 | #ifdef IP2DEBUG_INIT | ||
433 | printk (KERN_DEBUG "IP2 Unloaded\n" ); | ||
434 | #endif | ||
435 | } | 429 | } |
436 | module_exit(ip2_cleanup_module); | 430 | module_exit(ip2_cleanup_module); |
437 | #endif /* MODULE */ | ||
438 | 431 | ||
439 | static const struct tty_operations ip2_ops = { | 432 | static const struct tty_operations ip2_ops = { |
440 | .open = ip2_open, | 433 | .open = ip2_open, |
@@ -494,139 +487,168 @@ static const struct firmware *ip2_request_firmware(void) | |||
494 | return fw; | 487 | return fw; |
495 | } | 488 | } |
496 | 489 | ||
497 | int | 490 | #ifndef MODULE |
498 | ip2_loadmain(int *iop, int *irqp) | 491 | /****************************************************************************** |
492 | * ip2_setup: | ||
493 | * str: kernel command line string | ||
494 | * | ||
495 | * Can't autoprobe the boards so user must specify configuration on | ||
496 | * kernel command line. Sane people build it modular but the others | ||
497 | * come here. | ||
498 | * | ||
499 | * Alternating pairs of io,irq for up to 4 boards. | ||
500 | * ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3 | ||
501 | * | ||
502 | * io=0 => No board | ||
503 | * io=1 => PCI | ||
504 | * io=2 => EISA | ||
505 | * else => ISA I/O address | ||
506 | * | ||
507 | * irq=0 or invalid for ISA will revert to polling mode | ||
508 | * | ||
509 | * Any value = -1, do not overwrite compiled in value. | ||
510 | * | ||
511 | ******************************************************************************/ | ||
512 | static int __init ip2_setup(char *str) | ||
513 | { | ||
514 | int j, ints[10]; /* 4 boards, 2 parameters + 2 */ | ||
515 | unsigned int i; | ||
516 | |||
517 | str = get_options(str, ARRAY_SIZE(ints), ints); | ||
518 | |||
519 | for (i = 0, j = 1; i < 4; i++) { | ||
520 | if (j > ints[0]) | ||
521 | break; | ||
522 | if (ints[j] >= 0) | ||
523 | io[i] = ints[j]; | ||
524 | j++; | ||
525 | if (j > ints[0]) | ||
526 | break; | ||
527 | if (ints[j] >= 0) | ||
528 | irq[i] = ints[j]; | ||
529 | j++; | ||
530 | } | ||
531 | return 1; | ||
532 | } | ||
533 | __setup("ip2=", ip2_setup); | ||
534 | #endif /* !MODULE */ | ||
535 | |||
536 | static int __init ip2_loadmain(void) | ||
499 | { | 537 | { |
500 | int i, j, box; | 538 | int i, j, box; |
501 | int err = 0; | 539 | int err = 0; |
502 | static int loaded; | ||
503 | i2eBordStrPtr pB = NULL; | 540 | i2eBordStrPtr pB = NULL; |
504 | int rc = -1; | 541 | int rc = -1; |
505 | static struct pci_dev *pci_dev_i = NULL; | 542 | struct pci_dev *pdev = NULL; |
506 | const struct firmware *fw = NULL; | 543 | const struct firmware *fw = NULL; |
507 | 544 | ||
508 | ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0 ); | 545 | if (poll_only) { |
546 | /* Hard lock the interrupts to zero */ | ||
547 | irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0; | ||
548 | } | ||
549 | |||
550 | ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0); | ||
509 | 551 | ||
510 | /* process command line arguments to modprobe or | 552 | /* process command line arguments to modprobe or |
511 | insmod i.e. iop & irqp */ | 553 | insmod i.e. iop & irqp */ |
512 | /* irqp and iop should ALWAYS be specified now... But we check | 554 | /* irqp and iop should ALWAYS be specified now... But we check |
513 | them individually just to be sure, anyways... */ | 555 | them individually just to be sure, anyways... */ |
514 | for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 556 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { |
515 | if (iop) { | 557 | ip2config.addr[i] = io[i]; |
516 | ip2config.addr[i] = iop[i]; | 558 | if (irq[i] >= 0) |
517 | if (irqp) { | 559 | ip2config.irq[i] = irq[i]; |
518 | if( irqp[i] >= 0 ) { | 560 | else |
519 | ip2config.irq[i] = irqp[i]; | 561 | ip2config.irq[i] = 0; |
520 | } else { | 562 | /* This is a little bit of a hack. If poll_only=1 on command |
521 | ip2config.irq[i] = 0; | 563 | line back in ip2.c OR all IRQs on all specified boards are |
522 | } | 564 | explicitly set to 0, then drop to poll only mode and override |
523 | // This is a little bit of a hack. If poll_only=1 on command | 565 | PCI or EISA interrupts. This superceeds the old hack of |
524 | // line back in ip2.c OR all IRQs on all specified boards are | 566 | triggering if all interrupts were zero (like da default). |
525 | // explicitly set to 0, then drop to poll only mode and override | 567 | Still a hack but less prone to random acts of terrorism. |
526 | // PCI or EISA interrupts. This superceeds the old hack of | 568 | |
527 | // triggering if all interrupts were zero (like da default). | 569 | What we really should do, now that the IRQ default is set |
528 | // Still a hack but less prone to random acts of terrorism. | 570 | to -1, is to use 0 as a hard coded, do not probe. |
529 | // | 571 | |
530 | // What we really should do, now that the IRQ default is set | 572 | /\/\|=mhw=|\/\/ |
531 | // to -1, is to use 0 as a hard coded, do not probe. | 573 | */ |
532 | // | 574 | poll_only |= irq[i]; |
533 | // /\/\|=mhw=|\/\/ | ||
534 | poll_only |= irqp[i]; | ||
535 | } | ||
536 | } | ||
537 | } | 575 | } |
538 | poll_only = !poll_only; | 576 | poll_only = !poll_only; |
539 | 577 | ||
540 | /* Announce our presence */ | 578 | /* Announce our presence */ |
541 | printk( KERN_INFO "%s version %s\n", pcName, pcVersion ); | 579 | printk(KERN_INFO "%s version %s\n", pcName, pcVersion); |
542 | |||
543 | // ip2 can be unloaded and reloaded for no good reason | ||
544 | // we can't let that happen here or bad things happen | ||
545 | // second load hoses board but not system - fixme later | ||
546 | if (loaded) { | ||
547 | printk( KERN_INFO "Still loaded\n" ); | ||
548 | return 0; | ||
549 | } | ||
550 | loaded++; | ||
551 | 580 | ||
552 | ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS); | 581 | ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS); |
553 | if (!ip2_tty_driver) | 582 | if (!ip2_tty_driver) |
554 | return -ENOMEM; | 583 | return -ENOMEM; |
555 | 584 | ||
556 | /* Initialise the iiEllis subsystem. */ | ||
557 | iiEllisInit(); | ||
558 | |||
559 | /* Initialize arrays. */ | ||
560 | memset( i2BoardPtrTable, 0, sizeof i2BoardPtrTable ); | ||
561 | memset( DevTable, 0, sizeof DevTable ); | ||
562 | |||
563 | /* Initialise all the boards we can find (up to the maximum). */ | 585 | /* Initialise all the boards we can find (up to the maximum). */ |
564 | for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 586 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { |
565 | switch ( ip2config.addr[i] ) { | 587 | switch (ip2config.addr[i]) { |
566 | case 0: /* skip this slot even if card is present */ | 588 | case 0: /* skip this slot even if card is present */ |
567 | break; | 589 | break; |
568 | default: /* ISA */ | 590 | default: /* ISA */ |
569 | /* ISA address must be specified */ | 591 | /* ISA address must be specified */ |
570 | if ( (ip2config.addr[i] < 0x100) || (ip2config.addr[i] > 0x3f8) ) { | 592 | if (ip2config.addr[i] < 0x100 || |
571 | printk ( KERN_ERR "IP2: Bad ISA board %d address %x\n", | 593 | ip2config.addr[i] > 0x3f8) { |
572 | i, ip2config.addr[i] ); | 594 | printk(KERN_ERR "IP2: Bad ISA board %d " |
595 | "address %x\n", i, | ||
596 | ip2config.addr[i]); | ||
573 | ip2config.addr[i] = 0; | 597 | ip2config.addr[i] = 0; |
574 | } else { | 598 | break; |
575 | ip2config.type[i] = ISA; | 599 | } |
576 | 600 | ip2config.type[i] = ISA; | |
577 | /* Check for valid irq argument, set for polling if invalid */ | 601 | |
578 | if (ip2config.irq[i] && !is_valid_irq(ip2config.irq[i])) { | 602 | /* Check for valid irq argument, set for polling if |
579 | printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",ip2config.irq[i]); | 603 | * invalid */ |
580 | ip2config.irq[i] = 0;// 0 is polling and is valid in that sense | 604 | if (ip2config.irq[i] && |
581 | } | 605 | !is_valid_irq(ip2config.irq[i])) { |
606 | printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n", | ||
607 | ip2config.irq[i]); | ||
608 | /* 0 is polling and is valid in that sense */ | ||
609 | ip2config.irq[i] = 0; | ||
582 | } | 610 | } |
583 | break; | 611 | break; |
584 | case PCI: | 612 | case PCI: |
585 | #ifdef CONFIG_PCI | 613 | #ifdef CONFIG_PCI |
586 | { | 614 | { |
587 | int status; | 615 | u32 addr; |
616 | int status; | ||
588 | 617 | ||
589 | pci_dev_i = pci_get_device(PCI_VENDOR_ID_COMPUTONE, | 618 | pdev = pci_get_device(PCI_VENDOR_ID_COMPUTONE, |
590 | PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i); | 619 | PCI_DEVICE_ID_COMPUTONE_IP2EX, pdev); |
591 | if (pci_dev_i != NULL) { | 620 | if (pdev == NULL) { |
592 | unsigned int addr; | 621 | ip2config.addr[i] = 0; |
593 | 622 | printk(KERN_ERR "IP2: PCI board %d not " | |
594 | if (pci_enable_device(pci_dev_i)) { | 623 | "found\n", i); |
595 | printk( KERN_ERR "IP2: can't enable PCI device at %s\n", | 624 | break; |
596 | pci_name(pci_dev_i)); | 625 | } |
597 | break; | ||
598 | } | ||
599 | ip2config.type[i] = PCI; | ||
600 | ip2config.pci_dev[i] = pci_dev_get(pci_dev_i); | ||
601 | status = | ||
602 | pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr); | ||
603 | if ( addr & 1 ) { | ||
604 | ip2config.addr[i]=(USHORT)(addr&0xfffe); | ||
605 | } else { | ||
606 | printk( KERN_ERR "IP2: PCI I/O address error\n"); | ||
607 | } | ||
608 | 626 | ||
609 | // If the PCI BIOS assigned it, lets try and use it. If we | 627 | if (pci_enable_device(pdev)) { |
610 | // can't acquire it or it screws up, deal with it then. | 628 | dev_err(&pdev->dev, "can't enable device\n"); |
611 | 629 | break; | |
612 | // if (!is_valid_irq(pci_irq)) { | ||
613 | // printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq); | ||
614 | // pci_irq = 0; | ||
615 | // } | ||
616 | ip2config.irq[i] = pci_dev_i->irq; | ||
617 | } else { // ann error | ||
618 | ip2config.addr[i] = 0; | ||
619 | printk(KERN_ERR "IP2: PCI board %d not found\n", i); | ||
620 | } | ||
621 | } | 630 | } |
631 | ip2config.type[i] = PCI; | ||
632 | ip2config.pci_dev[i] = pci_dev_get(pdev); | ||
633 | status = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1, | ||
634 | &addr); | ||
635 | if (addr & 1) | ||
636 | ip2config.addr[i] = (USHORT)(addr & 0xfffe); | ||
637 | else | ||
638 | dev_err(&pdev->dev, "I/O address error\n"); | ||
639 | |||
640 | ip2config.irq[i] = pdev->irq; | ||
641 | } | ||
622 | #else | 642 | #else |
623 | printk( KERN_ERR "IP2: PCI card specified but PCI support not\n"); | 643 | printk(KERN_ERR "IP2: PCI card specified but PCI " |
624 | printk( KERN_ERR "IP2: configured in this kernel.\n"); | 644 | "support not enabled.\n"); |
625 | printk( KERN_ERR "IP2: Recompile kernel with CONFIG_PCI defined!\n"); | 645 | printk(KERN_ERR "IP2: Recompile kernel with CONFIG_PCI " |
646 | "defined!\n"); | ||
626 | #endif /* CONFIG_PCI */ | 647 | #endif /* CONFIG_PCI */ |
627 | break; | 648 | break; |
628 | case EISA: | 649 | case EISA: |
629 | if ( (ip2config.addr[i] = find_eisa_board( Eisa_slot + 1 )) != 0) { | 650 | ip2config.addr[i] = find_eisa_board(Eisa_slot + 1); |
651 | if (ip2config.addr[i] != 0) { | ||
630 | /* Eisa_irq set as side effect, boo */ | 652 | /* Eisa_irq set as side effect, boo */ |
631 | ip2config.type[i] = EISA; | 653 | ip2config.type[i] = EISA; |
632 | } | 654 | } |
@@ -634,31 +656,32 @@ ip2_loadmain(int *iop, int *irqp) | |||
634 | break; | 656 | break; |
635 | } /* switch */ | 657 | } /* switch */ |
636 | } /* for */ | 658 | } /* for */ |
637 | if (pci_dev_i) | 659 | pci_dev_put(pdev); |
638 | pci_dev_put(pci_dev_i); | ||
639 | 660 | ||
640 | for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 661 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { |
641 | if ( ip2config.addr[i] ) { | 662 | if (ip2config.addr[i]) { |
642 | pB = kzalloc(sizeof(i2eBordStr), GFP_KERNEL); | 663 | pB = kzalloc(sizeof(i2eBordStr), GFP_KERNEL); |
643 | if (pB) { | 664 | if (pB) { |
644 | i2BoardPtrTable[i] = pB; | 665 | i2BoardPtrTable[i] = pB; |
645 | iiSetAddress( pB, ip2config.addr[i], ii2DelayTimer ); | 666 | iiSetAddress(pB, ip2config.addr[i], |
646 | iiReset( pB ); | 667 | ii2DelayTimer); |
647 | } else { | 668 | iiReset(pB); |
648 | printk(KERN_ERR "IP2: board memory allocation error\n"); | 669 | } else |
649 | } | 670 | printk(KERN_ERR "IP2: board memory allocation " |
671 | "error\n"); | ||
650 | } | 672 | } |
651 | } | 673 | } |
652 | for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 674 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { |
653 | if ( ( pB = i2BoardPtrTable[i] ) != NULL ) { | 675 | pB = i2BoardPtrTable[i]; |
654 | iiResetDelay( pB ); | 676 | if (pB != NULL) { |
677 | iiResetDelay(pB); | ||
655 | break; | 678 | break; |
656 | } | 679 | } |
657 | } | 680 | } |
658 | for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 681 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { |
659 | /* We don't want to request the firmware unless we have at | 682 | /* We don't want to request the firmware unless we have at |
660 | least one board */ | 683 | least one board */ |
661 | if ( i2BoardPtrTable[i] != NULL ) { | 684 | if (i2BoardPtrTable[i] != NULL) { |
662 | if (!fw) | 685 | if (!fw) |
663 | fw = ip2_request_firmware(); | 686 | fw = ip2_request_firmware(); |
664 | if (!fw) | 687 | if (!fw) |
@@ -669,7 +692,7 @@ ip2_loadmain(int *iop, int *irqp) | |||
669 | if (fw) | 692 | if (fw) |
670 | release_firmware(fw); | 693 | release_firmware(fw); |
671 | 694 | ||
672 | ip2trace (ITRC_NO_PORT, ITRC_INIT, 2, 0 ); | 695 | ip2trace(ITRC_NO_PORT, ITRC_INIT, 2, 0); |
673 | 696 | ||
674 | ip2_tty_driver->owner = THIS_MODULE; | 697 | ip2_tty_driver->owner = THIS_MODULE; |
675 | ip2_tty_driver->name = "ttyF"; | 698 | ip2_tty_driver->name = "ttyF"; |
@@ -680,20 +703,23 @@ ip2_loadmain(int *iop, int *irqp) | |||
680 | ip2_tty_driver->subtype = SERIAL_TYPE_NORMAL; | 703 | ip2_tty_driver->subtype = SERIAL_TYPE_NORMAL; |
681 | ip2_tty_driver->init_termios = tty_std_termios; | 704 | ip2_tty_driver->init_termios = tty_std_termios; |
682 | ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; | 705 | ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; |
683 | ip2_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | 706 | ip2_tty_driver->flags = TTY_DRIVER_REAL_RAW | |
707 | TTY_DRIVER_DYNAMIC_DEV; | ||
684 | tty_set_operations(ip2_tty_driver, &ip2_ops); | 708 | tty_set_operations(ip2_tty_driver, &ip2_ops); |
685 | 709 | ||
686 | ip2trace (ITRC_NO_PORT, ITRC_INIT, 3, 0 ); | 710 | ip2trace(ITRC_NO_PORT, ITRC_INIT, 3, 0); |
687 | 711 | ||
688 | /* Register the tty devices. */ | 712 | err = tty_register_driver(ip2_tty_driver); |
689 | if ( ( err = tty_register_driver ( ip2_tty_driver ) ) ) { | 713 | if (err) { |
690 | printk(KERN_ERR "IP2: failed to register tty driver (%d)\n", err); | 714 | printk(KERN_ERR "IP2: failed to register tty driver\n"); |
691 | put_tty_driver(ip2_tty_driver); | 715 | put_tty_driver(ip2_tty_driver); |
692 | return -EINVAL; | 716 | return err; /* leaking resources */ |
693 | } else | 717 | } |
694 | /* Register the IPL driver. */ | 718 | |
695 | if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) ) { | 719 | err = register_chrdev(IP2_IPL_MAJOR, pcIpl, &ip2_ipl); |
696 | printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err ); | 720 | if (err) { |
721 | printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", | ||
722 | err); | ||
697 | } else { | 723 | } else { |
698 | /* create the sysfs class */ | 724 | /* create the sysfs class */ |
699 | ip2_class = class_create(THIS_MODULE, "ip2"); | 725 | ip2_class = class_create(THIS_MODULE, "ip2"); |
@@ -705,84 +731,86 @@ ip2_loadmain(int *iop, int *irqp) | |||
705 | /* Register the read_procmem thing */ | 731 | /* Register the read_procmem thing */ |
706 | if (!proc_create("ip2mem",0,NULL,&ip2mem_proc_fops)) { | 732 | if (!proc_create("ip2mem",0,NULL,&ip2mem_proc_fops)) { |
707 | printk(KERN_ERR "IP2: failed to register read_procmem\n"); | 733 | printk(KERN_ERR "IP2: failed to register read_procmem\n"); |
708 | } else { | 734 | return -EIO; /* leaking resources */ |
735 | } | ||
709 | 736 | ||
710 | ip2trace (ITRC_NO_PORT, ITRC_INIT, 4, 0 ); | 737 | ip2trace(ITRC_NO_PORT, ITRC_INIT, 4, 0); |
711 | /* Register the interrupt handler or poll handler, depending upon the | 738 | /* Register the interrupt handler or poll handler, depending upon the |
712 | * specified interrupt. | 739 | * specified interrupt. |
713 | */ | 740 | */ |
714 | 741 | ||
715 | for( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 742 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { |
716 | if ( 0 == ip2config.addr[i] ) { | 743 | if (ip2config.addr[i] == 0) |
717 | continue; | 744 | continue; |
718 | } | ||
719 | 745 | ||
720 | if ( NULL != ( pB = i2BoardPtrTable[i] ) ) { | 746 | pB = i2BoardPtrTable[i]; |
721 | device_create_drvdata(ip2_class, NULL, | 747 | if (pB != NULL) { |
722 | MKDEV(IP2_IPL_MAJOR, 4 * i), | 748 | device_create_drvdata(ip2_class, NULL, |
723 | NULL, "ipl%d", i); | 749 | MKDEV(IP2_IPL_MAJOR, 4 * i), |
724 | device_create_drvdata(ip2_class, NULL, | 750 | NULL, "ipl%d", i); |
725 | MKDEV(IP2_IPL_MAJOR, 4 * i + 1), | 751 | device_create_drvdata(ip2_class, NULL, |
726 | NULL, "stat%d", i); | 752 | MKDEV(IP2_IPL_MAJOR, 4 * i + 1), |
727 | 753 | NULL, "stat%d", i); | |
728 | for ( box = 0; box < ABS_MAX_BOXES; ++box ) | 754 | |
729 | { | 755 | for (box = 0; box < ABS_MAX_BOXES; box++) |
730 | for ( j = 0; j < ABS_BIGGEST_BOX; ++j ) | 756 | for (j = 0; j < ABS_BIGGEST_BOX; j++) |
731 | { | 757 | if (pB->i2eChannelMap[box] & (1 << j)) |
732 | if ( pB->i2eChannelMap[box] & (1 << j) ) | 758 | tty_register_device( |
733 | { | 759 | ip2_tty_driver, |
734 | tty_register_device(ip2_tty_driver, | 760 | j + ABS_BIGGEST_BOX * |
735 | j + ABS_BIGGEST_BOX * | 761 | (box+i*ABS_MAX_BOXES), |
736 | (box+i*ABS_MAX_BOXES), NULL); | 762 | NULL); |
737 | } | 763 | } |
738 | } | ||
739 | } | ||
740 | } | ||
741 | 764 | ||
742 | if (poll_only) { | 765 | if (poll_only) { |
743 | // Poll only forces driver to only use polling and | 766 | /* Poll only forces driver to only use polling and |
744 | // to ignore the probed PCI or EISA interrupts. | 767 | to ignore the probed PCI or EISA interrupts. */ |
745 | ip2config.irq[i] = CIR_POLL; | 768 | ip2config.irq[i] = CIR_POLL; |
746 | } | 769 | } |
747 | if ( ip2config.irq[i] == CIR_POLL ) { | 770 | if (ip2config.irq[i] == CIR_POLL) { |
748 | retry: | 771 | retry: |
749 | if (!TimerOn) { | 772 | if (!timer_pending(&PollTimer)) { |
750 | PollTimer.expires = POLL_TIMEOUT; | 773 | mod_timer(&PollTimer, POLL_TIMEOUT); |
751 | add_timer ( &PollTimer ); | 774 | printk(KERN_INFO "IP2: polling\n"); |
752 | TimerOn = 1; | ||
753 | printk( KERN_INFO "IP2: polling\n"); | ||
754 | } | ||
755 | } else { | ||
756 | if (have_requested_irq(ip2config.irq[i])) | ||
757 | continue; | ||
758 | rc = request_irq( ip2config.irq[i], ip2_interrupt, | ||
759 | IP2_SA_FLAGS | (ip2config.type[i] == PCI ? IRQF_SHARED : 0), | ||
760 | pcName, i2BoardPtrTable[i]); | ||
761 | if (rc) { | ||
762 | printk(KERN_ERR "IP2: an request_irq failed: error %d\n",rc); | ||
763 | ip2config.irq[i] = CIR_POLL; | ||
764 | printk( KERN_INFO "IP2: Polling %ld/sec.\n", | ||
765 | (POLL_TIMEOUT - jiffies)); | ||
766 | goto retry; | ||
767 | } | ||
768 | mark_requested_irq(ip2config.irq[i]); | ||
769 | /* Initialise the interrupt handler bottom half (aka slih). */ | ||
770 | } | 775 | } |
771 | } | 776 | } else { |
772 | for( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 777 | if (have_requested_irq(ip2config.irq[i])) |
773 | if ( i2BoardPtrTable[i] ) { | 778 | continue; |
774 | set_irq( i, ip2config.irq[i] ); /* set and enable board interrupt */ | 779 | rc = request_irq(ip2config.irq[i], ip2_interrupt, |
780 | IP2_SA_FLAGS | | ||
781 | (ip2config.type[i] == PCI ? IRQF_SHARED : 0), | ||
782 | pcName, i2BoardPtrTable[i]); | ||
783 | if (rc) { | ||
784 | printk(KERN_ERR "IP2: request_irq failed: " | ||
785 | "error %d\n", rc); | ||
786 | ip2config.irq[i] = CIR_POLL; | ||
787 | printk(KERN_INFO "IP2: Polling %ld/sec.\n", | ||
788 | (POLL_TIMEOUT - jiffies)); | ||
789 | goto retry; | ||
775 | } | 790 | } |
791 | mark_requested_irq(ip2config.irq[i]); | ||
792 | /* Initialise the interrupt handler bottom half | ||
793 | * (aka slih). */ | ||
776 | } | 794 | } |
777 | } | 795 | } |
778 | ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0 ); | 796 | |
779 | goto out; | 797 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { |
798 | if (i2BoardPtrTable[i]) { | ||
799 | /* set and enable board interrupt */ | ||
800 | set_irq(i, ip2config.irq[i]); | ||
801 | } | ||
802 | } | ||
803 | |||
804 | ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0); | ||
805 | |||
806 | return 0; | ||
780 | 807 | ||
781 | out_chrdev: | 808 | out_chrdev: |
782 | unregister_chrdev(IP2_IPL_MAJOR, "ip2"); | 809 | unregister_chrdev(IP2_IPL_MAJOR, "ip2"); |
783 | out: | 810 | /* unregister and put tty here */ |
784 | return err; | 811 | return err; |
785 | } | 812 | } |
813 | module_init(ip2_loadmain); | ||
786 | 814 | ||
787 | /******************************************************************************/ | 815 | /******************************************************************************/ |
788 | /* Function: ip2_init_board() */ | 816 | /* Function: ip2_init_board() */ |
@@ -1199,9 +1227,8 @@ ip2_polled_interrupt(void) | |||
1199 | { | 1227 | { |
1200 | int i; | 1228 | int i; |
1201 | i2eBordStrPtr pB; | 1229 | i2eBordStrPtr pB; |
1202 | const int irq = 0; | ||
1203 | 1230 | ||
1204 | ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, irq ); | 1231 | ip2trace(ITRC_NO_PORT, ITRC_INTR, 99, 1, 0); |
1205 | 1232 | ||
1206 | /* Service just the boards on the list using this irq */ | 1233 | /* Service just the boards on the list using this irq */ |
1207 | for( i = 0; i < i2nBoards; ++i ) { | 1234 | for( i = 0; i < i2nBoards; ++i ) { |
@@ -1210,9 +1237,8 @@ ip2_polled_interrupt(void) | |||
1210 | // Only process those boards which match our IRQ. | 1237 | // Only process those boards which match our IRQ. |
1211 | // IRQ = 0 for polled boards, we won't poll "IRQ" boards | 1238 | // IRQ = 0 for polled boards, we won't poll "IRQ" boards |
1212 | 1239 | ||
1213 | if ( pB && (pB->i2eUsingIrq == irq) ) { | 1240 | if (pB && pB->i2eUsingIrq == 0) |
1214 | ip2_irq_work(pB); | 1241 | ip2_irq_work(pB); |
1215 | } | ||
1216 | } | 1242 | } |
1217 | 1243 | ||
1218 | ++irq_counter; | 1244 | ++irq_counter; |
@@ -1250,16 +1276,12 @@ ip2_poll(unsigned long arg) | |||
1250 | { | 1276 | { |
1251 | ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 ); | 1277 | ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 ); |
1252 | 1278 | ||
1253 | TimerOn = 0; // it's the truth but not checked in service | ||
1254 | |||
1255 | // Just polled boards, IRQ = 0 will hit all non-interrupt boards. | 1279 | // Just polled boards, IRQ = 0 will hit all non-interrupt boards. |
1256 | // It will NOT poll boards handled by hard interrupts. | 1280 | // It will NOT poll boards handled by hard interrupts. |
1257 | // The issue of queued BH interrupts is handled in ip2_interrupt(). | 1281 | // The issue of queued BH interrupts is handled in ip2_interrupt(). |
1258 | ip2_polled_interrupt(); | 1282 | ip2_polled_interrupt(); |
1259 | 1283 | ||
1260 | PollTimer.expires = POLL_TIMEOUT; | 1284 | mod_timer(&PollTimer, POLL_TIMEOUT); |
1261 | add_timer( &PollTimer ); | ||
1262 | TimerOn = 1; | ||
1263 | 1285 | ||
1264 | ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); | 1286 | ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); |
1265 | } | 1287 | } |
@@ -2871,7 +2893,7 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg ) | |||
2871 | case 13: | 2893 | case 13: |
2872 | switch ( cmd ) { | 2894 | switch ( cmd ) { |
2873 | case 64: /* Driver - ip2stat */ | 2895 | case 64: /* Driver - ip2stat */ |
2874 | rc = put_user(ip2_tty_driver->refcount, pIndex++ ); | 2896 | rc = put_user(-1, pIndex++ ); |
2875 | rc = put_user(irq_counter, pIndex++ ); | 2897 | rc = put_user(irq_counter, pIndex++ ); |
2876 | rc = put_user(bh_counter, pIndex++ ); | 2898 | rc = put_user(bh_counter, pIndex++ ); |
2877 | break; | 2899 | break; |