mirror of https://gitee.com/openkylin/linux.git
[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>
This commit is contained in:
parent
e0c9b79730
commit
0905780aae
150
drivers/tc/zs.c
150
drivers/tc/zs.c
|
@ -6,7 +6,7 @@
|
||||||
*
|
*
|
||||||
* DECstation changes
|
* DECstation changes
|
||||||
* Copyright (C) 1998-2000 Harald Koerfgen
|
* Copyright (C) 1998-2000 Harald Koerfgen
|
||||||
* Copyright (C) 2000, 2001, 2002, 2003, 2004 Maciej W. Rozycki
|
* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Maciej W. Rozycki
|
||||||
*
|
*
|
||||||
* For the rest of the code the original Copyright applies:
|
* For the rest of the code the original Copyright applies:
|
||||||
* Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
|
* Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
|
||||||
|
@ -55,6 +55,7 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
#ifdef CONFIG_SERIAL_DEC_CONSOLE
|
#ifdef CONFIG_SERIAL_DEC_CONSOLE
|
||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -63,7 +64,6 @@
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/uaccess.h>
|
|
||||||
#include <asm/bootinfo.h>
|
#include <asm/bootinfo.h>
|
||||||
|
|
||||||
#include <asm/dec/interrupts.h>
|
#include <asm/dec/interrupts.h>
|
||||||
|
@ -128,6 +128,8 @@ static struct zs_parms ds_parms = {
|
||||||
|
|
||||||
#define BUS_PRESENT (DS_BUS_PRESENT)
|
#define BUS_PRESENT (DS_BUS_PRESENT)
|
||||||
|
|
||||||
|
DEFINE_SPINLOCK(zs_lock);
|
||||||
|
|
||||||
struct dec_zschannel zs_channels[NUM_CHANNELS];
|
struct dec_zschannel zs_channels[NUM_CHANNELS];
|
||||||
struct dec_serial zs_soft[NUM_CHANNELS];
|
struct dec_serial zs_soft[NUM_CHANNELS];
|
||||||
int zs_channels_found;
|
int zs_channels_found;
|
||||||
|
@ -159,8 +161,6 @@ static unsigned char zs_init_regs[16] __initdata = {
|
||||||
0 /* write 15 */
|
0 /* write 15 */
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_TASK_QUEUE(tq_zs_serial);
|
|
||||||
|
|
||||||
static struct tty_driver *serial_driver;
|
static struct tty_driver *serial_driver;
|
||||||
|
|
||||||
/* serial subtype definitions */
|
/* serial subtype definitions */
|
||||||
|
@ -294,8 +294,7 @@ static inline void zs_rtsdtr(struct dec_serial *info, int which, int set)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&zs_lock, flags);
|
||||||
save_flags(flags); cli();
|
|
||||||
if (info->zs_channel != info->zs_chan_a) {
|
if (info->zs_channel != info->zs_chan_a) {
|
||||||
if (set) {
|
if (set) {
|
||||||
info->zs_chan_a->curregs[5] |= (which & (RTS | DTR));
|
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)
|
||||||
}
|
}
|
||||||
write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]);
|
write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]);
|
||||||
}
|
}
|
||||||
restore_flags(flags);
|
spin_unlock_irqrestore(&zs_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Utility routines for the Zilog */
|
/* Utility routines for the Zilog */
|
||||||
|
@ -345,12 +344,10 @@ static inline void rs_recv_clear(struct dec_zschannel *zsc)
|
||||||
* This routine is used by the interrupt handler to schedule
|
* This routine is used by the interrupt handler to schedule
|
||||||
* processing in the software interrupt portion of the driver.
|
* processing in the software interrupt portion of the driver.
|
||||||
*/
|
*/
|
||||||
static _INLINE_ void rs_sched_event(struct dec_serial *info,
|
static _INLINE_ void rs_sched_event(struct dec_serial *info, int event)
|
||||||
int event)
|
|
||||||
{
|
{
|
||||||
info->event |= 1 << event;
|
info->event |= 1 << event;
|
||||||
queue_task(&info->tqueue, &tq_zs_serial);
|
tasklet_schedule(&info->tlet);
|
||||||
mark_bh(SERIAL_BH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static _INLINE_ void receive_chars(struct dec_serial *info,
|
static _INLINE_ void receive_chars(struct dec_serial *info,
|
||||||
|
@ -497,9 +494,10 @@ static _INLINE_ void status_handle(struct dec_serial *info)
|
||||||
/*
|
/*
|
||||||
* This is the serial driver's generic interrupt routine
|
* This is the serial driver's generic interrupt routine
|
||||||
*/
|
*/
|
||||||
void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
|
static irqreturn_t rs_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
struct dec_serial *info = (struct dec_serial *) dev_id;
|
struct dec_serial *info = (struct dec_serial *) dev_id;
|
||||||
|
irqreturn_t status = IRQ_NONE;
|
||||||
unsigned char zs_intreg;
|
unsigned char zs_intreg;
|
||||||
int shift;
|
int shift;
|
||||||
|
|
||||||
|
@ -521,6 +519,8 @@ void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
|
||||||
if ((zs_intreg & CHAN_IRQMASK) == 0)
|
if ((zs_intreg & CHAN_IRQMASK) == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
status = IRQ_HANDLED;
|
||||||
|
|
||||||
if (zs_intreg & CHBRxIP) {
|
if (zs_intreg & CHBRxIP) {
|
||||||
receive_chars(info, regs);
|
receive_chars(info, regs);
|
||||||
}
|
}
|
||||||
|
@ -534,6 +534,8 @@ void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
|
||||||
|
|
||||||
/* Why do we need this ? */
|
/* Why do we need this ? */
|
||||||
write_zsreg(info->zs_channel, 0, RES_H_IUS);
|
write_zsreg(info->zs_channel, 0, RES_H_IUS);
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ZS_DEBUG_REGS
|
#ifdef ZS_DEBUG_REGS
|
||||||
|
@ -578,12 +580,12 @@ static void rs_stop(struct tty_struct *tty)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
save_flags(flags); cli();
|
spin_lock_irqsave(&zs_lock, flags);
|
||||||
if (info->zs_channel->curregs[5] & TxENAB) {
|
if (info->zs_channel->curregs[5] & TxENAB) {
|
||||||
info->zs_channel->curregs[5] &= ~TxENAB;
|
info->zs_channel->curregs[5] &= ~TxENAB;
|
||||||
write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
|
write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
|
||||||
}
|
}
|
||||||
restore_flags(flags);
|
spin_unlock_irqrestore(&zs_lock, flags);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,7 +597,7 @@ static void rs_start(struct tty_struct *tty)
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_start"))
|
if (serial_paranoia_check(info, tty->name, "rs_start"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
save_flags(flags); cli();
|
spin_lock_irqsave(&zs_lock, flags);
|
||||||
#if 1
|
#if 1
|
||||||
if (info->xmit_cnt && info->xmit_buf && !(info->zs_channel->curregs[5] & TxENAB)) {
|
if (info->xmit_cnt && info->xmit_buf && !(info->zs_channel->curregs[5] & TxENAB)) {
|
||||||
info->zs_channel->curregs[5] |= TxENAB;
|
info->zs_channel->curregs[5] |= TxENAB;
|
||||||
|
@ -606,7 +608,7 @@ static void rs_start(struct tty_struct *tty)
|
||||||
transmit_chars(info);
|
transmit_chars(info);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
restore_flags(flags);
|
spin_unlock_irqrestore(&zs_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -618,12 +620,8 @@ static void rs_start(struct tty_struct *tty)
|
||||||
* interrupt driver proper are done; the interrupt driver schedules
|
* interrupt driver proper are done; the interrupt driver schedules
|
||||||
* them using rs_sched_event(), and they get done here.
|
* them using rs_sched_event(), and they get done here.
|
||||||
*/
|
*/
|
||||||
static void do_serial_bh(void)
|
|
||||||
{
|
|
||||||
run_task_queue(&tq_zs_serial);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void do_softint(void *private_)
|
static void do_softint(unsigned long private_)
|
||||||
{
|
{
|
||||||
struct dec_serial *info = (struct dec_serial *) private_;
|
struct dec_serial *info = (struct dec_serial *) private_;
|
||||||
struct tty_struct *tty;
|
struct tty_struct *tty;
|
||||||
|
@ -634,10 +632,11 @@ static void do_softint(void *private_)
|
||||||
|
|
||||||
if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
|
if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
|
||||||
tty_wakeup(tty);
|
tty_wakeup(tty);
|
||||||
|
wake_up_interruptible(&tty->write_wait);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int zs_startup(struct dec_serial * info)
|
static int zs_startup(struct dec_serial * info)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
@ -650,7 +649,7 @@ int zs_startup(struct dec_serial * info)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
save_flags(flags); cli();
|
spin_lock_irqsave(&zs_lock, flags);
|
||||||
|
|
||||||
#ifdef SERIAL_DEBUG_OPEN
|
#ifdef SERIAL_DEBUG_OPEN
|
||||||
printk("starting up ttyS%d (irq %d)...", info->line, info->irq);
|
printk("starting up ttyS%d (irq %d)...", info->line, info->irq);
|
||||||
|
@ -706,7 +705,7 @@ int zs_startup(struct dec_serial * info)
|
||||||
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
|
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
|
||||||
|
|
||||||
info->flags |= ZILOG_INITIALIZED;
|
info->flags |= ZILOG_INITIALIZED;
|
||||||
restore_flags(flags);
|
spin_unlock_irqrestore(&zs_lock, flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,7 +725,7 @@ static void shutdown(struct dec_serial * info)
|
||||||
info->irq);
|
info->irq);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
save_flags(flags); cli(); /* Disable interrupts */
|
spin_lock_irqsave(&zs_lock, flags);
|
||||||
|
|
||||||
if (info->xmit_buf) {
|
if (info->xmit_buf) {
|
||||||
free_page((unsigned long) info->xmit_buf);
|
free_page((unsigned long) info->xmit_buf);
|
||||||
|
@ -749,7 +748,7 @@ static void shutdown(struct dec_serial * info)
|
||||||
set_bit(TTY_IO_ERROR, &info->tty->flags);
|
set_bit(TTY_IO_ERROR, &info->tty->flags);
|
||||||
|
|
||||||
info->flags &= ~ZILOG_INITIALIZED;
|
info->flags &= ~ZILOG_INITIALIZED;
|
||||||
restore_flags(flags);
|
spin_unlock_irqrestore(&zs_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -785,7 +784,7 @@ static void change_speed(struct dec_serial *info)
|
||||||
i += 15;
|
i += 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
save_flags(flags); cli();
|
spin_lock_irqsave(&zs_lock, flags);
|
||||||
info->zs_baud = baud_table[i];
|
info->zs_baud = baud_table[i];
|
||||||
if (info->zs_baud) {
|
if (info->zs_baud) {
|
||||||
brg = BPS_TO_BRG(info->zs_baud, zs_parms->clock/info->clk_divisor);
|
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)
|
||||||
/* Load up the new values */
|
/* Load up the new values */
|
||||||
load_zsregs(info->zs_channel, info->zs_channel->curregs);
|
load_zsregs(info->zs_channel, info->zs_channel->curregs);
|
||||||
|
|
||||||
restore_flags(flags);
|
spin_unlock_irqrestore(&zs_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rs_flush_chars(struct tty_struct *tty)
|
static void rs_flush_chars(struct tty_struct *tty)
|
||||||
|
@ -874,9 +873,9 @@ static void rs_flush_chars(struct tty_struct *tty)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Enable transmitter */
|
/* Enable transmitter */
|
||||||
save_flags(flags); cli();
|
spin_lock_irqsave(&zs_lock, flags);
|
||||||
transmit_chars(info);
|
transmit_chars(info);
|
||||||
restore_flags(flags);
|
spin_unlock_irqrestore(&zs_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rs_write(struct tty_struct * tty,
|
static int rs_write(struct tty_struct * tty,
|
||||||
|
@ -892,26 +891,17 @@ static int rs_write(struct tty_struct * tty,
|
||||||
if (!tty || !info->xmit_buf)
|
if (!tty || !info->xmit_buf)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
save_flags(flags);
|
|
||||||
while (1) {
|
while (1) {
|
||||||
cli();
|
spin_lock_irqsave(&zs_lock, flags);
|
||||||
c = min(count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
|
c = min(count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
|
||||||
SERIAL_XMIT_SIZE - info->xmit_head));
|
SERIAL_XMIT_SIZE - info->xmit_head));
|
||||||
if (c <= 0)
|
if (c <= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (from_user) {
|
memcpy(info->xmit_buf + info->xmit_head, buf, c);
|
||||||
down(&tmp_buf_sem);
|
|
||||||
copy_from_user(tmp_buf, buf, c);
|
|
||||||
c = min(c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
|
|
||||||
SERIAL_XMIT_SIZE - info->xmit_head));
|
|
||||||
memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
|
|
||||||
up(&tmp_buf_sem);
|
|
||||||
} else
|
|
||||||
memcpy(info->xmit_buf + info->xmit_head, buf, c);
|
|
||||||
info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
|
info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
|
||||||
info->xmit_cnt += c;
|
info->xmit_cnt += c;
|
||||||
restore_flags(flags);
|
spin_unlock_irqrestore(&zs_lock, flags);
|
||||||
buf += c;
|
buf += c;
|
||||||
count -= c;
|
count -= c;
|
||||||
total += c;
|
total += c;
|
||||||
|
@ -920,7 +910,7 @@ static int rs_write(struct tty_struct * tty,
|
||||||
if (info->xmit_cnt && !tty->stopped && !info->tx_stopped
|
if (info->xmit_cnt && !tty->stopped && !info->tx_stopped
|
||||||
&& !info->tx_active)
|
&& !info->tx_active)
|
||||||
transmit_chars(info);
|
transmit_chars(info);
|
||||||
restore_flags(flags);
|
spin_unlock_irqrestore(&zs_lock, flags);
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -952,9 +942,9 @@ static void rs_flush_buffer(struct tty_struct *tty)
|
||||||
|
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
|
if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
|
||||||
return;
|
return;
|
||||||
cli();
|
spin_lock_irq(&zs_lock);
|
||||||
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
|
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
|
||||||
sti();
|
spin_unlock_irq(&zs_lock);
|
||||||
tty_wakeup(tty);
|
tty_wakeup(tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -982,11 +972,11 @@ static void rs_throttle(struct tty_struct * tty)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (I_IXOFF(tty)) {
|
if (I_IXOFF(tty)) {
|
||||||
save_flags(flags); cli();
|
spin_lock_irqsave(&zs_lock, flags);
|
||||||
info->x_char = STOP_CHAR(tty);
|
info->x_char = STOP_CHAR(tty);
|
||||||
if (!info->tx_active)
|
if (!info->tx_active)
|
||||||
transmit_chars(info);
|
transmit_chars(info);
|
||||||
restore_flags(flags);
|
spin_unlock_irqrestore(&zs_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (C_CRTSCTS(tty)) {
|
if (C_CRTSCTS(tty)) {
|
||||||
|
@ -1010,7 +1000,7 @@ static void rs_unthrottle(struct tty_struct * tty)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (I_IXOFF(tty)) {
|
if (I_IXOFF(tty)) {
|
||||||
save_flags(flags); cli();
|
spin_lock_irqsave(&zs_lock, flags);
|
||||||
if (info->x_char)
|
if (info->x_char)
|
||||||
info->x_char = 0;
|
info->x_char = 0;
|
||||||
else {
|
else {
|
||||||
|
@ -1018,7 +1008,7 @@ static void rs_unthrottle(struct tty_struct * tty)
|
||||||
if (!info->tx_active)
|
if (!info->tx_active)
|
||||||
transmit_chars(info);
|
transmit_chars(info);
|
||||||
}
|
}
|
||||||
restore_flags(flags);
|
spin_unlock_irqrestore(&zs_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (C_CRTSCTS(tty)) {
|
if (C_CRTSCTS(tty)) {
|
||||||
|
@ -1111,9 +1101,9 @@ static int get_lsr_info(struct dec_serial * info, unsigned int *value)
|
||||||
{
|
{
|
||||||
unsigned char status;
|
unsigned char status;
|
||||||
|
|
||||||
cli();
|
spin_lock(&zs_lock);
|
||||||
status = read_zsreg(info->zs_channel, 0);
|
status = read_zsreg(info->zs_channel, 0);
|
||||||
sti();
|
spin_unlock_irq(&zs_lock);
|
||||||
put_user(status,value);
|
put_user(status,value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1136,11 +1126,11 @@ static int rs_tiocmget(struct tty_struct *tty, struct file *file)
|
||||||
if (info->zs_channel == info->zs_chan_a)
|
if (info->zs_channel == info->zs_chan_a)
|
||||||
result = 0;
|
result = 0;
|
||||||
else {
|
else {
|
||||||
cli();
|
spin_lock(&zs_lock);
|
||||||
control = info->zs_chan_a->curregs[5];
|
control = info->zs_chan_a->curregs[5];
|
||||||
status_a = read_zsreg(info->zs_chan_a, 0);
|
status_a = read_zsreg(info->zs_chan_a, 0);
|
||||||
status_b = read_zsreg(info->zs_channel, 0);
|
status_b = read_zsreg(info->zs_channel, 0);
|
||||||
sti();
|
spin_unlock_irq(&zs_lock);
|
||||||
result = ((control & RTS) ? TIOCM_RTS: 0)
|
result = ((control & RTS) ? TIOCM_RTS: 0)
|
||||||
| ((control & DTR) ? TIOCM_DTR: 0)
|
| ((control & DTR) ? TIOCM_DTR: 0)
|
||||||
| ((status_b & DCD) ? TIOCM_CAR: 0)
|
| ((status_b & DCD) ? TIOCM_CAR: 0)
|
||||||
|
@ -1155,8 +1145,6 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file,
|
||||||
unsigned int set, unsigned int clear)
|
unsigned int set, unsigned int clear)
|
||||||
{
|
{
|
||||||
struct dec_serial * info = (struct dec_serial *)tty->driver_data;
|
struct dec_serial * info = (struct dec_serial *)tty->driver_data;
|
||||||
int error;
|
|
||||||
unsigned int arg, bits;
|
|
||||||
|
|
||||||
if (info->hook)
|
if (info->hook)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -1170,8 +1158,7 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file,
|
||||||
if (info->zs_channel == info->zs_chan_a)
|
if (info->zs_channel == info->zs_chan_a)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
get_user(arg, value);
|
spin_lock(&zs_lock);
|
||||||
cli();
|
|
||||||
if (set & TIOCM_RTS)
|
if (set & TIOCM_RTS)
|
||||||
info->zs_chan_a->curregs[5] |= RTS;
|
info->zs_chan_a->curregs[5] |= RTS;
|
||||||
if (set & TIOCM_DTR)
|
if (set & TIOCM_DTR)
|
||||||
|
@ -1181,7 +1168,7 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file,
|
||||||
if (clear & TIOCM_DTR)
|
if (clear & TIOCM_DTR)
|
||||||
info->zs_chan_a->curregs[5] &= ~DTR;
|
info->zs_chan_a->curregs[5] &= ~DTR;
|
||||||
write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]);
|
write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]);
|
||||||
sti();
|
spin_unlock_irq(&zs_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1198,19 +1185,18 @@ static void rs_break(struct tty_struct *tty, int break_state)
|
||||||
if (!info->port)
|
if (!info->port)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
save_flags(flags); cli();
|
spin_lock_irqsave(&zs_lock, flags);
|
||||||
if (break_state == -1)
|
if (break_state == -1)
|
||||||
info->zs_channel->curregs[5] |= SND_BRK;
|
info->zs_channel->curregs[5] |= SND_BRK;
|
||||||
else
|
else
|
||||||
info->zs_channel->curregs[5] &= ~SND_BRK;
|
info->zs_channel->curregs[5] &= ~SND_BRK;
|
||||||
write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
|
write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
|
||||||
restore_flags(flags);
|
spin_unlock_irqrestore(&zs_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rs_ioctl(struct tty_struct *tty, struct file * file,
|
static int rs_ioctl(struct tty_struct *tty, struct file * file,
|
||||||
unsigned int cmd, unsigned long arg)
|
unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
int error;
|
|
||||||
struct dec_serial * info = (struct dec_serial *)tty->driver_data;
|
struct dec_serial * info = (struct dec_serial *)tty->driver_data;
|
||||||
|
|
||||||
if (info->hook)
|
if (info->hook)
|
||||||
|
@ -1287,10 +1273,10 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
|
||||||
if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
|
if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
save_flags(flags); cli();
|
spin_lock_irqsave(&zs_lock, flags);
|
||||||
|
|
||||||
if (tty_hung_up_p(filp)) {
|
if (tty_hung_up_p(filp)) {
|
||||||
restore_flags(flags);
|
spin_unlock_irqrestore(&zs_lock, flags);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1315,7 +1301,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
|
||||||
info->count = 0;
|
info->count = 0;
|
||||||
}
|
}
|
||||||
if (info->count) {
|
if (info->count) {
|
||||||
restore_flags(flags);
|
spin_unlock_irqrestore(&zs_lock, flags);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
info->flags |= ZILOG_CLOSING;
|
info->flags |= ZILOG_CLOSING;
|
||||||
|
@ -1358,7 +1344,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
|
||||||
}
|
}
|
||||||
info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CLOSING);
|
info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CLOSING);
|
||||||
wake_up_interruptible(&info->close_wait);
|
wake_up_interruptible(&info->close_wait);
|
||||||
restore_flags(flags);
|
spin_unlock_irqrestore(&zs_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1398,7 +1384,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
|
||||||
/*
|
/*
|
||||||
* rs_hangup() --- called by tty_hangup() when a hangup is signaled.
|
* rs_hangup() --- called by tty_hangup() when a hangup is signaled.
|
||||||
*/
|
*/
|
||||||
void rs_hangup(struct tty_struct *tty)
|
static void rs_hangup(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
struct dec_serial * info = (struct dec_serial *)tty->driver_data;
|
struct dec_serial * info = (struct dec_serial *)tty->driver_data;
|
||||||
|
|
||||||
|
@ -1466,16 +1452,16 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
|
||||||
printk("block_til_ready before block: ttyS%d, count = %d\n",
|
printk("block_til_ready before block: ttyS%d, count = %d\n",
|
||||||
info->line, info->count);
|
info->line, info->count);
|
||||||
#endif
|
#endif
|
||||||
cli();
|
spin_lock(&zs_lock);
|
||||||
if (!tty_hung_up_p(filp))
|
if (!tty_hung_up_p(filp))
|
||||||
info->count--;
|
info->count--;
|
||||||
sti();
|
spin_unlock_irq(&zs_lock);
|
||||||
info->blocked_open++;
|
info->blocked_open++;
|
||||||
while (1) {
|
while (1) {
|
||||||
cli();
|
spin_lock(&zs_lock);
|
||||||
if (tty->termios->c_cflag & CBAUD)
|
if (tty->termios->c_cflag & CBAUD)
|
||||||
zs_rtsdtr(info, RTS | DTR, 1);
|
zs_rtsdtr(info, RTS | DTR, 1);
|
||||||
sti();
|
spin_unlock_irq(&zs_lock);
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
if (tty_hung_up_p(filp) ||
|
if (tty_hung_up_p(filp) ||
|
||||||
!(info->flags & ZILOG_INITIALIZED)) {
|
!(info->flags & ZILOG_INITIALIZED)) {
|
||||||
|
@ -1523,7 +1509,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
|
||||||
* the IRQ chain. It also performs the serial-specific
|
* the IRQ chain. It also performs the serial-specific
|
||||||
* initialization for the tty structure.
|
* initialization for the tty structure.
|
||||||
*/
|
*/
|
||||||
int rs_open(struct tty_struct *tty, struct file * filp)
|
static int rs_open(struct tty_struct *tty, struct file * filp)
|
||||||
{
|
{
|
||||||
struct dec_serial *info;
|
struct dec_serial *info;
|
||||||
int retval, line;
|
int retval, line;
|
||||||
|
@ -1706,7 +1692,7 @@ static void __init probe_sccs(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
save_and_cli(flags);
|
spin_lock_irqsave(&zs_lock, flags);
|
||||||
for (n = 0; n < zs_channels_found; n++) {
|
for (n = 0; n < zs_channels_found; n++) {
|
||||||
if (n % 2 == 0) {
|
if (n % 2 == 0) {
|
||||||
write_zsreg(zs_soft[n].zs_chan_a, R9, FHWRES);
|
write_zsreg(zs_soft[n].zs_chan_a, R9, FHWRES);
|
||||||
|
@ -1716,7 +1702,7 @@ static void __init probe_sccs(void)
|
||||||
load_zsregs(zs_soft[n].zs_channel,
|
load_zsregs(zs_soft[n].zs_channel,
|
||||||
zs_soft[n].zs_channel->curregs);
|
zs_soft[n].zs_channel->curregs);
|
||||||
}
|
}
|
||||||
restore_flags(flags);
|
spin_unlock_irqrestore(&zs_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct tty_operations serial_ops = {
|
static struct tty_operations serial_ops = {
|
||||||
|
@ -1749,9 +1735,6 @@ int __init zs_init(void)
|
||||||
if(!BUS_PRESENT)
|
if(!BUS_PRESENT)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* Setup base handler, and timer table. */
|
|
||||||
init_bh(SERIAL_BH, do_serial_bh);
|
|
||||||
|
|
||||||
/* Find out how many Z8530 SCCs we have */
|
/* Find out how many Z8530 SCCs we have */
|
||||||
if (zs_chain == 0)
|
if (zs_chain == 0)
|
||||||
probe_sccs();
|
probe_sccs();
|
||||||
|
@ -1800,8 +1783,7 @@ int __init zs_init(void)
|
||||||
info->event = 0;
|
info->event = 0;
|
||||||
info->count = 0;
|
info->count = 0;
|
||||||
info->blocked_open = 0;
|
info->blocked_open = 0;
|
||||||
info->tqueue.routine = do_softint;
|
tasklet_init(&info->tlet, do_softint, (unsigned long)info);
|
||||||
info->tqueue.data = info;
|
|
||||||
init_waitqueue_head(&info->open_wait);
|
init_waitqueue_head(&info->open_wait);
|
||||||
init_waitqueue_head(&info->close_wait);
|
init_waitqueue_head(&info->close_wait);
|
||||||
printk("ttyS%02d at 0x%08x (irq = %d) is a Z85C30 SCC\n",
|
printk("ttyS%02d at 0x%08x (irq = %d) is a Z85C30 SCC\n",
|
||||||
|
@ -1833,8 +1815,7 @@ int __init zs_init(void)
|
||||||
/*
|
/*
|
||||||
* polling I/O routines
|
* polling I/O routines
|
||||||
*/
|
*/
|
||||||
static int
|
static int zs_poll_tx_char(void *handle, unsigned char ch)
|
||||||
zs_poll_tx_char(void *handle, unsigned char ch)
|
|
||||||
{
|
{
|
||||||
struct dec_serial *info = handle;
|
struct dec_serial *info = handle;
|
||||||
struct dec_zschannel *chan = info->zs_channel;
|
struct dec_zschannel *chan = info->zs_channel;
|
||||||
|
@ -1857,8 +1838,7 @@ zs_poll_tx_char(void *handle, unsigned char ch)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int zs_poll_rx_char(void *handle)
|
||||||
zs_poll_rx_char(void *handle)
|
|
||||||
{
|
{
|
||||||
struct dec_serial *info = handle;
|
struct dec_serial *info = handle;
|
||||||
struct dec_zschannel *chan = info->zs_channel;
|
struct dec_zschannel *chan = info->zs_channel;
|
||||||
|
@ -2037,7 +2017,7 @@ static int __init serial_console_setup(struct console *co, char *options)
|
||||||
}
|
}
|
||||||
co->cflag = cflag;
|
co->cflag = cflag;
|
||||||
|
|
||||||
save_and_cli(flags);
|
spin_lock_irqsave(&zs_lock, flags);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up the baud rate generator.
|
* Set up the baud rate generator.
|
||||||
|
@ -2092,7 +2072,7 @@ static int __init serial_console_setup(struct console *co, char *options)
|
||||||
zs_soft[co->index].clk_divisor = clk_divisor;
|
zs_soft[co->index].clk_divisor = clk_divisor;
|
||||||
zs_soft[co->index].zs_baud = get_zsbaud(&zs_soft[co->index]);
|
zs_soft[co->index].zs_baud = get_zsbaud(&zs_soft[co->index]);
|
||||||
|
|
||||||
restore_flags(flags);
|
spin_unlock_irqrestore(&zs_lock, flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2229,5 +2209,3 @@ void __init zs_kgdb_hook(int tty_num)
|
||||||
set_debug_traps(); /* init stub */
|
set_debug_traps(); /* init stub */
|
||||||
}
|
}
|
||||||
#endif /* ifdef CONFIG_KGDB */
|
#endif /* ifdef CONFIG_KGDB */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,14 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
|
* Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
|
||||||
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
||||||
* Copyright (C) 2004 Maciej W. Rozycki
|
* Copyright (C) 2004, 2005 Maciej W. Rozycki
|
||||||
*/
|
*/
|
||||||
#ifndef _DECSERIAL_H
|
#ifndef _DECSERIAL_H
|
||||||
#define _DECSERIAL_H
|
#define _DECSERIAL_H
|
||||||
|
|
||||||
#include <asm/dec/serial.h>
|
#include <asm/dec/serial.h>
|
||||||
|
|
||||||
#define NUM_ZSREGS 16
|
#define NUM_ZSREGS 16
|
||||||
|
|
||||||
struct serial_struct {
|
struct serial_struct {
|
||||||
int type;
|
int type;
|
||||||
|
@ -139,8 +139,7 @@ struct dec_serial {
|
||||||
int xmit_head;
|
int xmit_head;
|
||||||
int xmit_tail;
|
int xmit_tail;
|
||||||
int xmit_cnt;
|
int xmit_cnt;
|
||||||
struct tq_struct tqueue;
|
struct tasklet_struct tlet;
|
||||||
struct tq_struct tqueue_hangup;
|
|
||||||
wait_queue_head_t open_wait;
|
wait_queue_head_t open_wait;
|
||||||
wait_queue_head_t close_wait;
|
wait_queue_head_t close_wait;
|
||||||
};
|
};
|
||||||
|
@ -282,7 +281,7 @@ struct dec_serial {
|
||||||
#define DLC 4 /* Disable Lower Chain */
|
#define DLC 4 /* Disable Lower Chain */
|
||||||
#define MIE 8 /* Master Interrupt Enable */
|
#define MIE 8 /* Master Interrupt Enable */
|
||||||
#define STATHI 0x10 /* Status high */
|
#define STATHI 0x10 /* Status high */
|
||||||
#define SOFTACK 0x20 /* Software Interrupt Acknowledge */
|
#define SOFTACK 0x20 /* Software Interrupt Acknowledge */
|
||||||
#define NORESET 0 /* No reset on write to R9 */
|
#define NORESET 0 /* No reset on write to R9 */
|
||||||
#define CHRB 0x40 /* Reset channel B */
|
#define CHRB 0x40 /* Reset channel B */
|
||||||
#define CHRA 0x80 /* Reset channel A */
|
#define CHRA 0x80 /* Reset channel A */
|
||||||
|
@ -395,8 +394,8 @@ struct dec_serial {
|
||||||
/* Read Register 15 (value of WR 15) */
|
/* Read Register 15 (value of WR 15) */
|
||||||
|
|
||||||
/* Misc macros */
|
/* Misc macros */
|
||||||
#define ZS_CLEARERR(channel) (write_zsreg(channel, 0, ERR_RES))
|
#define ZS_CLEARERR(channel) (write_zsreg(channel, 0, ERR_RES))
|
||||||
#define ZS_CLEARFIFO(channel) do { volatile unsigned char garbage; \
|
#define ZS_CLEARFIFO(channel) do { volatile unsigned char garbage; \
|
||||||
garbage = read_zsdata(channel); \
|
garbage = read_zsdata(channel); \
|
||||||
garbage = read_zsdata(channel); \
|
garbage = read_zsdata(channel); \
|
||||||
garbage = read_zsdata(channel); \
|
garbage = read_zsdata(channel); \
|
||||||
|
|
Loading…
Reference in New Issue