diff options
| author | Maciej W. Rozycki <macro@linux-mips.org> | 2005-06-13 15:58:50 -0400 |
|---|---|---|
| committer | Ralf Baechle <ralf@linux-mips.org> | 2005-11-17 11:23:39 -0500 |
| commit | 0905780aae58ea69f2dafea9716ee2ea78dbe4e2 (patch) | |
| tree | 8285d824fce3959edb64af5fbc2511cd549321e4 /drivers/tc | |
| parent | e0c9b7973021ea4baa1ed76ff25ceb80f75edd8f (diff) | |
[MIPS] zs.c: Resurrect the deceased zs.c for now.
Not that it's meant to be sustained for long, but from time to time it's
useful to have some console...
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers/tc')
| -rw-r--r-- | drivers/tc/zs.c | 150 | ||||
| -rw-r--r-- | drivers/tc/zs.h | 13 |
2 files changed, 70 insertions, 93 deletions
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c index c52af73a251b..6756d0fab6fe 100644 --- a/drivers/tc/zs.c +++ b/drivers/tc/zs.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * | 6 | * |
| 7 | * DECstation changes | 7 | * DECstation changes |
| 8 | * Copyright (C) 1998-2000 Harald Koerfgen | 8 | * Copyright (C) 1998-2000 Harald Koerfgen |
| 9 | * Copyright (C) 2000, 2001, 2002, 2003, 2004 Maciej W. Rozycki | 9 | * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Maciej W. Rozycki |
| 10 | * | 10 | * |
| 11 | * For the rest of the code the original Copyright applies: | 11 | * For the rest of the code the original Copyright applies: |
| 12 | * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) | 12 | * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) |
| @@ -55,6 +55,7 @@ | |||
| 55 | #include <linux/delay.h> | 55 | #include <linux/delay.h> |
| 56 | #include <linux/init.h> | 56 | #include <linux/init.h> |
| 57 | #include <linux/ioport.h> | 57 | #include <linux/ioport.h> |
| 58 | #include <linux/spinlock.h> | ||
| 58 | #ifdef CONFIG_SERIAL_DEC_CONSOLE | 59 | #ifdef CONFIG_SERIAL_DEC_CONSOLE |
| 59 | #include <linux/console.h> | 60 | #include <linux/console.h> |
| 60 | #endif | 61 | #endif |
| @@ -63,7 +64,6 @@ | |||
| 63 | #include <asm/pgtable.h> | 64 | #include <asm/pgtable.h> |
| 64 | #include <asm/irq.h> | 65 | #include <asm/irq.h> |
| 65 | #include <asm/system.h> | 66 | #include <asm/system.h> |
| 66 | #include <asm/uaccess.h> | ||
| 67 | #include <asm/bootinfo.h> | 67 | #include <asm/bootinfo.h> |
| 68 | 68 | ||
| 69 | #include <asm/dec/interrupts.h> | 69 | #include <asm/dec/interrupts.h> |
| @@ -128,6 +128,8 @@ static struct zs_parms ds_parms = { | |||
| 128 | 128 | ||
| 129 | #define BUS_PRESENT (DS_BUS_PRESENT) | 129 | #define BUS_PRESENT (DS_BUS_PRESENT) |
| 130 | 130 | ||
| 131 | DEFINE_SPINLOCK(zs_lock); | ||
| 132 | |||
| 131 | struct dec_zschannel zs_channels[NUM_CHANNELS]; | 133 | struct dec_zschannel zs_channels[NUM_CHANNELS]; |
| 132 | struct dec_serial zs_soft[NUM_CHANNELS]; | 134 | struct dec_serial zs_soft[NUM_CHANNELS]; |
| 133 | int zs_channels_found; | 135 | int zs_channels_found; |
| @@ -159,8 +161,6 @@ static unsigned char zs_init_regs[16] __initdata = { | |||
| 159 | 0 /* write 15 */ | 161 | 0 /* write 15 */ |
| 160 | }; | 162 | }; |
| 161 | 163 | ||
| 162 | DECLARE_TASK_QUEUE(tq_zs_serial); | ||
| 163 | |||
| 164 | static struct tty_driver *serial_driver; | 164 | static struct tty_driver *serial_driver; |
| 165 | 165 | ||
| 166 | /* serial subtype definitions */ | 166 | /* serial subtype definitions */ |
| @@ -294,8 +294,7 @@ static inline void zs_rtsdtr(struct dec_serial *info, int which, int set) | |||
| 294 | { | 294 | { |
| 295 | unsigned long flags; | 295 | unsigned long flags; |
| 296 | 296 | ||
| 297 | 297 | spin_lock_irqsave(&zs_lock, flags); | |
| 298 | save_flags(flags); cli(); | ||
| 299 | if (info->zs_channel != info->zs_chan_a) { | 298 | if (info->zs_channel != info->zs_chan_a) { |
| 300 | if (set) { | 299 | if (set) { |
| 301 | info->zs_chan_a->curregs[5] |= (which & (RTS | DTR)); | 300 | info->zs_chan_a->curregs[5] |= (which & (RTS | DTR)); |
| @@ -304,7 +303,7 @@ static inline void zs_rtsdtr(struct dec_serial *info, int which, int set) | |||
| 304 | } | 303 | } |
| 305 | write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); | 304 | write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); |
| 306 | } | 305 | } |
| 307 | restore_flags(flags); | 306 | spin_unlock_irqrestore(&zs_lock, flags); |
| 308 | } | 307 | } |
| 309 | 308 | ||
| 310 | /* Utility routines for the Zilog */ | 309 | /* Utility routines for the Zilog */ |
| @@ -345,12 +344,10 @@ static inline void rs_recv_clear(struct dec_zschannel *zsc) | |||
| 345 | * This routine is used by the interrupt handler to schedule | 344 | * This routine is used by the interrupt handler to schedule |
| 346 | * processing in the software interrupt portion of the driver. | 345 | * processing in the software interrupt portion of the driver. |
| 347 | */ | 346 | */ |
| 348 | static _INLINE_ void rs_sched_event(struct dec_serial *info, | 347 | static _INLINE_ void rs_sched_event(struct dec_serial *info, int event) |
| 349 | int event) | ||
| 350 | { | 348 | { |
| 351 | info->event |= 1 << event; | 349 | info->event |= 1 << event; |
| 352 | queue_task(&info->tqueue, &tq_zs_serial); | 350 | tasklet_schedule(&info->tlet); |
| 353 | mark_bh(SERIAL_BH); | ||
| 354 | } | 351 | } |
| 355 | 352 | ||
| 356 | static _INLINE_ void receive_chars(struct dec_serial *info, | 353 | static _INLINE_ void receive_chars(struct dec_serial *info, |
| @@ -497,9 +494,10 @@ static _INLINE_ void status_handle(struct dec_serial *info) | |||
| 497 | /* | 494 | /* |
| 498 | * This is the serial driver's generic interrupt routine | 495 | * This is the serial driver's generic interrupt routine |
| 499 | */ | 496 | */ |
| 500 | void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) | 497 | static irqreturn_t rs_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
| 501 | { | 498 | { |
| 502 | struct dec_serial *info = (struct dec_serial *) dev_id; | 499 | struct dec_serial *info = (struct dec_serial *) dev_id; |
| 500 | irqreturn_t status = IRQ_NONE; | ||
| 503 | unsigned char zs_intreg; | 501 | unsigned char zs_intreg; |
| 504 | int shift; | 502 | int shift; |
| 505 | 503 | ||
| @@ -521,6 +519,8 @@ void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) | |||
| 521 | if ((zs_intreg & CHAN_IRQMASK) == 0) | 519 | if ((zs_intreg & CHAN_IRQMASK) == 0) |
| 522 | break; | 520 | break; |
| 523 | 521 | ||
| 522 | status = IRQ_HANDLED; | ||
| 523 | |||
| 524 | if (zs_intreg & CHBRxIP) { | 524 | if (zs_intreg & CHBRxIP) { |
| 525 | receive_chars(info, regs); | 525 | receive_chars(info, regs); |
| 526 | } | 526 | } |
| @@ -534,6 +534,8 @@ void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) | |||
| 534 | 534 | ||
| 535 | /* Why do we need this ? */ | 535 | /* Why do we need this ? */ |
| 536 | write_zsreg(info->zs_channel, 0, RES_H_IUS); | 536 | write_zsreg(info->zs_channel, 0, RES_H_IUS); |
| 537 | |||
| 538 | return status; | ||
| 537 | } | 539 | } |
| 538 | 540 | ||
| 539 | #ifdef ZS_DEBUG_REGS | 541 | #ifdef ZS_DEBUG_REGS |
| @@ -578,12 +580,12 @@ static void rs_stop(struct tty_struct *tty) | |||
| 578 | return; | 580 | return; |
| 579 | 581 | ||
| 580 | #if 1 | 582 | #if 1 |
| 581 | save_flags(flags); cli(); | 583 | spin_lock_irqsave(&zs_lock, flags); |
| 582 | if (info->zs_channel->curregs[5] & TxENAB) { | 584 | if (info->zs_channel->curregs[5] & TxENAB) { |
| 583 | info->zs_channel->curregs[5] &= ~TxENAB; | 585 | info->zs_channel->curregs[5] &= ~TxENAB; |
| 584 | write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); | 586 | write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); |
| 585 | } | 587 | } |
| 586 | restore_flags(flags); | 588 | spin_unlock_irqrestore(&zs_lock, flags); |
| 587 | #endif | 589 | #endif |
| 588 | } | 590 | } |
| 589 | 591 | ||
| @@ -595,7 +597,7 @@ static void rs_start(struct tty_struct *tty) | |||
| 595 | if (serial_paranoia_check(info, tty->name, "rs_start")) | 597 | if (serial_paranoia_check(info, tty->name, "rs_start")) |
| 596 | return; | 598 | return; |
| 597 | 599 | ||
| 598 | save_flags(flags); cli(); | 600 | spin_lock_irqsave(&zs_lock, flags); |
| 599 | #if 1 | 601 | #if 1 |
| 600 | if (info->xmit_cnt && info->xmit_buf && !(info->zs_channel->curregs[5] & TxENAB)) { | 602 | if (info->xmit_cnt && info->xmit_buf && !(info->zs_channel->curregs[5] & TxENAB)) { |
| 601 | info->zs_channel->curregs[5] |= TxENAB; | 603 | info->zs_channel->curregs[5] |= TxENAB; |
| @@ -606,7 +608,7 @@ static void rs_start(struct tty_struct *tty) | |||
| 606 | transmit_chars(info); | 608 | transmit_chars(info); |
| 607 | } | 609 | } |
| 608 | #endif | 610 | #endif |
| 609 | restore_flags(flags); | 611 | spin_unlock_irqrestore(&zs_lock, flags); |
| 610 | } | 612 | } |
| 611 | 613 | ||
| 612 | /* | 614 | /* |
| @@ -618,12 +620,8 @@ static void rs_start(struct tty_struct *tty) | |||
| 618 | * interrupt driver proper are done; the interrupt driver schedules | 620 | * interrupt driver proper are done; the interrupt driver schedules |
| 619 | * them using rs_sched_event(), and they get done here. | 621 | * them using rs_sched_event(), and they get done here. |
| 620 | */ | 622 | */ |
| 621 | static void do_serial_bh(void) | ||
| 622 | { | ||
| 623 | run_task_queue(&tq_zs_serial); | ||
| 624 | } | ||
| 625 | 623 | ||
| 626 | static void do_softint(void *private_) | 624 | static void do_softint(unsigned long private_) |
| 627 | { | 625 | { |
| 628 | struct dec_serial *info = (struct dec_serial *) private_; | 626 | struct dec_serial *info = (struct dec_serial *) private_; |
| 629 | struct tty_struct *tty; | 627 | struct tty_struct *tty; |
| @@ -634,10 +632,11 @@ static void do_softint(void *private_) | |||
| 634 | 632 | ||
| 635 | if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { | 633 | if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { |
| 636 | tty_wakeup(tty); | 634 | tty_wakeup(tty); |
| 635 | wake_up_interruptible(&tty->write_wait); | ||
| 637 | } | 636 | } |
| 638 | } | 637 | } |
| 639 | 638 | ||
| 640 | int zs_startup(struct dec_serial * info) | 639 | static int zs_startup(struct dec_serial * info) |
| 641 | { | 640 | { |
| 642 | unsigned long flags; | 641 | unsigned long flags; |
| 643 | 642 | ||
| @@ -650,7 +649,7 @@ int zs_startup(struct dec_serial * info) | |||
| 650 | return -ENOMEM; | 649 | return -ENOMEM; |
| 651 | } | 650 | } |
| 652 | 651 | ||
| 653 | save_flags(flags); cli(); | 652 | spin_lock_irqsave(&zs_lock, flags); |
| 654 | 653 | ||
| 655 | #ifdef SERIAL_DEBUG_OPEN | 654 | #ifdef SERIAL_DEBUG_OPEN |
| 656 | printk("starting up ttyS%d (irq %d)...", info->line, info->irq); | 655 | printk("starting up ttyS%d (irq %d)...", info->line, info->irq); |
| @@ -706,7 +705,7 @@ int zs_startup(struct dec_serial * info) | |||
| 706 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | 705 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; |
| 707 | 706 | ||
| 708 | info->flags |= ZILOG_INITIALIZED; | 707 | info->flags |= ZILOG_INITIALIZED; |
| 709 | restore_flags(flags); | 708 | spin_unlock_irqrestore(&zs_lock, flags); |
| 710 | return 0; | 709 | return 0; |
| 711 | } | 710 | } |
| 712 | 711 | ||
| @@ -726,7 +725,7 @@ static void shutdown(struct dec_serial * info) | |||
| 726 | info->irq); | 725 | info->irq); |
| 727 | #endif | 726 | #endif |
| 728 | 727 | ||
| 729 | save_flags(flags); cli(); /* Disable interrupts */ | 728 | spin_lock_irqsave(&zs_lock, flags); |
| 730 | 729 | ||
| 731 | if (info->xmit_buf) { | 730 | if (info->xmit_buf) { |
| 732 | free_page((unsigned long) info->xmit_buf); | 731 | free_page((unsigned long) info->xmit_buf); |
| @@ -749,7 +748,7 @@ static void shutdown(struct dec_serial * info) | |||
| 749 | set_bit(TTY_IO_ERROR, &info->tty->flags); | 748 | set_bit(TTY_IO_ERROR, &info->tty->flags); |
| 750 | 749 | ||
| 751 | info->flags &= ~ZILOG_INITIALIZED; | 750 | info->flags &= ~ZILOG_INITIALIZED; |
| 752 | restore_flags(flags); | 751 | spin_unlock_irqrestore(&zs_lock, flags); |
| 753 | } | 752 | } |
| 754 | 753 | ||
| 755 | /* | 754 | /* |
| @@ -785,7 +784,7 @@ static void change_speed(struct dec_serial *info) | |||
| 785 | i += 15; | 784 | i += 15; |
| 786 | } | 785 | } |
| 787 | 786 | ||
| 788 | save_flags(flags); cli(); | 787 | spin_lock_irqsave(&zs_lock, flags); |
| 789 | info->zs_baud = baud_table[i]; | 788 | info->zs_baud = baud_table[i]; |
| 790 | if (info->zs_baud) { | 789 | if (info->zs_baud) { |
| 791 | brg = BPS_TO_BRG(info->zs_baud, zs_parms->clock/info->clk_divisor); | 790 | brg = BPS_TO_BRG(info->zs_baud, zs_parms->clock/info->clk_divisor); |
| @@ -858,7 +857,7 @@ static void change_speed(struct dec_serial *info) | |||
| 858 | /* Load up the new values */ | 857 | /* Load up the new values */ |
| 859 | load_zsregs(info->zs_channel, info->zs_channel->curregs); | 858 | load_zsregs(info->zs_channel, info->zs_channel->curregs); |
| 860 | 859 | ||
| 861 | restore_flags(flags); | 860 | spin_unlock_irqrestore(&zs_lock, flags); |
| 862 | } | 861 | } |
| 863 | 862 | ||
| 864 | static void rs_flush_chars(struct tty_struct *tty) | 863 | static void rs_flush_chars(struct tty_struct *tty) |
| @@ -874,9 +873,9 @@ static void rs_flush_chars(struct tty_struct *tty) | |||
| 874 | return; | 873 | return; |
| 875 | 874 | ||
| 876 | /* Enable transmitter */ | 875 | /* Enable transmitter */ |
| 877 | save_flags(flags); cli(); | 876 | spin_lock_irqsave(&zs_lock, flags); |
| 878 | transmit_chars(info); | 877 | transmit_chars(info); |
| 879 | restore_flags(flags); | 878 | spin_unlock_irqrestore(&zs_lock, flags); |
| 880 | } | 879 | } |
| 881 | 880 | ||
| 882 | static int rs_write(struct tty_struct * tty, | 881 | static int rs_write(struct tty_struct * tty, |
| @@ -892,26 +891,17 @@ static int rs_write(struct tty_struct * tty, | |||
| 892 | if (!tty || !info->xmit_buf) | 891 | if (!tty || !info->xmit_buf) |
| 893 | return 0; | 892 | return 0; |
| 894 | 893 | ||
| 895 | save_flags(flags); | ||
| 896 | while (1) { | 894 | while (1) { |
| 897 | cli(); | 895 | spin_lock_irqsave(&zs_lock, flags); |
| 898 | c = min(count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, | 896 | c = min(count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, |
| 899 | SERIAL_XMIT_SIZE - info->xmit_head)); | 897 | SERIAL_XMIT_SIZE - info->xmit_head)); |
| 900 | if (c <= 0) | 898 | if (c <= 0) |
| 901 | break; | 899 | break; |
| 902 | 900 | ||
| 903 | if (from_user) { | 901 | memcpy(info->xmit_buf + info->xmit_head, buf, c); |
| 904 | down(&tmp_buf_sem); | ||
| 905 | copy_from_user(tmp_buf, buf, c); | ||
| 906 | c = min(c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, | ||
| 907 | SERIAL_XMIT_SIZE - info->xmit_head)); | ||
| 908 | memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); | ||
| 909 | up(&tmp_buf_sem); | ||
| 910 | } else | ||
| 911 | memcpy(info->xmit_buf + info->xmit_head, buf, c); | ||
| 912 | info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); | 902 | info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); |
| 913 | info->xmit_cnt += c; | 903 | info->xmit_cnt += c; |
| 914 | restore_flags(flags); | 904 | spin_unlock_irqrestore(&zs_lock, flags); |
| 915 | buf += c; | 905 | buf += c; |
| 916 | count -= c; | 906 | count -= c; |
| 917 | total += c; | 907 | total += c; |
| @@ -920,7 +910,7 @@ static int rs_write(struct tty_struct * tty, | |||
| 920 | if (info->xmit_cnt && !tty->stopped && !info->tx_stopped | 910 | if (info->xmit_cnt && !tty->stopped && !info->tx_stopped |
| 921 | && !info->tx_active) | 911 | && !info->tx_active) |
| 922 | transmit_chars(info); | 912 | transmit_chars(info); |
| 923 | restore_flags(flags); | 913 | spin_unlock_irqrestore(&zs_lock, flags); |
| 924 | return total; | 914 | return total; |
| 925 | } | 915 | } |
| 926 | 916 | ||
| @@ -952,9 +942,9 @@ static void rs_flush_buffer(struct tty_struct *tty) | |||
| 952 | 942 | ||
| 953 | if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) | 943 | if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) |
| 954 | return; | 944 | return; |
| 955 | cli(); | 945 | spin_lock_irq(&zs_lock); |
| 956 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | 946 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; |
| 957 | sti(); | 947 | spin_unlock_irq(&zs_lock); |
| 958 | tty_wakeup(tty); | 948 | tty_wakeup(tty); |
| 959 | } | 949 | } |
| 960 | 950 | ||
| @@ -982,11 +972,11 @@ static void rs_throttle(struct tty_struct * tty) | |||
| 982 | return; | 972 | return; |
| 983 | 973 | ||
| 984 | if (I_IXOFF(tty)) { | 974 | if (I_IXOFF(tty)) { |
| 985 | save_flags(flags); cli(); | 975 | spin_lock_irqsave(&zs_lock, flags); |
| 986 | info->x_char = STOP_CHAR(tty); | 976 | info->x_char = STOP_CHAR(tty); |
| 987 | if (!info->tx_active) | 977 | if (!info->tx_active) |
| 988 | transmit_chars(info); | 978 | transmit_chars(info); |
| 989 | restore_flags(flags); | 979 | spin_unlock_irqrestore(&zs_lock, flags); |
| 990 | } | 980 | } |
| 991 | 981 | ||
| 992 | if (C_CRTSCTS(tty)) { | 982 | if (C_CRTSCTS(tty)) { |
| @@ -1010,7 +1000,7 @@ static void rs_unthrottle(struct tty_struct * tty) | |||
| 1010 | return; | 1000 | return; |
| 1011 | 1001 | ||
| 1012 | if (I_IXOFF(tty)) { | 1002 | if (I_IXOFF(tty)) { |
| 1013 | save_flags(flags); cli(); | 1003 | spin_lock_irqsave(&zs_lock, flags); |
| 1014 | if (info->x_char) | 1004 | if (info->x_char) |
| 1015 | info->x_char = 0; | 1005 | info->x_char = 0; |
| 1016 | else { | 1006 | else { |
| @@ -1018,7 +1008,7 @@ static void rs_unthrottle(struct tty_struct * tty) | |||
| 1018 | if (!info->tx_active) | 1008 | if (!info->tx_active) |
| 1019 | transmit_chars(info); | 1009 | transmit_chars(info); |
| 1020 | } | 1010 | } |
| 1021 | restore_flags(flags); | 1011 | spin_unlock_irqrestore(&zs_lock, flags); |
| 1022 | } | 1012 | } |
| 1023 | 1013 | ||
| 1024 | if (C_CRTSCTS(tty)) { | 1014 | if (C_CRTSCTS(tty)) { |
| @@ -1111,9 +1101,9 @@ static int get_lsr_info(struct dec_serial * info, unsigned int *value) | |||
| 1111 | { | 1101 | { |
| 1112 | unsigned char status; | 1102 | unsigned char status; |
| 1113 | 1103 | ||
| 1114 | cli(); | 1104 | spin_lock(&zs_lock); |
| 1115 | status = read_zsreg(info->zs_channel, 0); | 1105 | status = read_zsreg(info->zs_channel, 0); |
| 1116 | sti(); | 1106 | spin_unlock_irq(&zs_lock); |
| 1117 | put_user(status,value); | 1107 | put_user(status,value); |
| 1118 | return 0; | 1108 | return 0; |
| 1119 | } | 1109 | } |
| @@ -1136,11 +1126,11 @@ static int rs_tiocmget(struct tty_struct *tty, struct file *file) | |||
| 1136 | if (info->zs_channel == info->zs_chan_a) | 1126 | if (info->zs_channel == info->zs_chan_a) |
| 1137 | result = 0; | 1127 | result = 0; |
| 1138 | else { | 1128 | else { |
| 1139 | cli(); | 1129 | spin_lock(&zs_lock); |
| 1140 | control = info->zs_chan_a->curregs[5]; | 1130 | control = info->zs_chan_a->curregs[5]; |
| 1141 | status_a = read_zsreg(info->zs_chan_a, 0); | 1131 | status_a = read_zsreg(info->zs_chan_a, 0); |
| 1142 | status_b = read_zsreg(info->zs_channel, 0); | 1132 | status_b = read_zsreg(info->zs_channel, 0); |
| 1143 | sti(); | 1133 | spin_unlock_irq(&zs_lock); |
| 1144 | result = ((control & RTS) ? TIOCM_RTS: 0) | 1134 | result = ((control & RTS) ? TIOCM_RTS: 0) |
| 1145 | | ((control & DTR) ? TIOCM_DTR: 0) | 1135 | | ((control & DTR) ? TIOCM_DTR: 0) |
| 1146 | | ((status_b & DCD) ? TIOCM_CAR: 0) | 1136 | | ((status_b & DCD) ? TIOCM_CAR: 0) |
| @@ -1155,8 +1145,6 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file, | |||
| 1155 | unsigned int set, unsigned int clear) | 1145 | unsigned int set, unsigned int clear) |
| 1156 | { | 1146 | { |
| 1157 | struct dec_serial * info = (struct dec_serial *)tty->driver_data; | 1147 | struct dec_serial * info = (struct dec_serial *)tty->driver_data; |
| 1158 | int error; | ||
| 1159 | unsigned int arg, bits; | ||
| 1160 | 1148 | ||
| 1161 | if (info->hook) | 1149 | if (info->hook) |
| 1162 | return -ENODEV; | 1150 | return -ENODEV; |
| @@ -1170,8 +1158,7 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file, | |||
| 1170 | if (info->zs_channel == info->zs_chan_a) | 1158 | if (info->zs_channel == info->zs_chan_a) |
| 1171 | return 0; | 1159 | return 0; |
| 1172 | 1160 | ||
| 1173 | get_user(arg, value); | 1161 | spin_lock(&zs_lock); |
| 1174 | cli(); | ||
| 1175 | if (set & TIOCM_RTS) | 1162 | if (set & TIOCM_RTS) |
| 1176 | info->zs_chan_a->curregs[5] |= RTS; | 1163 | info->zs_chan_a->curregs[5] |= RTS; |
| 1177 | if (set & TIOCM_DTR) | 1164 | if (set & TIOCM_DTR) |
| @@ -1181,7 +1168,7 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file, | |||
| 1181 | if (clear & TIOCM_DTR) | 1168 | if (clear & TIOCM_DTR) |
| 1182 | info->zs_chan_a->curregs[5] &= ~DTR; | 1169 | info->zs_chan_a->curregs[5] &= ~DTR; |
| 1183 | write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); | 1170 | write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); |
| 1184 | sti(); | 1171 | spin_unlock_irq(&zs_lock); |
| 1185 | return 0; | 1172 | return 0; |
| 1186 | } | 1173 | } |
| 1187 | 1174 | ||
| @@ -1198,19 +1185,18 @@ static void rs_break(struct tty_struct *tty, int break_state) | |||
| 1198 | if (!info->port) | 1185 | if (!info->port) |
| 1199 | return; | 1186 | return; |
| 1200 | 1187 | ||
| 1201 | save_flags(flags); cli(); | 1188 | spin_lock_irqsave(&zs_lock, flags); |
| 1202 | if (break_state == -1) | 1189 | if (break_state == -1) |
| 1203 | info->zs_channel->curregs[5] |= SND_BRK; | 1190 | info->zs_channel->curregs[5] |= SND_BRK; |
| 1204 | else | 1191 | else |
| 1205 | info->zs_channel->curregs[5] &= ~SND_BRK; | 1192 | info->zs_channel->curregs[5] &= ~SND_BRK; |
| 1206 | write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); | 1193 | write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); |
| 1207 | restore_flags(flags); | 1194 | spin_unlock_irqrestore(&zs_lock, flags); |
| 1208 | } | 1195 | } |
| 1209 | 1196 | ||
| 1210 | static int rs_ioctl(struct tty_struct *tty, struct file * file, | 1197 | static int rs_ioctl(struct tty_struct *tty, struct file * file, |
| 1211 | unsigned int cmd, unsigned long arg) | 1198 | unsigned int cmd, unsigned long arg) |
| 1212 | { | 1199 | { |
| 1213 | int error; | ||
| 1214 | struct dec_serial * info = (struct dec_serial *)tty->driver_data; | 1200 | struct dec_serial * info = (struct dec_serial *)tty->driver_data; |
| 1215 | 1201 | ||
| 1216 | if (info->hook) | 1202 | if (info->hook) |
| @@ -1287,10 +1273,10 @@ static void rs_close(struct tty_struct *tty, struct file * filp) | |||
| 1287 | if (!info || serial_paranoia_check(info, tty->name, "rs_close")) | 1273 | if (!info || serial_paranoia_check(info, tty->name, "rs_close")) |
| 1288 | return; | 1274 | return; |
| 1289 | 1275 | ||
| 1290 | save_flags(flags); cli(); | 1276 | spin_lock_irqsave(&zs_lock, flags); |
| 1291 | 1277 | ||
| 1292 | if (tty_hung_up_p(filp)) { | 1278 | if (tty_hung_up_p(filp)) { |
| 1293 | restore_flags(flags); | 1279 | spin_unlock_irqrestore(&zs_lock, flags); |
| 1294 | return; | 1280 | return; |
| 1295 | } | 1281 | } |
| 1296 | 1282 | ||
| @@ -1315,7 +1301,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) | |||
| 1315 | info->count = 0; | 1301 | info->count = 0; |
| 1316 | } | 1302 | } |
| 1317 | if (info->count) { | 1303 | if (info->count) { |
| 1318 | restore_flags(flags); | 1304 | spin_unlock_irqrestore(&zs_lock, flags); |
| 1319 | return; | 1305 | return; |
| 1320 | } | 1306 | } |
| 1321 | info->flags |= ZILOG_CLOSING; | 1307 | info->flags |= ZILOG_CLOSING; |
| @@ -1358,7 +1344,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) | |||
| 1358 | } | 1344 | } |
| 1359 | info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CLOSING); | 1345 | info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CLOSING); |
| 1360 | wake_up_interruptible(&info->close_wait); | 1346 | wake_up_interruptible(&info->close_wait); |
| 1361 | restore_flags(flags); | 1347 | spin_unlock_irqrestore(&zs_lock, flags); |
| 1362 | } | 1348 | } |
| 1363 | 1349 | ||
| 1364 | /* | 1350 | /* |
| @@ -1398,7 +1384,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
| 1398 | /* | 1384 | /* |
| 1399 | * rs_hangup() --- called by tty_hangup() when a hangup is signaled. | 1385 | * rs_hangup() --- called by tty_hangup() when a hangup is signaled. |
| 1400 | */ | 1386 | */ |
| 1401 | void rs_hangup(struct tty_struct *tty) | 1387 | static void rs_hangup(struct tty_struct *tty) |
| 1402 | { | 1388 | { |
| 1403 | struct dec_serial * info = (struct dec_serial *)tty->driver_data; | 1389 | struct dec_serial * info = (struct dec_serial *)tty->driver_data; |
| 1404 | 1390 | ||
| @@ -1466,16 +1452,16 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
| 1466 | printk("block_til_ready before block: ttyS%d, count = %d\n", | 1452 | printk("block_til_ready before block: ttyS%d, count = %d\n", |
| 1467 | info->line, info->count); | 1453 | info->line, info->count); |
| 1468 | #endif | 1454 | #endif |
| 1469 | cli(); | 1455 | spin_lock(&zs_lock); |
| 1470 | if (!tty_hung_up_p(filp)) | 1456 | if (!tty_hung_up_p(filp)) |
| 1471 | info->count--; | 1457 | info->count--; |
| 1472 | sti(); | 1458 | spin_unlock_irq(&zs_lock); |
| 1473 | info->blocked_open++; | 1459 | info->blocked_open++; |
| 1474 | while (1) { | 1460 | while (1) { |
| 1475 | cli(); | 1461 | spin_lock(&zs_lock); |
| 1476 | if (tty->termios->c_cflag & CBAUD) | 1462 | if (tty->termios->c_cflag & CBAUD) |
| 1477 | zs_rtsdtr(info, RTS | DTR, 1); | 1463 | zs_rtsdtr(info, RTS | DTR, 1); |
| 1478 | sti(); | 1464 | spin_unlock_irq(&zs_lock); |
| 1479 | set_current_state(TASK_INTERRUPTIBLE); | 1465 | set_current_state(TASK_INTERRUPTIBLE); |
| 1480 | if (tty_hung_up_p(filp) || | 1466 | if (tty_hung_up_p(filp) || |
| 1481 | !(info->flags & ZILOG_INITIALIZED)) { | 1467 | !(info->flags & ZILOG_INITIALIZED)) { |
| @@ -1523,7 +1509,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
| 1523 | * the IRQ chain. It also performs the serial-specific | 1509 | * the IRQ chain. It also performs the serial-specific |
| 1524 | * initialization for the tty structure. | 1510 | * initialization for the tty structure. |
| 1525 | */ | 1511 | */ |
| 1526 | int rs_open(struct tty_struct *tty, struct file * filp) | 1512 | static int rs_open(struct tty_struct *tty, struct file * filp) |
| 1527 | { | 1513 | { |
| 1528 | struct dec_serial *info; | 1514 | struct dec_serial *info; |
| 1529 | int retval, line; | 1515 | int retval, line; |
| @@ -1706,7 +1692,7 @@ static void __init probe_sccs(void) | |||
| 1706 | } | 1692 | } |
| 1707 | } | 1693 | } |
| 1708 | 1694 | ||
| 1709 | save_and_cli(flags); | 1695 | spin_lock_irqsave(&zs_lock, flags); |
| 1710 | for (n = 0; n < zs_channels_found; n++) { | 1696 | for (n = 0; n < zs_channels_found; n++) { |
| 1711 | if (n % 2 == 0) { | 1697 | if (n % 2 == 0) { |
| 1712 | write_zsreg(zs_soft[n].zs_chan_a, R9, FHWRES); | 1698 | write_zsreg(zs_soft[n].zs_chan_a, R9, FHWRES); |
| @@ -1716,7 +1702,7 @@ static void __init probe_sccs(void) | |||
| 1716 | load_zsregs(zs_soft[n].zs_channel, | 1702 | load_zsregs(zs_soft[n].zs_channel, |
| 1717 | zs_soft[n].zs_channel->curregs); | 1703 | zs_soft[n].zs_channel->curregs); |
| 1718 | } | 1704 | } |
| 1719 | restore_flags(flags); | 1705 | spin_unlock_irqrestore(&zs_lock, flags); |
| 1720 | } | 1706 | } |
| 1721 | 1707 | ||
| 1722 | static struct tty_operations serial_ops = { | 1708 | static struct tty_operations serial_ops = { |
| @@ -1749,9 +1735,6 @@ int __init zs_init(void) | |||
| 1749 | if(!BUS_PRESENT) | 1735 | if(!BUS_PRESENT) |
| 1750 | return -ENODEV; | 1736 | return -ENODEV; |
| 1751 | 1737 | ||
| 1752 | /* Setup base handler, and timer table. */ | ||
| 1753 | init_bh(SERIAL_BH, do_serial_bh); | ||
| 1754 | |||
| 1755 | /* Find out how many Z8530 SCCs we have */ | 1738 | /* Find out how many Z8530 SCCs we have */ |
| 1756 | if (zs_chain == 0) | 1739 | if (zs_chain == 0) |
| 1757 | probe_sccs(); | 1740 | probe_sccs(); |
| @@ -1800,8 +1783,7 @@ int __init zs_init(void) | |||
| 1800 | info->event = 0; | 1783 | info->event = 0; |
| 1801 | info->count = 0; | 1784 | info->count = 0; |
| 1802 | info->blocked_open = 0; | 1785 | info->blocked_open = 0; |
| 1803 | info->tqueue.routine = do_softint; | 1786 | tasklet_init(&info->tlet, do_softint, (unsigned long)info); |
| 1804 | info->tqueue.data = info; | ||
| 1805 | init_waitqueue_head(&info->open_wait); | 1787 | init_waitqueue_head(&info->open_wait); |
| 1806 | init_waitqueue_head(&info->close_wait); | 1788 | init_waitqueue_head(&info->close_wait); |
| 1807 | printk("ttyS%02d at 0x%08x (irq = %d) is a Z85C30 SCC\n", | 1789 | printk("ttyS%02d at 0x%08x (irq = %d) is a Z85C30 SCC\n", |
| @@ -1833,8 +1815,7 @@ int __init zs_init(void) | |||
| 1833 | /* | 1815 | /* |
| 1834 | * polling I/O routines | 1816 | * polling I/O routines |
| 1835 | */ | 1817 | */ |
| 1836 | static int | 1818 | static int zs_poll_tx_char(void *handle, unsigned char ch) |
| 1837 | zs_poll_tx_char(void *handle, unsigned char ch) | ||
| 1838 | { | 1819 | { |
| 1839 | struct dec_serial *info = handle; | 1820 | struct dec_serial *info = handle; |
| 1840 | struct dec_zschannel *chan = info->zs_channel; | 1821 | struct dec_zschannel *chan = info->zs_channel; |
| @@ -1857,8 +1838,7 @@ zs_poll_tx_char(void *handle, unsigned char ch) | |||
| 1857 | return -ENODEV; | 1838 | return -ENODEV; |
| 1858 | } | 1839 | } |
| 1859 | 1840 | ||
| 1860 | static int | 1841 | static int zs_poll_rx_char(void *handle) |
| 1861 | zs_poll_rx_char(void *handle) | ||
| 1862 | { | 1842 | { |
| 1863 | struct dec_serial *info = handle; | 1843 | struct dec_serial *info = handle; |
| 1864 | struct dec_zschannel *chan = info->zs_channel; | 1844 | struct dec_zschannel *chan = info->zs_channel; |
| @@ -2037,7 +2017,7 @@ static int __init serial_console_setup(struct console *co, char *options) | |||
| 2037 | } | 2017 | } |
| 2038 | co->cflag = cflag; | 2018 | co->cflag = cflag; |
| 2039 | 2019 | ||
| 2040 | save_and_cli(flags); | 2020 | spin_lock_irqsave(&zs_lock, flags); |
| 2041 | 2021 | ||
| 2042 | /* | 2022 | /* |
| 2043 | * Set up the baud rate generator. | 2023 | * Set up the baud rate generator. |
| @@ -2092,7 +2072,7 @@ static int __init serial_console_setup(struct console *co, char *options) | |||
| 2092 | zs_soft[co->index].clk_divisor = clk_divisor; | 2072 | zs_soft[co->index].clk_divisor = clk_divisor; |
| 2093 | zs_soft[co->index].zs_baud = get_zsbaud(&zs_soft[co->index]); | 2073 | zs_soft[co->index].zs_baud = get_zsbaud(&zs_soft[co->index]); |
| 2094 | 2074 | ||
| 2095 | restore_flags(flags); | 2075 | spin_unlock_irqrestore(&zs_lock, flags); |
| 2096 | 2076 | ||
| 2097 | return 0; | 2077 | return 0; |
| 2098 | } | 2078 | } |
| @@ -2229,5 +2209,3 @@ void __init zs_kgdb_hook(int tty_num) | |||
| 2229 | set_debug_traps(); /* init stub */ | 2209 | set_debug_traps(); /* init stub */ |
| 2230 | } | 2210 | } |
| 2231 | #endif /* ifdef CONFIG_KGDB */ | 2211 | #endif /* ifdef CONFIG_KGDB */ |
| 2232 | |||
| 2233 | |||
diff --git a/drivers/tc/zs.h b/drivers/tc/zs.h index c52edffa6049..13512200ceba 100644 --- a/drivers/tc/zs.h +++ b/drivers/tc/zs.h | |||
| @@ -6,14 +6,14 @@ | |||
| 6 | * | 6 | * |
| 7 | * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) | 7 | * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) |
| 8 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | 8 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) |
| 9 | * Copyright (C) 2004 Maciej W. Rozycki | 9 | * Copyright (C) 2004, 2005 Maciej W. Rozycki |
| 10 | */ | 10 | */ |
| 11 | #ifndef _DECSERIAL_H | 11 | #ifndef _DECSERIAL_H |
| 12 | #define _DECSERIAL_H | 12 | #define _DECSERIAL_H |
| 13 | 13 | ||
| 14 | #include <asm/dec/serial.h> | 14 | #include <asm/dec/serial.h> |
| 15 | 15 | ||
| 16 | #define NUM_ZSREGS 16 | 16 | #define NUM_ZSREGS 16 |
| 17 | 17 | ||
| 18 | struct serial_struct { | 18 | struct serial_struct { |
| 19 | int type; | 19 | int type; |
| @@ -139,8 +139,7 @@ struct dec_serial { | |||
| 139 | int xmit_head; | 139 | int xmit_head; |
| 140 | int xmit_tail; | 140 | int xmit_tail; |
| 141 | int xmit_cnt; | 141 | int xmit_cnt; |
| 142 | struct tq_struct tqueue; | 142 | struct tasklet_struct tlet; |
| 143 | struct tq_struct tqueue_hangup; | ||
| 144 | wait_queue_head_t open_wait; | 143 | wait_queue_head_t open_wait; |
| 145 | wait_queue_head_t close_wait; | 144 | wait_queue_head_t close_wait; |
| 146 | }; | 145 | }; |
| @@ -282,7 +281,7 @@ struct dec_serial { | |||
| 282 | #define DLC 4 /* Disable Lower Chain */ | 281 | #define DLC 4 /* Disable Lower Chain */ |
| 283 | #define MIE 8 /* Master Interrupt Enable */ | 282 | #define MIE 8 /* Master Interrupt Enable */ |
| 284 | #define STATHI 0x10 /* Status high */ | 283 | #define STATHI 0x10 /* Status high */ |
| 285 | #define SOFTACK 0x20 /* Software Interrupt Acknowledge */ | 284 | #define SOFTACK 0x20 /* Software Interrupt Acknowledge */ |
| 286 | #define NORESET 0 /* No reset on write to R9 */ | 285 | #define NORESET 0 /* No reset on write to R9 */ |
| 287 | #define CHRB 0x40 /* Reset channel B */ | 286 | #define CHRB 0x40 /* Reset channel B */ |
| 288 | #define CHRA 0x80 /* Reset channel A */ | 287 | #define CHRA 0x80 /* Reset channel A */ |
| @@ -395,8 +394,8 @@ struct dec_serial { | |||
| 395 | /* Read Register 15 (value of WR 15) */ | 394 | /* Read Register 15 (value of WR 15) */ |
| 396 | 395 | ||
| 397 | /* Misc macros */ | 396 | /* Misc macros */ |
| 398 | #define ZS_CLEARERR(channel) (write_zsreg(channel, 0, ERR_RES)) | 397 | #define ZS_CLEARERR(channel) (write_zsreg(channel, 0, ERR_RES)) |
| 399 | #define ZS_CLEARFIFO(channel) do { volatile unsigned char garbage; \ | 398 | #define ZS_CLEARFIFO(channel) do { volatile unsigned char garbage; \ |
| 400 | garbage = read_zsdata(channel); \ | 399 | garbage = read_zsdata(channel); \ |
| 401 | garbage = read_zsdata(channel); \ | 400 | garbage = read_zsdata(channel); \ |
| 402 | garbage = read_zsdata(channel); \ | 401 | garbage = read_zsdata(channel); \ |
