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 | |
| 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>
| -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 c52af73a25..6756d0fab6 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; |
