diff options
Diffstat (limited to 'drivers/char/specialix.c')
-rw-r--r-- | drivers/char/specialix.c | 342 |
1 files changed, 170 insertions, 172 deletions
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 50e0b612a8a2..352547eabf7b 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c | |||
@@ -38,19 +38,19 @@ | |||
38 | * | 38 | * |
39 | * Revision 1.0: April 1st 1997. | 39 | * Revision 1.0: April 1st 1997. |
40 | * Initial release for alpha testing. | 40 | * Initial release for alpha testing. |
41 | * Revision 1.1: April 14th 1997. | 41 | * Revision 1.1: April 14th 1997. |
42 | * Incorporated Richard Hudsons suggestions, | 42 | * Incorporated Richard Hudsons suggestions, |
43 | * removed some debugging printk's. | 43 | * removed some debugging printk's. |
44 | * Revision 1.2: April 15th 1997. | 44 | * Revision 1.2: April 15th 1997. |
45 | * Ported to 2.1.x kernels. | 45 | * Ported to 2.1.x kernels. |
46 | * Revision 1.3: April 17th 1997 | 46 | * Revision 1.3: April 17th 1997 |
47 | * Backported to 2.0. (Compatibility macros). | 47 | * Backported to 2.0. (Compatibility macros). |
48 | * Revision 1.4: April 18th 1997 | 48 | * Revision 1.4: April 18th 1997 |
49 | * Fixed DTR/RTS bug that caused the card to indicate | 49 | * Fixed DTR/RTS bug that caused the card to indicate |
50 | * "don't send data" to a modem after the password prompt. | 50 | * "don't send data" to a modem after the password prompt. |
51 | * Fixed bug for premature (fake) interrupts. | 51 | * Fixed bug for premature (fake) interrupts. |
52 | * Revision 1.5: April 19th 1997 | 52 | * Revision 1.5: April 19th 1997 |
53 | * fixed a minor typo in the header file, cleanup a little. | 53 | * fixed a minor typo in the header file, cleanup a little. |
54 | * performance warnings are now MAXed at once per minute. | 54 | * performance warnings are now MAXed at once per minute. |
55 | * Revision 1.6: May 23 1997 | 55 | * Revision 1.6: May 23 1997 |
56 | * Changed the specialix=... format to include interrupt. | 56 | * Changed the specialix=... format to include interrupt. |
@@ -60,10 +60,10 @@ | |||
60 | * port to linux-2.1.43 kernel. | 60 | * port to linux-2.1.43 kernel. |
61 | * Revision 1.9: Oct 9 1998 | 61 | * Revision 1.9: Oct 9 1998 |
62 | * Added stuff for the IO8+/PCI version. | 62 | * Added stuff for the IO8+/PCI version. |
63 | * Revision 1.10: Oct 22 1999 / Jan 21 2000. | 63 | * Revision 1.10: Oct 22 1999 / Jan 21 2000. |
64 | * Added stuff for setserial. | 64 | * Added stuff for setserial. |
65 | * Nicolas Mailhot (Nicolas.Mailhot@email.enst.fr) | 65 | * Nicolas Mailhot (Nicolas.Mailhot@email.enst.fr) |
66 | * | 66 | * |
67 | */ | 67 | */ |
68 | 68 | ||
69 | #define VERSION "1.11" | 69 | #define VERSION "1.11" |
@@ -154,7 +154,7 @@ static int sx_poll = HZ; | |||
154 | 154 | ||
155 | 155 | ||
156 | 156 | ||
157 | /* | 157 | /* |
158 | * The following defines are mostly for testing purposes. But if you need | 158 | * The following defines are mostly for testing purposes. But if you need |
159 | * some nice reporting in your syslog, you can define them also. | 159 | * some nice reporting in your syslog, you can define them also. |
160 | */ | 160 | */ |
@@ -188,7 +188,7 @@ static DECLARE_MUTEX(tmp_buf_sem); | |||
188 | 188 | ||
189 | static unsigned long baud_table[] = { | 189 | static unsigned long baud_table[] = { |
190 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, | 190 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, |
191 | 9600, 19200, 38400, 57600, 115200, 0, | 191 | 9600, 19200, 38400, 57600, 115200, 0, |
192 | }; | 192 | }; |
193 | 193 | ||
194 | static struct specialix_board sx_board[SX_NBOARD] = { | 194 | static struct specialix_board sx_board[SX_NBOARD] = { |
@@ -216,7 +216,7 @@ static inline int sx_paranoia_check(struct specialix_port const * port, | |||
216 | KERN_ERR "sx: Warning: bad specialix port magic number for device %s in %s\n"; | 216 | KERN_ERR "sx: Warning: bad specialix port magic number for device %s in %s\n"; |
217 | static const char *badinfo = | 217 | static const char *badinfo = |
218 | KERN_ERR "sx: Warning: null specialix port for device %s in %s\n"; | 218 | KERN_ERR "sx: Warning: null specialix port for device %s in %s\n"; |
219 | 219 | ||
220 | if (!port) { | 220 | if (!port) { |
221 | printk(badinfo, name, routine); | 221 | printk(badinfo, name, routine); |
222 | return 1; | 222 | return 1; |
@@ -231,9 +231,9 @@ static inline int sx_paranoia_check(struct specialix_port const * port, | |||
231 | 231 | ||
232 | 232 | ||
233 | /* | 233 | /* |
234 | * | 234 | * |
235 | * Service functions for specialix IO8+ driver. | 235 | * Service functions for specialix IO8+ driver. |
236 | * | 236 | * |
237 | */ | 237 | */ |
238 | 238 | ||
239 | /* Get board number from pointer */ | 239 | /* Get board number from pointer */ |
@@ -246,7 +246,7 @@ static inline int board_No (struct specialix_board * bp) | |||
246 | /* Get port number from pointer */ | 246 | /* Get port number from pointer */ |
247 | static inline int port_No (struct specialix_port const * port) | 247 | static inline int port_No (struct specialix_port const * port) |
248 | { | 248 | { |
249 | return SX_PORT(port - sx_port); | 249 | return SX_PORT(port - sx_port); |
250 | } | 250 | } |
251 | 251 | ||
252 | 252 | ||
@@ -309,7 +309,7 @@ static inline void sx_wait_CCR(struct specialix_board * bp) | |||
309 | return; | 309 | return; |
310 | udelay (1); | 310 | udelay (1); |
311 | } | 311 | } |
312 | 312 | ||
313 | printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); | 313 | printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); |
314 | } | 314 | } |
315 | 315 | ||
@@ -329,7 +329,7 @@ static inline void sx_wait_CCR_off(struct specialix_board * bp) | |||
329 | return; | 329 | return; |
330 | udelay (1); | 330 | udelay (1); |
331 | } | 331 | } |
332 | 332 | ||
333 | printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); | 333 | printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); |
334 | } | 334 | } |
335 | 335 | ||
@@ -338,34 +338,28 @@ static inline void sx_wait_CCR_off(struct specialix_board * bp) | |||
338 | * specialix IO8+ IO range functions. | 338 | * specialix IO8+ IO range functions. |
339 | */ | 339 | */ |
340 | 340 | ||
341 | static inline int sx_check_io_range(struct specialix_board * bp) | 341 | static inline int sx_request_io_range(struct specialix_board * bp) |
342 | { | 342 | { |
343 | return check_region (bp->base, SX_IO_SPACE); | 343 | return request_region(bp->base, |
344 | } | 344 | bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE, |
345 | 345 | "specialix IO8+") == NULL; | |
346 | |||
347 | static inline void sx_request_io_range(struct specialix_board * bp) | ||
348 | { | ||
349 | request_region(bp->base, | ||
350 | bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE, | ||
351 | "specialix IO8+" ); | ||
352 | } | 346 | } |
353 | 347 | ||
354 | 348 | ||
355 | static inline void sx_release_io_range(struct specialix_board * bp) | 349 | static inline void sx_release_io_range(struct specialix_board * bp) |
356 | { | 350 | { |
357 | release_region(bp->base, | 351 | release_region(bp->base, |
358 | bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE); | 352 | bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE); |
359 | } | 353 | } |
360 | 354 | ||
361 | 355 | ||
362 | /* Must be called with enabled interrupts */ | 356 | /* Must be called with enabled interrupts */ |
363 | /* Ugly. Very ugly. Don't use this for anything else than initialization | 357 | /* Ugly. Very ugly. Don't use this for anything else than initialization |
364 | code */ | 358 | code */ |
365 | static inline void sx_long_delay(unsigned long delay) | 359 | static inline void sx_long_delay(unsigned long delay) |
366 | { | 360 | { |
367 | unsigned long i; | 361 | unsigned long i; |
368 | 362 | ||
369 | for (i = jiffies + delay; time_after(i, jiffies); ) ; | 363 | for (i = jiffies + delay; time_after(i, jiffies); ) ; |
370 | } | 364 | } |
371 | 365 | ||
@@ -378,7 +372,7 @@ static int sx_set_irq ( struct specialix_board *bp) | |||
378 | int i; | 372 | int i; |
379 | unsigned long flags; | 373 | unsigned long flags; |
380 | 374 | ||
381 | if (bp->flags & SX_BOARD_IS_PCI) | 375 | if (bp->flags & SX_BOARD_IS_PCI) |
382 | return 1; | 376 | return 1; |
383 | switch (bp->irq) { | 377 | switch (bp->irq) { |
384 | /* In the same order as in the docs... */ | 378 | /* In the same order as in the docs... */ |
@@ -420,7 +414,7 @@ static int sx_init_CD186x(struct specialix_board * bp) | |||
420 | sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT); /* Prio for receiver intr */ | 414 | sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT); /* Prio for receiver intr */ |
421 | /* Set RegAckEn */ | 415 | /* Set RegAckEn */ |
422 | sx_out_off(bp, CD186x_SRCR, sx_in (bp, CD186x_SRCR) | SRCR_REGACKEN); | 416 | sx_out_off(bp, CD186x_SRCR, sx_in (bp, CD186x_SRCR) | SRCR_REGACKEN); |
423 | 417 | ||
424 | /* Setting up prescaler. We need 4 ticks per 1 ms */ | 418 | /* Setting up prescaler. We need 4 ticks per 1 ms */ |
425 | scaler = SX_OSCFREQ/SPECIALIX_TPS; | 419 | scaler = SX_OSCFREQ/SPECIALIX_TPS; |
426 | 420 | ||
@@ -448,7 +442,7 @@ static int read_cross_byte (struct specialix_board *bp, int reg, int bit) | |||
448 | spin_lock_irqsave(&bp->lock, flags); | 442 | spin_lock_irqsave(&bp->lock, flags); |
449 | for (i=0, t=0;i<8;i++) { | 443 | for (i=0, t=0;i<8;i++) { |
450 | sx_out_off (bp, CD186x_CAR, i); | 444 | sx_out_off (bp, CD186x_CAR, i); |
451 | if (sx_in_off (bp, reg) & bit) | 445 | if (sx_in_off (bp, reg) & bit) |
452 | t |= 1 << i; | 446 | t |= 1 << i; |
453 | } | 447 | } |
454 | spin_unlock_irqrestore(&bp->lock, flags); | 448 | spin_unlock_irqrestore(&bp->lock, flags); |
@@ -472,7 +466,7 @@ void missed_irq (unsigned long data) | |||
472 | spin_unlock_irqrestore(&bp->lock, flags); | 466 | spin_unlock_irqrestore(&bp->lock, flags); |
473 | if (irq) { | 467 | if (irq) { |
474 | printk (KERN_INFO "Missed interrupt... Calling int from timer. \n"); | 468 | printk (KERN_INFO "Missed interrupt... Calling int from timer. \n"); |
475 | sx_interrupt (((struct specialix_board *)data)->irq, | 469 | sx_interrupt (((struct specialix_board *)data)->irq, |
476 | (void*)data, NULL); | 470 | (void*)data, NULL); |
477 | } | 471 | } |
478 | missed_irq_timer.expires = jiffies + sx_poll; | 472 | missed_irq_timer.expires = jiffies + sx_poll; |
@@ -495,7 +489,7 @@ static int sx_probe(struct specialix_board *bp) | |||
495 | 489 | ||
496 | func_enter(); | 490 | func_enter(); |
497 | 491 | ||
498 | if (sx_check_io_range(bp)) { | 492 | if (sx_request_io_range(bp)) { |
499 | func_exit(); | 493 | func_exit(); |
500 | return 1; | 494 | return 1; |
501 | } | 495 | } |
@@ -509,15 +503,16 @@ static int sx_probe(struct specialix_board *bp) | |||
509 | short_pause (); | 503 | short_pause (); |
510 | val2 = sx_in_off(bp, CD186x_PPRL); | 504 | val2 = sx_in_off(bp, CD186x_PPRL); |
511 | 505 | ||
512 | 506 | ||
513 | if ((val1 != 0x5a) || (val2 != 0xa5)) { | 507 | if ((val1 != 0x5a) || (val2 != 0xa5)) { |
514 | printk(KERN_INFO "sx%d: specialix IO8+ Board at 0x%03x not found.\n", | 508 | printk(KERN_INFO "sx%d: specialix IO8+ Board at 0x%03x not found.\n", |
515 | board_No(bp), bp->base); | 509 | board_No(bp), bp->base); |
510 | sx_release_io_range(bp); | ||
516 | func_exit(); | 511 | func_exit(); |
517 | return 1; | 512 | return 1; |
518 | } | 513 | } |
519 | 514 | ||
520 | /* Check the DSR lines that Specialix uses as board | 515 | /* Check the DSR lines that Specialix uses as board |
521 | identification */ | 516 | identification */ |
522 | val1 = read_cross_byte (bp, CD186x_MSVR, MSVR_DSR); | 517 | val1 = read_cross_byte (bp, CD186x_MSVR, MSVR_DSR); |
523 | val2 = read_cross_byte (bp, CD186x_MSVR, MSVR_RTS); | 518 | val2 = read_cross_byte (bp, CD186x_MSVR, MSVR_RTS); |
@@ -532,6 +527,7 @@ static int sx_probe(struct specialix_board *bp) | |||
532 | if (val1 != val2) { | 527 | if (val1 != val2) { |
533 | printk(KERN_INFO "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n", | 528 | printk(KERN_INFO "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n", |
534 | board_No(bp), val2, bp->base, val1); | 529 | board_No(bp), val2, bp->base, val1); |
530 | sx_release_io_range(bp); | ||
535 | func_exit(); | 531 | func_exit(); |
536 | return 1; | 532 | return 1; |
537 | } | 533 | } |
@@ -546,7 +542,7 @@ static int sx_probe(struct specialix_board *bp) | |||
546 | sx_wait_CCR(bp); | 542 | sx_wait_CCR(bp); |
547 | sx_out(bp, CD186x_CCR, CCR_TXEN); /* Enable transmitter */ | 543 | sx_out(bp, CD186x_CCR, CCR_TXEN); /* Enable transmitter */ |
548 | sx_out(bp, CD186x_IER, IER_TXRDY); /* Enable tx empty intr */ | 544 | sx_out(bp, CD186x_IER, IER_TXRDY); /* Enable tx empty intr */ |
549 | sx_long_delay(HZ/20); | 545 | sx_long_delay(HZ/20); |
550 | irqs = probe_irq_off(irqs); | 546 | irqs = probe_irq_off(irqs); |
551 | 547 | ||
552 | dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR)); | 548 | dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR)); |
@@ -561,14 +557,15 @@ static int sx_probe(struct specialix_board *bp) | |||
561 | } | 557 | } |
562 | 558 | ||
563 | dprintk (SX_DEBUG_INIT "val1 = %02x, val2 = %02x, val3 = %02x.\n", | 559 | dprintk (SX_DEBUG_INIT "val1 = %02x, val2 = %02x, val3 = %02x.\n", |
564 | val1, val2, val3); | 560 | val1, val2, val3); |
565 | 561 | ||
566 | } | 562 | } |
567 | 563 | ||
568 | #if 0 | 564 | #if 0 |
569 | if (irqs <= 0) { | 565 | if (irqs <= 0) { |
570 | printk(KERN_ERR "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n", | 566 | printk(KERN_ERR "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n", |
571 | board_No(bp), bp->base); | 567 | board_No(bp), bp->base); |
568 | sx_release_io_range(bp); | ||
572 | func_exit(); | 569 | func_exit(); |
573 | return 1; | 570 | return 1; |
574 | } | 571 | } |
@@ -579,19 +576,20 @@ static int sx_probe(struct specialix_board *bp) | |||
579 | #endif | 576 | #endif |
580 | /* Reset CD186x again */ | 577 | /* Reset CD186x again */ |
581 | if (!sx_init_CD186x(bp)) { | 578 | if (!sx_init_CD186x(bp)) { |
579 | sx_release_io_range(bp); | ||
582 | func_exit(); | 580 | func_exit(); |
583 | return -EIO; | 581 | return 1; |
584 | } | 582 | } |
585 | 583 | ||
586 | sx_request_io_range(bp); | 584 | sx_request_io_range(bp); |
587 | bp->flags |= SX_BOARD_PRESENT; | 585 | bp->flags |= SX_BOARD_PRESENT; |
588 | 586 | ||
589 | /* Chip revcode pkgtype | 587 | /* Chip revcode pkgtype |
590 | GFRCR SRCR bit 7 | 588 | GFRCR SRCR bit 7 |
591 | CD180 rev B 0x81 0 | 589 | CD180 rev B 0x81 0 |
592 | CD180 rev C 0x82 0 | 590 | CD180 rev C 0x82 0 |
593 | CD1864 rev A 0x82 1 | 591 | CD1864 rev A 0x82 1 |
594 | CD1865 rev A 0x83 1 -- Do not use!!! Does not work. | 592 | CD1865 rev A 0x83 1 -- Do not use!!! Does not work. |
595 | CD1865 rev B 0x84 1 | 593 | CD1865 rev B 0x84 1 |
596 | -- Thanks to Gwen Wang, Cirrus Logic. | 594 | -- Thanks to Gwen Wang, Cirrus Logic. |
597 | */ | 595 | */ |
@@ -623,8 +621,8 @@ static int sx_probe(struct specialix_board *bp) | |||
623 | return 0; | 621 | return 0; |
624 | } | 622 | } |
625 | 623 | ||
626 | /* | 624 | /* |
627 | * | 625 | * |
628 | * Interrupt processing routines. | 626 | * Interrupt processing routines. |
629 | * */ | 627 | * */ |
630 | 628 | ||
@@ -657,7 +655,7 @@ static inline struct specialix_port * sx_get_port(struct specialix_board * bp, | |||
657 | return port; | 655 | return port; |
658 | } | 656 | } |
659 | } | 657 | } |
660 | printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n", | 658 | printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n", |
661 | board_No(bp), what, channel); | 659 | board_No(bp), what, channel); |
662 | return NULL; | 660 | return NULL; |
663 | } | 661 | } |
@@ -681,7 +679,7 @@ static inline void sx_receive_exc(struct specialix_board * bp) | |||
681 | tty = port->tty; | 679 | tty = port->tty; |
682 | dprintk (SX_DEBUG_RX, "port: %p count: %d BUFF_SIZE: %d\n", | 680 | dprintk (SX_DEBUG_RX, "port: %p count: %d BUFF_SIZE: %d\n", |
683 | port, tty->flip.count, TTY_FLIPBUF_SIZE); | 681 | port, tty->flip.count, TTY_FLIPBUF_SIZE); |
684 | 682 | ||
685 | status = sx_in(bp, CD186x_RCSR); | 683 | status = sx_in(bp, CD186x_RCSR); |
686 | 684 | ||
687 | dprintk (SX_DEBUG_RX, "status: 0x%x\n", status); | 685 | dprintk (SX_DEBUG_RX, "status: 0x%x\n", status); |
@@ -707,30 +705,30 @@ static inline void sx_receive_exc(struct specialix_board * bp) | |||
707 | return; | 705 | return; |
708 | } | 706 | } |
709 | if (status & RCSR_TOUT) { | 707 | if (status & RCSR_TOUT) { |
710 | printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n", | 708 | printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n", |
711 | board_No(bp), port_No(port)); | 709 | board_No(bp), port_No(port)); |
712 | func_exit(); | 710 | func_exit(); |
713 | return; | 711 | return; |
714 | 712 | ||
715 | } else if (status & RCSR_BREAK) { | 713 | } else if (status & RCSR_BREAK) { |
716 | dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n", | 714 | dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n", |
717 | board_No(bp), port_No(port)); | 715 | board_No(bp), port_No(port)); |
718 | *tty->flip.flag_buf_ptr++ = TTY_BREAK; | 716 | *tty->flip.flag_buf_ptr++ = TTY_BREAK; |
719 | if (port->flags & ASYNC_SAK) | 717 | if (port->flags & ASYNC_SAK) |
720 | do_SAK(tty); | 718 | do_SAK(tty); |
721 | 719 | ||
722 | } else if (status & RCSR_PE) | 720 | } else if (status & RCSR_PE) |
723 | *tty->flip.flag_buf_ptr++ = TTY_PARITY; | 721 | *tty->flip.flag_buf_ptr++ = TTY_PARITY; |
724 | 722 | ||
725 | else if (status & RCSR_FE) | 723 | else if (status & RCSR_FE) |
726 | *tty->flip.flag_buf_ptr++ = TTY_FRAME; | 724 | *tty->flip.flag_buf_ptr++ = TTY_FRAME; |
727 | 725 | ||
728 | else if (status & RCSR_OE) | 726 | else if (status & RCSR_OE) |
729 | *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; | 727 | *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; |
730 | 728 | ||
731 | else | 729 | else |
732 | *tty->flip.flag_buf_ptr++ = 0; | 730 | *tty->flip.flag_buf_ptr++ = 0; |
733 | 731 | ||
734 | *tty->flip.char_buf_ptr++ = ch; | 732 | *tty->flip.char_buf_ptr++ = ch; |
735 | tty->flip.count++; | 733 | tty->flip.count++; |
736 | schedule_delayed_work(&tty->flip.work, 1); | 734 | schedule_delayed_work(&tty->flip.work, 1); |
@@ -746,18 +744,18 @@ static inline void sx_receive(struct specialix_board * bp) | |||
746 | unsigned char count; | 744 | unsigned char count; |
747 | 745 | ||
748 | func_enter(); | 746 | func_enter(); |
749 | 747 | ||
750 | if (!(port = sx_get_port(bp, "Receive"))) { | 748 | if (!(port = sx_get_port(bp, "Receive"))) { |
751 | dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n"); | 749 | dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n"); |
752 | func_exit(); | 750 | func_exit(); |
753 | return; | 751 | return; |
754 | } | 752 | } |
755 | tty = port->tty; | 753 | tty = port->tty; |
756 | 754 | ||
757 | count = sx_in(bp, CD186x_RDCR); | 755 | count = sx_in(bp, CD186x_RDCR); |
758 | dprintk (SX_DEBUG_RX, "port: %p: count: %d\n", port, count); | 756 | dprintk (SX_DEBUG_RX, "port: %p: count: %d\n", port, count); |
759 | port->hits[count > 8 ? 9 : count]++; | 757 | port->hits[count > 8 ? 9 : count]++; |
760 | 758 | ||
761 | while (count--) { | 759 | while (count--) { |
762 | if (tty->flip.count >= TTY_FLIPBUF_SIZE) { | 760 | if (tty->flip.count >= TTY_FLIPBUF_SIZE) { |
763 | printk(KERN_INFO "sx%d: port %d: Working around flip buffer overflow.\n", | 761 | printk(KERN_INFO "sx%d: port %d: Working around flip buffer overflow.\n", |
@@ -787,7 +785,7 @@ static inline void sx_transmit(struct specialix_board * bp) | |||
787 | } | 785 | } |
788 | dprintk (SX_DEBUG_TX, "port: %p\n", port); | 786 | dprintk (SX_DEBUG_TX, "port: %p\n", port); |
789 | tty = port->tty; | 787 | tty = port->tty; |
790 | 788 | ||
791 | if (port->IER & IER_TXEMPTY) { | 789 | if (port->IER & IER_TXEMPTY) { |
792 | /* FIFO drained */ | 790 | /* FIFO drained */ |
793 | sx_out(bp, CD186x_CAR, port_No(port)); | 791 | sx_out(bp, CD186x_CAR, port_No(port)); |
@@ -796,7 +794,7 @@ static inline void sx_transmit(struct specialix_board * bp) | |||
796 | func_exit(); | 794 | func_exit(); |
797 | return; | 795 | return; |
798 | } | 796 | } |
799 | 797 | ||
800 | if ((port->xmit_cnt <= 0 && !port->break_length) | 798 | if ((port->xmit_cnt <= 0 && !port->break_length) |
801 | || tty->stopped || tty->hw_stopped) { | 799 | || tty->stopped || tty->hw_stopped) { |
802 | sx_out(bp, CD186x_CAR, port_No(port)); | 800 | sx_out(bp, CD186x_CAR, port_No(port)); |
@@ -805,7 +803,7 @@ static inline void sx_transmit(struct specialix_board * bp) | |||
805 | func_exit(); | 803 | func_exit(); |
806 | return; | 804 | return; |
807 | } | 805 | } |
808 | 806 | ||
809 | if (port->break_length) { | 807 | if (port->break_length) { |
810 | if (port->break_length > 0) { | 808 | if (port->break_length > 0) { |
811 | if (port->COR2 & COR2_ETC) { | 809 | if (port->COR2 & COR2_ETC) { |
@@ -831,7 +829,7 @@ static inline void sx_transmit(struct specialix_board * bp) | |||
831 | func_exit(); | 829 | func_exit(); |
832 | return; | 830 | return; |
833 | } | 831 | } |
834 | 832 | ||
835 | count = CD186x_NFIFO; | 833 | count = CD186x_NFIFO; |
836 | do { | 834 | do { |
837 | sx_out(bp, CD186x_TDR, port->xmit_buf[port->xmit_tail++]); | 835 | sx_out(bp, CD186x_TDR, port->xmit_buf[port->xmit_tail++]); |
@@ -839,7 +837,7 @@ static inline void sx_transmit(struct specialix_board * bp) | |||
839 | if (--port->xmit_cnt <= 0) | 837 | if (--port->xmit_cnt <= 0) |
840 | break; | 838 | break; |
841 | } while (--count > 0); | 839 | } while (--count > 0); |
842 | 840 | ||
843 | if (port->xmit_cnt <= 0) { | 841 | if (port->xmit_cnt <= 0) { |
844 | sx_out(bp, CD186x_CAR, port_No(port)); | 842 | sx_out(bp, CD186x_CAR, port_No(port)); |
845 | port->IER &= ~IER_TXRDY; | 843 | port->IER &= ~IER_TXRDY; |
@@ -862,9 +860,9 @@ static inline void sx_check_modem(struct specialix_board * bp) | |||
862 | dprintk (SX_DEBUG_SIGNALS, "Modem intr. "); | 860 | dprintk (SX_DEBUG_SIGNALS, "Modem intr. "); |
863 | if (!(port = sx_get_port(bp, "Modem"))) | 861 | if (!(port = sx_get_port(bp, "Modem"))) |
864 | return; | 862 | return; |
865 | 863 | ||
866 | tty = port->tty; | 864 | tty = port->tty; |
867 | 865 | ||
868 | mcr = sx_in(bp, CD186x_MCR); | 866 | mcr = sx_in(bp, CD186x_MCR); |
869 | printk ("mcr = %02x.\n", mcr); | 867 | printk ("mcr = %02x.\n", mcr); |
870 | 868 | ||
@@ -879,7 +877,7 @@ static inline void sx_check_modem(struct specialix_board * bp) | |||
879 | schedule_work(&port->tqueue_hangup); | 877 | schedule_work(&port->tqueue_hangup); |
880 | } | 878 | } |
881 | } | 879 | } |
882 | 880 | ||
883 | #ifdef SPECIALIX_BRAIN_DAMAGED_CTS | 881 | #ifdef SPECIALIX_BRAIN_DAMAGED_CTS |
884 | if (mcr & MCR_CTSCHG) { | 882 | if (mcr & MCR_CTSCHG) { |
885 | if (sx_in(bp, CD186x_MSVR) & MSVR_CTS) { | 883 | if (sx_in(bp, CD186x_MSVR) & MSVR_CTS) { |
@@ -906,7 +904,7 @@ static inline void sx_check_modem(struct specialix_board * bp) | |||
906 | sx_out(bp, CD186x_IER, port->IER); | 904 | sx_out(bp, CD186x_IER, port->IER); |
907 | } | 905 | } |
908 | #endif /* SPECIALIX_BRAIN_DAMAGED_CTS */ | 906 | #endif /* SPECIALIX_BRAIN_DAMAGED_CTS */ |
909 | 907 | ||
910 | /* Clear change bits */ | 908 | /* Clear change bits */ |
911 | sx_out(bp, CD186x_MCR, 0); | 909 | sx_out(bp, CD186x_MCR, 0); |
912 | } | 910 | } |
@@ -940,7 +938,7 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
940 | while ((++loop < 16) && (status = (sx_in(bp, CD186x_SRSR) & | 938 | while ((++loop < 16) && (status = (sx_in(bp, CD186x_SRSR) & |
941 | (SRSR_RREQint | | 939 | (SRSR_RREQint | |
942 | SRSR_TREQint | | 940 | SRSR_TREQint | |
943 | SRSR_MREQint)))) { | 941 | SRSR_MREQint)))) { |
944 | if (status & SRSR_RREQint) { | 942 | if (status & SRSR_RREQint) { |
945 | ack = sx_in(bp, CD186x_RRAR); | 943 | ack = sx_in(bp, CD186x_RRAR); |
946 | 944 | ||
@@ -951,7 +949,7 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
951 | else | 949 | else |
952 | printk(KERN_ERR "sx%d: status: 0x%x Bad receive ack 0x%02x.\n", | 950 | printk(KERN_ERR "sx%d: status: 0x%x Bad receive ack 0x%02x.\n", |
953 | board_No(bp), status, ack); | 951 | board_No(bp), status, ack); |
954 | 952 | ||
955 | } else if (status & SRSR_TREQint) { | 953 | } else if (status & SRSR_TREQint) { |
956 | ack = sx_in(bp, CD186x_TRAR); | 954 | ack = sx_in(bp, CD186x_TRAR); |
957 | 955 | ||
@@ -963,13 +961,13 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
963 | } else if (status & SRSR_MREQint) { | 961 | } else if (status & SRSR_MREQint) { |
964 | ack = sx_in(bp, CD186x_MRAR); | 962 | ack = sx_in(bp, CD186x_MRAR); |
965 | 963 | ||
966 | if (ack == (SX_ID | GIVR_IT_MODEM)) | 964 | if (ack == (SX_ID | GIVR_IT_MODEM)) |
967 | sx_check_modem(bp); | 965 | sx_check_modem(bp); |
968 | else | 966 | else |
969 | printk(KERN_ERR "sx%d: status: 0x%x Bad modem ack 0x%02x.\n", | 967 | printk(KERN_ERR "sx%d: status: 0x%x Bad modem ack 0x%02x.\n", |
970 | board_No(bp), status, ack); | 968 | board_No(bp), status, ack); |
971 | 969 | ||
972 | } | 970 | } |
973 | 971 | ||
974 | sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */ | 972 | sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */ |
975 | } | 973 | } |
@@ -1026,7 +1024,7 @@ static inline int sx_setup_board(struct specialix_board * bp) | |||
1026 | { | 1024 | { |
1027 | int error; | 1025 | int error; |
1028 | 1026 | ||
1029 | if (bp->flags & SX_BOARD_ACTIVE) | 1027 | if (bp->flags & SX_BOARD_ACTIVE) |
1030 | return 0; | 1028 | return 0; |
1031 | 1029 | ||
1032 | if (bp->flags & SX_BOARD_IS_PCI) | 1030 | if (bp->flags & SX_BOARD_IS_PCI) |
@@ -1034,7 +1032,7 @@ static inline int sx_setup_board(struct specialix_board * bp) | |||
1034 | else | 1032 | else |
1035 | error = request_irq(bp->irq, sx_interrupt, SA_INTERRUPT, "specialix IO8+", bp); | 1033 | error = request_irq(bp->irq, sx_interrupt, SA_INTERRUPT, "specialix IO8+", bp); |
1036 | 1034 | ||
1037 | if (error) | 1035 | if (error) |
1038 | return error; | 1036 | return error; |
1039 | 1037 | ||
1040 | turn_ints_on (bp); | 1038 | turn_ints_on (bp); |
@@ -1055,7 +1053,7 @@ static inline void sx_shutdown_board(struct specialix_board *bp) | |||
1055 | } | 1053 | } |
1056 | 1054 | ||
1057 | bp->flags &= ~SX_BOARD_ACTIVE; | 1055 | bp->flags &= ~SX_BOARD_ACTIVE; |
1058 | 1056 | ||
1059 | dprintk (SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n", | 1057 | dprintk (SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n", |
1060 | bp->irq, board_No (bp)); | 1058 | bp->irq, board_No (bp)); |
1061 | free_irq(bp->irq, bp); | 1059 | free_irq(bp->irq, bp); |
@@ -1068,7 +1066,7 @@ static inline void sx_shutdown_board(struct specialix_board *bp) | |||
1068 | 1066 | ||
1069 | 1067 | ||
1070 | /* | 1068 | /* |
1071 | * Setting up port characteristics. | 1069 | * Setting up port characteristics. |
1072 | * Must be called with disabled interrupts | 1070 | * Must be called with disabled interrupts |
1073 | */ | 1071 | */ |
1074 | static void sx_change_speed(struct specialix_board *bp, struct specialix_port *port) | 1072 | static void sx_change_speed(struct specialix_board *bp, struct specialix_port *port) |
@@ -1103,10 +1101,10 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1103 | spin_unlock_irqrestore(&bp->lock, flags); | 1101 | spin_unlock_irqrestore(&bp->lock, flags); |
1104 | dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR); | 1102 | dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR); |
1105 | baud = C_BAUD(tty); | 1103 | baud = C_BAUD(tty); |
1106 | 1104 | ||
1107 | if (baud & CBAUDEX) { | 1105 | if (baud & CBAUDEX) { |
1108 | baud &= ~CBAUDEX; | 1106 | baud &= ~CBAUDEX; |
1109 | if (baud < 1 || baud > 2) | 1107 | if (baud < 1 || baud > 2) |
1110 | port->tty->termios->c_cflag &= ~CBAUDEX; | 1108 | port->tty->termios->c_cflag &= ~CBAUDEX; |
1111 | else | 1109 | else |
1112 | baud += 15; | 1110 | baud += 15; |
@@ -1117,8 +1115,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1117 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) | 1115 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) |
1118 | baud += 2; | 1116 | baud += 2; |
1119 | } | 1117 | } |
1120 | 1118 | ||
1121 | 1119 | ||
1122 | if (!baud_table[baud]) { | 1120 | if (!baud_table[baud]) { |
1123 | /* Drop DTR & exit */ | 1121 | /* Drop DTR & exit */ |
1124 | dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n"); | 1122 | dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n"); |
@@ -1127,7 +1125,7 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1127 | spin_lock_irqsave(&bp->lock, flags); | 1125 | spin_lock_irqsave(&bp->lock, flags); |
1128 | sx_out(bp, CD186x_MSVR, port->MSVR ); | 1126 | sx_out(bp, CD186x_MSVR, port->MSVR ); |
1129 | spin_unlock_irqrestore(&bp->lock, flags); | 1127 | spin_unlock_irqrestore(&bp->lock, flags); |
1130 | } | 1128 | } |
1131 | else | 1129 | else |
1132 | dprintk (SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n"); | 1130 | dprintk (SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n"); |
1133 | return; | 1131 | return; |
@@ -1137,9 +1135,9 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1137 | port ->MSVR |= MSVR_DTR; | 1135 | port ->MSVR |= MSVR_DTR; |
1138 | } | 1136 | } |
1139 | } | 1137 | } |
1140 | 1138 | ||
1141 | /* | 1139 | /* |
1142 | * Now we must calculate some speed depended things | 1140 | * Now we must calculate some speed depended things |
1143 | */ | 1141 | */ |
1144 | 1142 | ||
1145 | /* Set baud rate for port */ | 1143 | /* Set baud rate for port */ |
@@ -1152,7 +1150,7 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1152 | tmp = (((SX_OSCFREQ + baud_table[baud]/2) / baud_table[baud] + | 1150 | tmp = (((SX_OSCFREQ + baud_table[baud]/2) / baud_table[baud] + |
1153 | CD186x_TPC/2) / CD186x_TPC); | 1151 | CD186x_TPC/2) / CD186x_TPC); |
1154 | 1152 | ||
1155 | if ((tmp < 0x10) && time_before(again, jiffies)) { | 1153 | if ((tmp < 0x10) && time_before(again, jiffies)) { |
1156 | again = jiffies + HZ * 60; | 1154 | again = jiffies + HZ * 60; |
1157 | /* Page 48 of version 2.0 of the CL-CD1865 databook */ | 1155 | /* Page 48 of version 2.0 of the CL-CD1865 databook */ |
1158 | if (tmp >= 12) { | 1156 | if (tmp >= 12) { |
@@ -1164,27 +1162,27 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1164 | printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n" | 1162 | printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n" |
1165 | "Warning: overstressing Cirrus chip. " | 1163 | "Warning: overstressing Cirrus chip. " |
1166 | "This might not work.\n" | 1164 | "This might not work.\n" |
1167 | "Read specialix.txt for more info.\n", | 1165 | "Read specialix.txt for more info.\n", |
1168 | port_No (port), tmp); | 1166 | port_No (port), tmp); |
1169 | } | 1167 | } |
1170 | } | 1168 | } |
1171 | spin_lock_irqsave(&bp->lock, flags); | 1169 | spin_lock_irqsave(&bp->lock, flags); |
1172 | sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff); | 1170 | sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff); |
1173 | sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff); | 1171 | sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff); |
1174 | sx_out(bp, CD186x_RBPRL, tmp & 0xff); | 1172 | sx_out(bp, CD186x_RBPRL, tmp & 0xff); |
1175 | sx_out(bp, CD186x_TBPRL, tmp & 0xff); | 1173 | sx_out(bp, CD186x_TBPRL, tmp & 0xff); |
1176 | spin_unlock_irqrestore(&bp->lock, flags); | 1174 | spin_unlock_irqrestore(&bp->lock, flags); |
1177 | if (port->custom_divisor) { | 1175 | if (port->custom_divisor) { |
1178 | baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor; | 1176 | baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor; |
1179 | baud = ( baud + 5 ) / 10; | 1177 | baud = ( baud + 5 ) / 10; |
1180 | } else | 1178 | } else |
1181 | baud = (baud_table[baud] + 5) / 10; /* Estimated CPS */ | 1179 | baud = (baud_table[baud] + 5) / 10; /* Estimated CPS */ |
1182 | 1180 | ||
1183 | /* Two timer ticks seems enough to wakeup something like SLIP driver */ | 1181 | /* Two timer ticks seems enough to wakeup something like SLIP driver */ |
1184 | tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO; | 1182 | tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO; |
1185 | port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ? | 1183 | port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ? |
1186 | SERIAL_XMIT_SIZE - 1 : tmp); | 1184 | SERIAL_XMIT_SIZE - 1 : tmp); |
1187 | 1185 | ||
1188 | /* Receiver timeout will be transmission time for 1.5 chars */ | 1186 | /* Receiver timeout will be transmission time for 1.5 chars */ |
1189 | tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud; | 1187 | tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud; |
1190 | tmp = (tmp > 0xff) ? 0xff : tmp; | 1188 | tmp = (tmp > 0xff) ? 0xff : tmp; |
@@ -1205,29 +1203,29 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1205 | cor1 |= COR1_8BITS; | 1203 | cor1 |= COR1_8BITS; |
1206 | break; | 1204 | break; |
1207 | } | 1205 | } |
1208 | 1206 | ||
1209 | if (C_CSTOPB(tty)) | 1207 | if (C_CSTOPB(tty)) |
1210 | cor1 |= COR1_2SB; | 1208 | cor1 |= COR1_2SB; |
1211 | 1209 | ||
1212 | cor1 |= COR1_IGNORE; | 1210 | cor1 |= COR1_IGNORE; |
1213 | if (C_PARENB(tty)) { | 1211 | if (C_PARENB(tty)) { |
1214 | cor1 |= COR1_NORMPAR; | 1212 | cor1 |= COR1_NORMPAR; |
1215 | if (C_PARODD(tty)) | 1213 | if (C_PARODD(tty)) |
1216 | cor1 |= COR1_ODDP; | 1214 | cor1 |= COR1_ODDP; |
1217 | if (I_INPCK(tty)) | 1215 | if (I_INPCK(tty)) |
1218 | cor1 &= ~COR1_IGNORE; | 1216 | cor1 &= ~COR1_IGNORE; |
1219 | } | 1217 | } |
1220 | /* Set marking of some errors */ | 1218 | /* Set marking of some errors */ |
1221 | port->mark_mask = RCSR_OE | RCSR_TOUT; | 1219 | port->mark_mask = RCSR_OE | RCSR_TOUT; |
1222 | if (I_INPCK(tty)) | 1220 | if (I_INPCK(tty)) |
1223 | port->mark_mask |= RCSR_FE | RCSR_PE; | 1221 | port->mark_mask |= RCSR_FE | RCSR_PE; |
1224 | if (I_BRKINT(tty) || I_PARMRK(tty)) | 1222 | if (I_BRKINT(tty) || I_PARMRK(tty)) |
1225 | port->mark_mask |= RCSR_BREAK; | 1223 | port->mark_mask |= RCSR_BREAK; |
1226 | if (I_IGNPAR(tty)) | 1224 | if (I_IGNPAR(tty)) |
1227 | port->mark_mask &= ~(RCSR_FE | RCSR_PE); | 1225 | port->mark_mask &= ~(RCSR_FE | RCSR_PE); |
1228 | if (I_IGNBRK(tty)) { | 1226 | if (I_IGNBRK(tty)) { |
1229 | port->mark_mask &= ~RCSR_BREAK; | 1227 | port->mark_mask &= ~RCSR_BREAK; |
1230 | if (I_IGNPAR(tty)) | 1228 | if (I_IGNPAR(tty)) |
1231 | /* Real raw mode. Ignore all */ | 1229 | /* Real raw mode. Ignore all */ |
1232 | port->mark_mask &= ~RCSR_OE; | 1230 | port->mark_mask &= ~RCSR_OE; |
1233 | } | 1231 | } |
@@ -1241,7 +1239,7 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1241 | tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & (MSVR_CTS|MSVR_DSR)); | 1239 | tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & (MSVR_CTS|MSVR_DSR)); |
1242 | spin_unlock_irqrestore(&bp->lock, flags); | 1240 | spin_unlock_irqrestore(&bp->lock, flags); |
1243 | #else | 1241 | #else |
1244 | port->COR2 |= COR2_CTSAE; | 1242 | port->COR2 |= COR2_CTSAE; |
1245 | #endif | 1243 | #endif |
1246 | } | 1244 | } |
1247 | /* Enable Software Flow Control. FIXME: I'm not sure about this */ | 1245 | /* Enable Software Flow Control. FIXME: I'm not sure about this */ |
@@ -1264,11 +1262,11 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1264 | mcor1 |= MCOR1_CDZD; | 1262 | mcor1 |= MCOR1_CDZD; |
1265 | mcor2 |= MCOR2_CDOD; | 1263 | mcor2 |= MCOR2_CDOD; |
1266 | } | 1264 | } |
1267 | 1265 | ||
1268 | if (C_CREAD(tty)) | 1266 | if (C_CREAD(tty)) |
1269 | /* Enable receiver */ | 1267 | /* Enable receiver */ |
1270 | port->IER |= IER_RXD; | 1268 | port->IER |= IER_RXD; |
1271 | 1269 | ||
1272 | /* Set input FIFO size (1-8 bytes) */ | 1270 | /* Set input FIFO size (1-8 bytes) */ |
1273 | cor3 |= sx_rxfifo; | 1271 | cor3 |= sx_rxfifo; |
1274 | /* Setting up CD186x channel registers */ | 1272 | /* Setting up CD186x channel registers */ |
@@ -1311,11 +1309,11 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port | |||
1311 | func_exit(); | 1309 | func_exit(); |
1312 | return 0; | 1310 | return 0; |
1313 | } | 1311 | } |
1314 | 1312 | ||
1315 | if (!port->xmit_buf) { | 1313 | if (!port->xmit_buf) { |
1316 | /* We may sleep in get_zeroed_page() */ | 1314 | /* We may sleep in get_zeroed_page() */ |
1317 | unsigned long tmp; | 1315 | unsigned long tmp; |
1318 | 1316 | ||
1319 | if (!(tmp = get_zeroed_page(GFP_KERNEL))) { | 1317 | if (!(tmp = get_zeroed_page(GFP_KERNEL))) { |
1320 | func_exit(); | 1318 | func_exit(); |
1321 | return -ENOMEM; | 1319 | return -ENOMEM; |
@@ -1328,10 +1326,10 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port | |||
1328 | } | 1326 | } |
1329 | port->xmit_buf = (unsigned char *) tmp; | 1327 | port->xmit_buf = (unsigned char *) tmp; |
1330 | } | 1328 | } |
1331 | 1329 | ||
1332 | spin_lock_irqsave(&port->lock, flags); | 1330 | spin_lock_irqsave(&port->lock, flags); |
1333 | 1331 | ||
1334 | if (port->tty) | 1332 | if (port->tty) |
1335 | clear_bit(TTY_IO_ERROR, &port->tty->flags); | 1333 | clear_bit(TTY_IO_ERROR, &port->tty->flags); |
1336 | 1334 | ||
1337 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; | 1335 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; |
@@ -1340,7 +1338,7 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port | |||
1340 | 1338 | ||
1341 | spin_unlock_irqrestore(&port->lock, flags); | 1339 | spin_unlock_irqrestore(&port->lock, flags); |
1342 | 1340 | ||
1343 | 1341 | ||
1344 | func_exit(); | 1342 | func_exit(); |
1345 | return 0; | 1343 | return 0; |
1346 | } | 1344 | } |
@@ -1352,14 +1350,14 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port * | |||
1352 | struct tty_struct *tty; | 1350 | struct tty_struct *tty; |
1353 | int i; | 1351 | int i; |
1354 | unsigned long flags; | 1352 | unsigned long flags; |
1355 | 1353 | ||
1356 | func_enter(); | 1354 | func_enter(); |
1357 | 1355 | ||
1358 | if (!(port->flags & ASYNC_INITIALIZED)) { | 1356 | if (!(port->flags & ASYNC_INITIALIZED)) { |
1359 | func_exit(); | 1357 | func_exit(); |
1360 | return; | 1358 | return; |
1361 | } | 1359 | } |
1362 | 1360 | ||
1363 | if (sx_debug & SX_DEBUG_FIFO) { | 1361 | if (sx_debug & SX_DEBUG_FIFO) { |
1364 | dprintk(SX_DEBUG_FIFO, "sx%d: port %d: %ld overruns, FIFO hits [ ", | 1362 | dprintk(SX_DEBUG_FIFO, "sx%d: port %d: %ld overruns, FIFO hits [ ", |
1365 | board_No(bp), port_No(port), port->overrun); | 1363 | board_No(bp), port_No(port), port->overrun); |
@@ -1394,13 +1392,13 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port * | |||
1394 | if (tty) | 1392 | if (tty) |
1395 | set_bit(TTY_IO_ERROR, &tty->flags); | 1393 | set_bit(TTY_IO_ERROR, &tty->flags); |
1396 | port->flags &= ~ASYNC_INITIALIZED; | 1394 | port->flags &= ~ASYNC_INITIALIZED; |
1397 | 1395 | ||
1398 | if (!bp->count) | 1396 | if (!bp->count) |
1399 | sx_shutdown_board(bp); | 1397 | sx_shutdown_board(bp); |
1400 | func_exit(); | 1398 | func_exit(); |
1401 | } | 1399 | } |
1402 | 1400 | ||
1403 | 1401 | ||
1404 | static int block_til_ready(struct tty_struct *tty, struct file * filp, | 1402 | static int block_til_ready(struct tty_struct *tty, struct file * filp, |
1405 | struct specialix_port *port) | 1403 | struct specialix_port *port) |
1406 | { | 1404 | { |
@@ -1427,7 +1425,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
1427 | return -ERESTARTSYS; | 1425 | return -ERESTARTSYS; |
1428 | } | 1426 | } |
1429 | } | 1427 | } |
1430 | 1428 | ||
1431 | /* | 1429 | /* |
1432 | * If non-blocking mode is set, or the port is not enabled, | 1430 | * If non-blocking mode is set, or the port is not enabled, |
1433 | * then make the check up front and then exit. | 1431 | * then make the check up front and then exit. |
@@ -1477,7 +1475,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
1477 | if (port->flags & ASYNC_HUP_NOTIFY) | 1475 | if (port->flags & ASYNC_HUP_NOTIFY) |
1478 | retval = -EAGAIN; | 1476 | retval = -EAGAIN; |
1479 | else | 1477 | else |
1480 | retval = -ERESTARTSYS; | 1478 | retval = -ERESTARTSYS; |
1481 | break; | 1479 | break; |
1482 | } | 1480 | } |
1483 | if (!(port->flags & ASYNC_CLOSING) && | 1481 | if (!(port->flags & ASYNC_CLOSING) && |
@@ -1506,7 +1504,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
1506 | port->flags |= ASYNC_NORMAL_ACTIVE; | 1504 | port->flags |= ASYNC_NORMAL_ACTIVE; |
1507 | func_exit(); | 1505 | func_exit(); |
1508 | return 0; | 1506 | return 0; |
1509 | } | 1507 | } |
1510 | 1508 | ||
1511 | 1509 | ||
1512 | static int sx_open(struct tty_struct * tty, struct file * filp) | 1510 | static int sx_open(struct tty_struct * tty, struct file * filp) |
@@ -1526,7 +1524,7 @@ static int sx_open(struct tty_struct * tty, struct file * filp) | |||
1526 | func_exit(); | 1524 | func_exit(); |
1527 | return -ENODEV; | 1525 | return -ENODEV; |
1528 | } | 1526 | } |
1529 | 1527 | ||
1530 | bp = &sx_board[board]; | 1528 | bp = &sx_board[board]; |
1531 | port = sx_port + board * SX_NPORT + SX_PORT(tty->index); | 1529 | port = sx_port + board * SX_NPORT + SX_PORT(tty->index); |
1532 | port->overrun = 0; | 1530 | port->overrun = 0; |
@@ -1557,7 +1555,7 @@ static int sx_open(struct tty_struct * tty, struct file * filp) | |||
1557 | func_enter(); | 1555 | func_enter(); |
1558 | return error; | 1556 | return error; |
1559 | } | 1557 | } |
1560 | 1558 | ||
1561 | if ((error = block_til_ready(tty, filp, port))) { | 1559 | if ((error = block_til_ready(tty, filp, port))) { |
1562 | func_enter(); | 1560 | func_enter(); |
1563 | return error; | 1561 | return error; |
@@ -1574,7 +1572,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp) | |||
1574 | struct specialix_board *bp; | 1572 | struct specialix_board *bp; |
1575 | unsigned long flags; | 1573 | unsigned long flags; |
1576 | unsigned long timeout; | 1574 | unsigned long timeout; |
1577 | 1575 | ||
1578 | func_enter(); | 1576 | func_enter(); |
1579 | if (!port || sx_paranoia_check(port, tty->name, "close")) { | 1577 | if (!port || sx_paranoia_check(port, tty->name, "close")) { |
1580 | func_exit(); | 1578 | func_exit(); |
@@ -1587,7 +1585,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp) | |||
1587 | func_exit(); | 1585 | func_exit(); |
1588 | return; | 1586 | return; |
1589 | } | 1587 | } |
1590 | 1588 | ||
1591 | bp = port_Board(port); | 1589 | bp = port_Board(port); |
1592 | if ((tty->count == 1) && (port->count != 1)) { | 1590 | if ((tty->count == 1) && (port->count != 1)) { |
1593 | printk(KERN_ERR "sx%d: sx_close: bad port count;" | 1591 | printk(KERN_ERR "sx%d: sx_close: bad port count;" |
@@ -1607,7 +1605,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp) | |||
1607 | } | 1605 | } |
1608 | port->flags |= ASYNC_CLOSING; | 1606 | port->flags |= ASYNC_CLOSING; |
1609 | /* | 1607 | /* |
1610 | * Now we wait for the transmit buffer to clear; and we notify | 1608 | * Now we wait for the transmit buffer to clear; and we notify |
1611 | * the line discipline to only process XON/XOFF characters. | 1609 | * the line discipline to only process XON/XOFF characters. |
1612 | */ | 1610 | */ |
1613 | tty->closing = 1; | 1611 | tty->closing = 1; |
@@ -1681,7 +1679,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp) | |||
1681 | } | 1679 | } |
1682 | 1680 | ||
1683 | 1681 | ||
1684 | static int sx_write(struct tty_struct * tty, | 1682 | static int sx_write(struct tty_struct * tty, |
1685 | const unsigned char *buf, int count) | 1683 | const unsigned char *buf, int count) |
1686 | { | 1684 | { |
1687 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1685 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
@@ -1694,7 +1692,7 @@ static int sx_write(struct tty_struct * tty, | |||
1694 | func_exit(); | 1692 | func_exit(); |
1695 | return 0; | 1693 | return 0; |
1696 | } | 1694 | } |
1697 | 1695 | ||
1698 | bp = port_Board(port); | 1696 | bp = port_Board(port); |
1699 | 1697 | ||
1700 | if (!tty || !port->xmit_buf || !tmp_buf) { | 1698 | if (!tty || !port->xmit_buf || !tmp_buf) { |
@@ -1824,7 +1822,7 @@ static int sx_chars_in_buffer(struct tty_struct *tty) | |||
1824 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1822 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
1825 | 1823 | ||
1826 | func_enter(); | 1824 | func_enter(); |
1827 | 1825 | ||
1828 | if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer")) { | 1826 | if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer")) { |
1829 | func_exit(); | 1827 | func_exit(); |
1830 | return 0; | 1828 | return 0; |
@@ -1881,13 +1879,13 @@ static int sx_tiocmget(struct tty_struct *tty, struct file *file) | |||
1881 | port_No(port), status, sx_in (bp, CD186x_CAR)); | 1879 | port_No(port), status, sx_in (bp, CD186x_CAR)); |
1882 | dprintk (SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port); | 1880 | dprintk (SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port); |
1883 | if (SX_CRTSCTS(port->tty)) { | 1881 | if (SX_CRTSCTS(port->tty)) { |
1884 | result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */ | 1882 | result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */ |
1885 | | ((status & MSVR_DTR) ? TIOCM_RTS : 0) | 1883 | | ((status & MSVR_DTR) ? TIOCM_RTS : 0) |
1886 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) | 1884 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) |
1887 | |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */ | 1885 | |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */ |
1888 | | ((status & MSVR_CTS) ? TIOCM_CTS : 0); | 1886 | | ((status & MSVR_CTS) ? TIOCM_CTS : 0); |
1889 | } else { | 1887 | } else { |
1890 | result = /* (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */ | 1888 | result = /* (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */ |
1891 | | ((status & MSVR_DTR) ? TIOCM_DTR : 0) | 1889 | | ((status & MSVR_DTR) ? TIOCM_DTR : 0) |
1892 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) | 1890 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) |
1893 | |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */ | 1891 | |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */ |
@@ -1955,7 +1953,7 @@ static inline void sx_send_break(struct specialix_port * port, unsigned long len | |||
1955 | { | 1953 | { |
1956 | struct specialix_board *bp = port_Board(port); | 1954 | struct specialix_board *bp = port_Board(port); |
1957 | unsigned long flags; | 1955 | unsigned long flags; |
1958 | 1956 | ||
1959 | func_enter(); | 1957 | func_enter(); |
1960 | 1958 | ||
1961 | spin_lock_irqsave (&port->lock, flags); | 1959 | spin_lock_irqsave (&port->lock, flags); |
@@ -1996,8 +1994,8 @@ static inline int sx_set_serial_info(struct specialix_port * port, | |||
1996 | func_enter(); | 1994 | func_enter(); |
1997 | return -EFAULT; | 1995 | return -EFAULT; |
1998 | } | 1996 | } |
1999 | 1997 | ||
2000 | #if 0 | 1998 | #if 0 |
2001 | if ((tmp.irq != bp->irq) || | 1999 | if ((tmp.irq != bp->irq) || |
2002 | (tmp.port != bp->base) || | 2000 | (tmp.port != bp->base) || |
2003 | (tmp.type != PORT_CIRRUS) || | 2001 | (tmp.type != PORT_CIRRUS) || |
@@ -2008,12 +2006,12 @@ static inline int sx_set_serial_info(struct specialix_port * port, | |||
2008 | func_exit(); | 2006 | func_exit(); |
2009 | return -EINVAL; | 2007 | return -EINVAL; |
2010 | } | 2008 | } |
2011 | #endif | 2009 | #endif |
2012 | 2010 | ||
2013 | change_speed = ((port->flags & ASYNC_SPD_MASK) != | 2011 | change_speed = ((port->flags & ASYNC_SPD_MASK) != |
2014 | (tmp.flags & ASYNC_SPD_MASK)); | 2012 | (tmp.flags & ASYNC_SPD_MASK)); |
2015 | change_speed |= (tmp.custom_divisor != port->custom_divisor); | 2013 | change_speed |= (tmp.custom_divisor != port->custom_divisor); |
2016 | 2014 | ||
2017 | if (!capable(CAP_SYS_ADMIN)) { | 2015 | if (!capable(CAP_SYS_ADMIN)) { |
2018 | if ((tmp.close_delay != port->close_delay) || | 2016 | if ((tmp.close_delay != port->close_delay) || |
2019 | (tmp.closing_wait != port->closing_wait) || | 2017 | (tmp.closing_wait != port->closing_wait) || |
@@ -2045,7 +2043,7 @@ static inline int sx_get_serial_info(struct specialix_port * port, | |||
2045 | { | 2043 | { |
2046 | struct serial_struct tmp; | 2044 | struct serial_struct tmp; |
2047 | struct specialix_board *bp = port_Board(port); | 2045 | struct specialix_board *bp = port_Board(port); |
2048 | 2046 | ||
2049 | func_enter(); | 2047 | func_enter(); |
2050 | 2048 | ||
2051 | /* | 2049 | /* |
@@ -2074,7 +2072,7 @@ static inline int sx_get_serial_info(struct specialix_port * port, | |||
2074 | } | 2072 | } |
2075 | 2073 | ||
2076 | 2074 | ||
2077 | static int sx_ioctl(struct tty_struct * tty, struct file * filp, | 2075 | static int sx_ioctl(struct tty_struct * tty, struct file * filp, |
2078 | unsigned int cmd, unsigned long arg) | 2076 | unsigned int cmd, unsigned long arg) |
2079 | { | 2077 | { |
2080 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2078 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
@@ -2087,7 +2085,7 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp, | |||
2087 | func_exit(); | 2085 | func_exit(); |
2088 | return -ENODEV; | 2086 | return -ENODEV; |
2089 | } | 2087 | } |
2090 | 2088 | ||
2091 | switch (cmd) { | 2089 | switch (cmd) { |
2092 | case TCSBRK: /* SVID version: non-zero arg --> no break */ | 2090 | case TCSBRK: /* SVID version: non-zero arg --> no break */ |
2093 | retval = tty_check_change(tty); | 2091 | retval = tty_check_change(tty); |
@@ -2129,7 +2127,7 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp, | |||
2129 | case TIOCGSERIAL: | 2127 | case TIOCGSERIAL: |
2130 | func_exit(); | 2128 | func_exit(); |
2131 | return sx_get_serial_info(port, argp); | 2129 | return sx_get_serial_info(port, argp); |
2132 | case TIOCSSERIAL: | 2130 | case TIOCSSERIAL: |
2133 | func_exit(); | 2131 | func_exit(); |
2134 | return sx_set_serial_info(port, argp); | 2132 | return sx_set_serial_info(port, argp); |
2135 | default: | 2133 | default: |
@@ -2153,16 +2151,16 @@ static void sx_throttle(struct tty_struct * tty) | |||
2153 | func_exit(); | 2151 | func_exit(); |
2154 | return; | 2152 | return; |
2155 | } | 2153 | } |
2156 | 2154 | ||
2157 | bp = port_Board(port); | 2155 | bp = port_Board(port); |
2158 | 2156 | ||
2159 | /* Use DTR instead of RTS ! */ | 2157 | /* Use DTR instead of RTS ! */ |
2160 | if (SX_CRTSCTS (tty)) | 2158 | if (SX_CRTSCTS (tty)) |
2161 | port->MSVR &= ~MSVR_DTR; | 2159 | port->MSVR &= ~MSVR_DTR; |
2162 | else { | 2160 | else { |
2163 | /* Auch!!! I think the system shouldn't call this then. */ | 2161 | /* Auch!!! I think the system shouldn't call this then. */ |
2164 | /* Or maybe we're supposed (allowed?) to do our side of hw | 2162 | /* Or maybe we're supposed (allowed?) to do our side of hw |
2165 | handshake anyway, even when hardware handshake is off. | 2163 | handshake anyway, even when hardware handshake is off. |
2166 | When you see this in your logs, please report.... */ | 2164 | When you see this in your logs, please report.... */ |
2167 | printk (KERN_ERR "sx%d: Need to throttle, but can't (hardware hs is off)\n", | 2165 | printk (KERN_ERR "sx%d: Need to throttle, but can't (hardware hs is off)\n", |
2168 | port_No (port)); | 2166 | port_No (port)); |
@@ -2193,14 +2191,14 @@ static void sx_unthrottle(struct tty_struct * tty) | |||
2193 | unsigned long flags; | 2191 | unsigned long flags; |
2194 | 2192 | ||
2195 | func_enter(); | 2193 | func_enter(); |
2196 | 2194 | ||
2197 | if (sx_paranoia_check(port, tty->name, "sx_unthrottle")) { | 2195 | if (sx_paranoia_check(port, tty->name, "sx_unthrottle")) { |
2198 | func_exit(); | 2196 | func_exit(); |
2199 | return; | 2197 | return; |
2200 | } | 2198 | } |
2201 | 2199 | ||
2202 | bp = port_Board(port); | 2200 | bp = port_Board(port); |
2203 | 2201 | ||
2204 | spin_lock_irqsave(&port->lock, flags); | 2202 | spin_lock_irqsave(&port->lock, flags); |
2205 | /* XXXX Use DTR INSTEAD???? */ | 2203 | /* XXXX Use DTR INSTEAD???? */ |
2206 | if (SX_CRTSCTS(tty)) { | 2204 | if (SX_CRTSCTS(tty)) { |
@@ -2234,14 +2232,14 @@ static void sx_stop(struct tty_struct * tty) | |||
2234 | unsigned long flags; | 2232 | unsigned long flags; |
2235 | 2233 | ||
2236 | func_enter(); | 2234 | func_enter(); |
2237 | 2235 | ||
2238 | if (sx_paranoia_check(port, tty->name, "sx_stop")) { | 2236 | if (sx_paranoia_check(port, tty->name, "sx_stop")) { |
2239 | func_exit(); | 2237 | func_exit(); |
2240 | return; | 2238 | return; |
2241 | } | 2239 | } |
2242 | 2240 | ||
2243 | bp = port_Board(port); | 2241 | bp = port_Board(port); |
2244 | 2242 | ||
2245 | spin_lock_irqsave(&port->lock, flags); | 2243 | spin_lock_irqsave(&port->lock, flags); |
2246 | port->IER &= ~IER_TXRDY; | 2244 | port->IER &= ~IER_TXRDY; |
2247 | spin_lock_irqsave(&bp->lock, flags); | 2245 | spin_lock_irqsave(&bp->lock, flags); |
@@ -2261,14 +2259,14 @@ static void sx_start(struct tty_struct * tty) | |||
2261 | unsigned long flags; | 2259 | unsigned long flags; |
2262 | 2260 | ||
2263 | func_enter(); | 2261 | func_enter(); |
2264 | 2262 | ||
2265 | if (sx_paranoia_check(port, tty->name, "sx_start")) { | 2263 | if (sx_paranoia_check(port, tty->name, "sx_start")) { |
2266 | func_exit(); | 2264 | func_exit(); |
2267 | return; | 2265 | return; |
2268 | } | 2266 | } |
2269 | 2267 | ||
2270 | bp = port_Board(port); | 2268 | bp = port_Board(port); |
2271 | 2269 | ||
2272 | spin_lock_irqsave(&port->lock, flags); | 2270 | spin_lock_irqsave(&port->lock, flags); |
2273 | if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) { | 2271 | if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) { |
2274 | port->IER |= IER_TXRDY; | 2272 | port->IER |= IER_TXRDY; |
@@ -2290,13 +2288,13 @@ static void sx_start(struct tty_struct * tty) | |||
2290 | * | 2288 | * |
2291 | * serial interrupt routine -> (workqueue) -> | 2289 | * serial interrupt routine -> (workqueue) -> |
2292 | * do_sx_hangup() -> tty->hangup() -> sx_hangup() | 2290 | * do_sx_hangup() -> tty->hangup() -> sx_hangup() |
2293 | * | 2291 | * |
2294 | */ | 2292 | */ |
2295 | static void do_sx_hangup(void *private_) | 2293 | static void do_sx_hangup(void *private_) |
2296 | { | 2294 | { |
2297 | struct specialix_port *port = (struct specialix_port *) private_; | 2295 | struct specialix_port *port = (struct specialix_port *) private_; |
2298 | struct tty_struct *tty; | 2296 | struct tty_struct *tty; |
2299 | 2297 | ||
2300 | func_enter(); | 2298 | func_enter(); |
2301 | 2299 | ||
2302 | tty = port->tty; | 2300 | tty = port->tty; |
@@ -2319,9 +2317,9 @@ static void sx_hangup(struct tty_struct * tty) | |||
2319 | func_exit(); | 2317 | func_exit(); |
2320 | return; | 2318 | return; |
2321 | } | 2319 | } |
2322 | 2320 | ||
2323 | bp = port_Board(port); | 2321 | bp = port_Board(port); |
2324 | 2322 | ||
2325 | sx_shutdown_port(bp, port); | 2323 | sx_shutdown_port(bp, port); |
2326 | spin_lock_irqsave(&port->lock, flags); | 2324 | spin_lock_irqsave(&port->lock, flags); |
2327 | port->event = 0; | 2325 | port->event = 0; |
@@ -2346,10 +2344,10 @@ static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios | |||
2346 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2344 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
2347 | unsigned long flags; | 2345 | unsigned long flags; |
2348 | struct specialix_board * bp; | 2346 | struct specialix_board * bp; |
2349 | 2347 | ||
2350 | if (sx_paranoia_check(port, tty->name, "sx_set_termios")) | 2348 | if (sx_paranoia_check(port, tty->name, "sx_set_termios")) |
2351 | return; | 2349 | return; |
2352 | 2350 | ||
2353 | if (tty->termios->c_cflag == old_termios->c_cflag && | 2351 | if (tty->termios->c_cflag == old_termios->c_cflag && |
2354 | tty->termios->c_iflag == old_termios->c_iflag) | 2352 | tty->termios->c_iflag == old_termios->c_iflag) |
2355 | return; | 2353 | return; |
@@ -2420,7 +2418,7 @@ static int sx_init_drivers(void) | |||
2420 | func_exit(); | 2418 | func_exit(); |
2421 | return 1; | 2419 | return 1; |
2422 | } | 2420 | } |
2423 | 2421 | ||
2424 | if (!(tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL))) { | 2422 | if (!(tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL))) { |
2425 | printk(KERN_ERR "sx: Couldn't get free page.\n"); | 2423 | printk(KERN_ERR "sx: Couldn't get free page.\n"); |
2426 | put_tty_driver(specialix_driver); | 2424 | put_tty_driver(specialix_driver); |
@@ -2457,7 +2455,7 @@ static int sx_init_drivers(void) | |||
2457 | init_waitqueue_head(&sx_port[i].close_wait); | 2455 | init_waitqueue_head(&sx_port[i].close_wait); |
2458 | spin_lock_init(&sx_port[i].lock); | 2456 | spin_lock_init(&sx_port[i].lock); |
2459 | } | 2457 | } |
2460 | 2458 | ||
2461 | func_exit(); | 2459 | func_exit(); |
2462 | return 0; | 2460 | return 0; |
2463 | } | 2461 | } |
@@ -2472,8 +2470,8 @@ static void sx_release_drivers(void) | |||
2472 | func_exit(); | 2470 | func_exit(); |
2473 | } | 2471 | } |
2474 | 2472 | ||
2475 | /* | 2473 | /* |
2476 | * This routine must be called by kernel at boot time | 2474 | * This routine must be called by kernel at boot time |
2477 | */ | 2475 | */ |
2478 | static int __init specialix_init(void) | 2476 | static int __init specialix_init(void) |
2479 | { | 2477 | { |
@@ -2489,7 +2487,7 @@ static int __init specialix_init(void) | |||
2489 | #else | 2487 | #else |
2490 | printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n"); | 2488 | printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n"); |
2491 | #endif | 2489 | #endif |
2492 | 2490 | ||
2493 | for (i = 0; i < SX_NBOARD; i++) | 2491 | for (i = 0; i < SX_NBOARD; i++) |
2494 | sx_board[i].lock = SPIN_LOCK_UNLOCKED; | 2492 | sx_board[i].lock = SPIN_LOCK_UNLOCKED; |
2495 | 2493 | ||
@@ -2498,7 +2496,7 @@ static int __init specialix_init(void) | |||
2498 | return -EIO; | 2496 | return -EIO; |
2499 | } | 2497 | } |
2500 | 2498 | ||
2501 | for (i = 0; i < SX_NBOARD; i++) | 2499 | for (i = 0; i < SX_NBOARD; i++) |
2502 | if (sx_board[i].base && !sx_probe(&sx_board[i])) | 2500 | if (sx_board[i].base && !sx_probe(&sx_board[i])) |
2503 | found++; | 2501 | found++; |
2504 | 2502 | ||
@@ -2512,8 +2510,8 @@ static int __init specialix_init(void) | |||
2512 | i++; | 2510 | i++; |
2513 | continue; | 2511 | continue; |
2514 | } | 2512 | } |
2515 | pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, | 2513 | pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, |
2516 | PCI_DEVICE_ID_SPECIALIX_IO8, | 2514 | PCI_DEVICE_ID_SPECIALIX_IO8, |
2517 | pdev); | 2515 | pdev); |
2518 | if (!pdev) break; | 2516 | if (!pdev) break; |
2519 | 2517 | ||
@@ -2557,10 +2555,10 @@ module_param(sx_poll, int, 0); | |||
2557 | /* | 2555 | /* |
2558 | * You can setup up to 4 boards. | 2556 | * You can setup up to 4 boards. |
2559 | * by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter. | 2557 | * by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter. |
2560 | * You should specify the IRQs too in that case "irq=....,...". | 2558 | * You should specify the IRQs too in that case "irq=....,...". |
2561 | * | 2559 | * |
2562 | * More than 4 boards in one computer is not possible, as the card can | 2560 | * More than 4 boards in one computer is not possible, as the card can |
2563 | * only use 4 different interrupts. | 2561 | * only use 4 different interrupts. |
2564 | * | 2562 | * |
2565 | */ | 2563 | */ |
2566 | static int __init specialix_init_module(void) | 2564 | static int __init specialix_init_module(void) |
@@ -2583,16 +2581,16 @@ static int __init specialix_init_module(void) | |||
2583 | 2581 | ||
2584 | return specialix_init(); | 2582 | return specialix_init(); |
2585 | } | 2583 | } |
2586 | 2584 | ||
2587 | static void __exit specialix_exit_module(void) | 2585 | static void __exit specialix_exit_module(void) |
2588 | { | 2586 | { |
2589 | int i; | 2587 | int i; |
2590 | 2588 | ||
2591 | func_enter(); | 2589 | func_enter(); |
2592 | 2590 | ||
2593 | sx_release_drivers(); | 2591 | sx_release_drivers(); |
2594 | for (i = 0; i < SX_NBOARD; i++) | 2592 | for (i = 0; i < SX_NBOARD; i++) |
2595 | if (sx_board[i].flags & SX_BOARD_PRESENT) | 2593 | if (sx_board[i].flags & SX_BOARD_PRESENT) |
2596 | sx_release_io_range(&sx_board[i]); | 2594 | sx_release_io_range(&sx_board[i]); |
2597 | #ifdef SPECIALIX_TIMER | 2595 | #ifdef SPECIALIX_TIMER |
2598 | del_timer (&missed_irq_timer); | 2596 | del_timer (&missed_irq_timer); |