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