Commit 00bd610d authored by Pete Zaitcev's avatar Pete Zaitcev Committed by David S. Miller

[SPARC]: Get kbd/mouse working again with sunzilog serial.

parent 322d9100
...@@ -292,6 +292,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up, ...@@ -292,6 +292,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
struct pt_regs *regs) struct pt_regs *regs)
{ {
if (ZS_IS_KEYB(up)) { if (ZS_IS_KEYB(up)) {
/* if (!serial_console) XXX Keith's case #1 - two brks work */
if (ch == SUNKBD_RESET) { if (ch == SUNKBD_RESET) {
up->kbd_id = 1; up->kbd_id = 1;
up->l1_down = 0; up->l1_down = 0;
...@@ -308,6 +309,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up, ...@@ -308,6 +309,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
return; return;
} }
#ifdef CONFIG_SERIO #ifdef CONFIG_SERIO
if (up->serio_open)
serio_interrupt(&up->serio, ch, 0, regs); serio_interrupt(&up->serio, ch, 0, regs);
#endif #endif
} else if (ZS_IS_MOUSE(up)) { } else if (ZS_IS_MOUSE(up)) {
...@@ -322,6 +324,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up, ...@@ -322,6 +324,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
case 0: case 0:
#ifdef CONFIG_SERIO #ifdef CONFIG_SERIO
if (up->serio_open)
serio_interrupt(&up->serio, ch, 0, regs); serio_interrupt(&up->serio, ch, 0, regs);
#endif #endif
break; break;
...@@ -333,16 +336,15 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up, ...@@ -333,16 +336,15 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up,
struct zilog_channel *channel, struct zilog_channel *channel,
struct pt_regs *regs) struct pt_regs *regs)
{ {
struct tty_struct *tty = up->port.info->tty; /* XXX info==NULL? */ struct tty_struct *tty;
while (1) {
unsigned char ch, r1; unsigned char ch, r1;
if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { tty = NULL;
tty->flip.work.func((void *)tty); if (up->port.info != NULL && /* Unopened serial console */
if (tty->flip.count >= TTY_FLIPBUF_SIZE) up->port.info->tty != NULL) /* Keyboard || mouse */
return; /* XXX Ignores SysRq when we need it most. Fix. */ tty = up->port.info->tty;
}
for (;;) {
r1 = read_zsreg(channel, R1); r1 = read_zsreg(channel, R1);
if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) { if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
...@@ -360,6 +362,9 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up, ...@@ -360,6 +362,9 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up,
if (ch & BRK_ABRT) if (ch & BRK_ABRT)
r1 |= BRK_ABRT; r1 |= BRK_ABRT;
if (!(ch & Rx_CH_AV))
break;
ch = sbus_readb(&channel->data); ch = sbus_readb(&channel->data);
ZSDELAY(); ZSDELAY();
...@@ -367,21 +372,22 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up, ...@@ -367,21 +372,22 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up,
if (unlikely(ZS_IS_KEYB(up)) || unlikely(ZS_IS_MOUSE(up))) { if (unlikely(ZS_IS_KEYB(up)) || unlikely(ZS_IS_MOUSE(up))) {
sunzilog_kbdms_receive_chars(up, ch, 0, regs); sunzilog_kbdms_receive_chars(up, ch, 0, regs);
goto next_char; continue;
} }
if (ZS_IS_CONS(up) && (r1 & BRK_ABRT)) { if (tty == NULL) {
/* Wait for BREAK to deassert to avoid potentially uart_handle_sysrq_char(&up->port, ch, regs);
* confusing the PROM. continue;
*/
while (1) {
ch = sbus_readb(&channel->control);
ZSDELAY();
if (!(ch & BRK_ABRT))
break;
} }
sun_do_break();
return; if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
tty->flip.work.func((void *)tty);
/*
* The 8250 bails out of the loop here,
* but we need to read everything, or die.
*/
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
continue;
} }
/* A real serial line, record the character and status. */ /* A real serial line, record the character and status. */
...@@ -393,7 +399,7 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up, ...@@ -393,7 +399,7 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up,
r1 &= ~(PAR_ERR | CRC_ERR); r1 &= ~(PAR_ERR | CRC_ERR);
up->port.icount.brk++; up->port.icount.brk++;
if (uart_handle_break(&up->port)) if (uart_handle_break(&up->port))
goto next_char; continue;
} }
else if (r1 & PAR_ERR) else if (r1 & PAR_ERR)
up->port.icount.parity++; up->port.icount.parity++;
...@@ -410,7 +416,7 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up, ...@@ -410,7 +416,7 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up,
*tty->flip.flag_buf_ptr = TTY_FRAME; *tty->flip.flag_buf_ptr = TTY_FRAME;
} }
if (uart_handle_sysrq_char(&up->port, ch, regs)) if (uart_handle_sysrq_char(&up->port, ch, regs))
goto next_char; continue;
if (up->port.ignore_status_mask == 0xff || if (up->port.ignore_status_mask == 0xff ||
(r1 & up->port.ignore_status_mask) == 0) { (r1 & up->port.ignore_status_mask) == 0) {
...@@ -425,13 +431,9 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up, ...@@ -425,13 +431,9 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up,
tty->flip.char_buf_ptr++; tty->flip.char_buf_ptr++;
tty->flip.count++; tty->flip.count++;
} }
next_char:
ch = sbus_readb(&channel->control);
ZSDELAY();
if (!(ch & Rx_CH_AV))
break;
} }
if (tty)
tty_flip_buffer_push(tty); tty_flip_buffer_push(tty);
} }
...@@ -448,8 +450,23 @@ static void sunzilog_status_handle(struct uart_sunzilog_port *up, ...@@ -448,8 +450,23 @@ static void sunzilog_status_handle(struct uart_sunzilog_port *up,
ZSDELAY(); ZSDELAY();
ZS_WSYNC(channel); ZS_WSYNC(channel);
if ((status & BRK_ABRT) && ZS_IS_MOUSE(up)) if (status & BRK_ABRT) {
if (ZS_IS_MOUSE(up))
sunzilog_kbdms_receive_chars(up, 0, 1, regs); sunzilog_kbdms_receive_chars(up, 0, 1, regs);
if (ZS_IS_CONS(up)) {
/* Wait for BREAK to deassert to avoid potentially
* confusing the PROM.
*/
while (1) {
status = sbus_readb(&channel->control);
ZSDELAY();
if (!(status & BRK_ABRT))
break;
}
sun_do_break();
return;
}
}
if (ZS_WANTS_MODEM_STATUS(up)) { if (ZS_WANTS_MODEM_STATUS(up)) {
if (status & SYNC) if (status & SYNC)
...@@ -1364,8 +1381,8 @@ static int __init sunzilog_console_setup(struct console *con, char *options) ...@@ -1364,8 +1381,8 @@ static int __init sunzilog_console_setup(struct console *con, char *options)
unsigned long flags; unsigned long flags;
int baud, brg; int baud, brg;
printk("Console: ttyS%d (SunZilog)\n", printk(KERN_INFO "Console: ttyS%d (SunZilog zs%d)\n",
(sunzilog_reg.minor - 64) + con->index); (sunzilog_reg.minor - 64) + con->index, con->index);
/* Get firmware console settings. */ /* Get firmware console settings. */
sunserial_console_termios(con); sunserial_console_termios(con);
...@@ -1596,6 +1613,8 @@ static void __init sunzilog_init_hw(void) ...@@ -1596,6 +1613,8 @@ static void __init sunzilog_init_hw(void)
if (i == KEYBOARD_LINE || i == MOUSE_LINE) { if (i == KEYBOARD_LINE || i == MOUSE_LINE) {
sunzilog_init_kbdms(up, i); sunzilog_init_kbdms(up, i);
up->curregs[R9] |= (NV | MIE);
write_zsreg(channel, R9, up->curregs[R9]);
} else { } else {
/* Normal serial TTY. */ /* Normal serial TTY. */
up->parity_mask = 0xff; up->parity_mask = 0xff;
...@@ -1632,7 +1651,7 @@ static int __init sunzilog_ports_init(void) ...@@ -1632,7 +1651,7 @@ static int __init sunzilog_ports_init(void)
struct zs_probe_scan scan; struct zs_probe_scan scan;
int ret; int ret;
printk(KERN_INFO "Serial: Sun Zilog driver (%d chips).\n", NUM_SUNZILOG); printk(KERN_DEBUG "SunZilog: %d chips.\n", NUM_SUNZILOG);
scan.scanner = sunzilog_scan_probe; scan.scanner = sunzilog_scan_probe;
scan.depth = 0; scan.depth = 0;
...@@ -1668,7 +1687,10 @@ static int __init sunzilog_ports_init(void) ...@@ -1668,7 +1687,10 @@ static int __init sunzilog_ports_init(void)
if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up))
continue; continue;
uart_add_one_port(&sunzilog_reg, &up->port); if (uart_add_one_port(&sunzilog_reg, &up->port)) {
printk(KERN_ERR
"SunZilog: failed to add port zs%d\n", i);
}
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment