Commit b3718602 authored by David S. Miller's avatar David S. Miller

SPARC UART: More build fixes.

parent 7e0fc16e
...@@ -13,13 +13,19 @@ ...@@ -13,13 +13,19 @@
#ifndef _SERIAL_SUN_H #ifndef _SERIAL_SUN_H
#define _SERIAL_SUN_H #define _SERIAL_SUN_H
#include <linux/config.h> /* Serial keyboard defines for L1-A processing... */
#define SUNKBD_RESET 0xff
#define SUNKBD_L1 0x01
#define SUNKBD_UP 0x80
#define SUNKBD_A 0x4d
extern void sun_do_break(void); extern void sun_do_break(void);
extern unsigned int suncore_mouse_baud_cflag_next(unsigned int, int *); extern unsigned int suncore_mouse_baud_cflag_next(unsigned int, int *);
extern int suncore_mouse_baud_detection(unsigned char, int); extern int suncore_mouse_baud_detection(unsigned char, int);
extern struct pt_regs *kbd_pt_regs;
extern int serial_console; extern int serial_console;
extern int stop_a_enabled; extern int stop_a_enabled;
extern int sunserial_current_minor; extern int sunserial_current_minor;
......
...@@ -15,21 +15,46 @@ ...@@ -15,21 +15,46 @@
* David S. Miller (davem@redhat.com), 2002-Jul-29 * David S. Miller (davem@redhat.com), 2002-Jul-29
*/ */
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/major.h>
#include <linux/string.h>
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/circ_buf.h>
#include <linux/serial.h>
#include <linux/console.h>
#include <linux/spinlock.h>
#ifdef CONFIG_SERIO #ifdef CONFIG_SERIO
#include <linux/serio.h> #include <linux/serio.h>
#endif #endif
#include <linux/init.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/oplib.h>
#include <asm/ebus.h>
#ifdef CONFIG_SPARC64
#include <asm/isa.h>
#endif
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
#include "suncore.h" #include "suncore.h"
#include "sunkbd.h"
#include "sunmouse.h"
/* We are on a NS PC87303 clocked with 24.0 MHz, which results /* We are on a NS PC87303 clocked with 24.0 MHz, which results
* in a UART clock of 1.8462 MHz. * in a UART clock of 1.8462 MHz.
*/ */
#define BAUD_BASE (1846200 / 16) #define SU_BASE_BAUD (1846200 / 16)
enum su_type { SU_PORT_NONE, SU_PORT_MS, SU_PORT_KBD, SU_PORT_PORT }; enum su_type { SU_PORT_NONE, SU_PORT_MS, SU_PORT_KBD, SU_PORT_PORT };
static char *su_typev[] = { "???", "mouse", "kbd", "serial" }; static char *su_typev[] = { "su(???)", "su(mouse)", "su(kbd)", "su(serial)" };
/* /*
* Here we define the default xmit fifo size used for each type of UART. * Here we define the default xmit fifo size used for each type of UART.
...@@ -51,6 +76,28 @@ static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = { ...@@ -51,6 +76,28 @@ static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = {
{ "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO } { "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO }
}; };
struct uart_sunsu_port {
struct uart_port port;
unsigned char acr;
unsigned char ier;
unsigned char rev;
unsigned char lcr;
unsigned int lsr_break_flag;
unsigned int cflag;
/* Probing information. */
enum su_type su_type;
int port_node;
unsigned int irq;
/* L1-A keyboard break state. */
int kbd_id;
int l1_down;
#ifdef CONFIG_SERIO
struct serio serio;
#endif
};
#define _INLINE_ #define _INLINE_
static _INLINE_ unsigned int serial_in(struct uart_sunsu_port *up, int offset) static _INLINE_ unsigned int serial_in(struct uart_sunsu_port *up, int offset)
...@@ -121,6 +168,7 @@ static void serial_icr_write(struct uart_sunsu_port *up, int offset, int value) ...@@ -121,6 +168,7 @@ static void serial_icr_write(struct uart_sunsu_port *up, int offset, int value)
serial_out(up, UART_ICR, value); serial_out(up, UART_ICR, value);
} }
#if 0 /* Unused currently */
static unsigned int serial_icr_read(struct uart_sunsu_port *up, int offset) static unsigned int serial_icr_read(struct uart_sunsu_port *up, int offset)
{ {
unsigned int value; unsigned int value;
...@@ -132,6 +180,7 @@ static unsigned int serial_icr_read(struct uart_sunsu_port *up, int offset) ...@@ -132,6 +180,7 @@ static unsigned int serial_icr_read(struct uart_sunsu_port *up, int offset)
return value; return value;
} }
#endif
#ifdef CONFIG_SERIAL_8250_RSA #ifdef CONFIG_SERIAL_8250_RSA
/* /*
...@@ -257,7 +306,7 @@ static void sunsu_enable_ms(struct uart_port *port) ...@@ -257,7 +306,7 @@ static void sunsu_enable_ms(struct uart_port *port)
} }
static _INLINE_ void static _INLINE_ void
receive_chars(struct uart_sunsu_port *up, int *status, struct pt_regs *regs) receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs *regs)
{ {
struct tty_struct *tty = up->port.info->tty; struct tty_struct *tty = up->port.info->tty;
unsigned char ch; unsigned char ch;
...@@ -283,7 +332,7 @@ receive_chars(struct uart_sunsu_port *up, int *status, struct pt_regs *regs) ...@@ -283,7 +332,7 @@ receive_chars(struct uart_sunsu_port *up, int *status, struct pt_regs *regs)
if (*status & UART_LSR_BI) { if (*status & UART_LSR_BI) {
*status &= ~(UART_LSR_FE | UART_LSR_PE); *status &= ~(UART_LSR_FE | UART_LSR_PE);
up->port.icount.brk++; up->port.icount.brk++;
if (SU_IS_CONS(up)) if (up->port.line == up->port.cons->index)
saw_console_brk = 1; saw_console_brk = 1;
/* /*
* We do the SysRQ and SAK checking * We do the SysRQ and SAK checking
...@@ -410,7 +459,7 @@ static void sunsu_serial_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -410,7 +459,7 @@ static void sunsu_serial_interrupt(int irq, void *dev_id, struct pt_regs *regs)
do { do {
status = serial_inp(up, UART_LSR); status = serial_inp(up, UART_LSR);
if (status & UART_LSR_DR) if (status & UART_LSR_DR)
receive_serial_chars(up, &status, regs); receive_chars(up, &status, regs);
check_modem_status(up); check_modem_status(up);
if (status & UART_LSR_THRE) if (status & UART_LSR_THRE)
transmit_chars(up); transmit_chars(up);
...@@ -427,17 +476,17 @@ sunsu_change_speed(struct uart_port *port, unsigned int cflag, ...@@ -427,17 +476,17 @@ sunsu_change_speed(struct uart_port *port, unsigned int cflag,
static void sunsu_change_mouse_baud(struct uart_sunsu_port *up) static void sunsu_change_mouse_baud(struct uart_sunsu_port *up)
{ {
unsigned int cur_cflag = up->port.cflag; unsigned int cur_cflag = up->cflag;
int quot, new_baud; int quot, new_baud;
up->port.cflag &= ~CBAUD; up->cflag &= ~CBAUD;
up->port.cflag |= suncore_mouse_baud_cflag_next(cur_cflag, &new_baud); up->cflag |= suncore_mouse_baud_cflag_next(cur_cflag, &new_baud);
quot = sunsu_calc_quot(new_baud); quot = up->port.uartclk / (16 * new_baud);
spin_unlock(&up->port.lock); spin_unlock(&up->port.lock);
sunsu_change_speed(up, up->port.cflag, 0, quot); sunsu_change_speed(&up->port, up->cflag, 0, quot);
spin_lock(&up->port.lock); spin_lock(&up->port.lock);
} }
...@@ -447,7 +496,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg ...@@ -447,7 +496,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg
do { do {
unsigned char ch = serial_inp(up, UART_RX); unsigned char ch = serial_inp(up, UART_RX);
if (up->port_type == SU_PORT_KBD) { if (up->su_type == SU_PORT_KBD) {
if (ch == SUNKBD_RESET) { if (ch == SUNKBD_RESET) {
up->kbd_id = 1; up->kbd_id = 1;
up->l1_down = 0; up->l1_down = 0;
...@@ -470,7 +519,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg ...@@ -470,7 +519,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg
#ifdef CONFIG_SERIO #ifdef CONFIG_SERIO
serio_interrupt(&up->serio, ch, 0); serio_interrupt(&up->serio, ch, 0);
#endif #endif
} else if (up->port_type == SU_PORT_MS) { } else if (up->su_type == SU_PORT_MS) {
int ret = suncore_mouse_baud_detection(ch, is_break); int ret = suncore_mouse_baud_detection(ch, is_break);
switch (ret) { switch (ret) {
...@@ -629,6 +678,18 @@ static int sunsu_startup(struct uart_port *port) ...@@ -629,6 +678,18 @@ static int sunsu_startup(struct uart_port *port)
return -ENODEV; return -ENODEV;
} }
if (up->su_type != SU_PORT_PORT) {
retval = request_irq(up->irq, sunsu_kbd_ms_interrupt,
SA_SHIRQ, su_typev[up->su_type], up);
} else {
retval = request_irq(up->irq, sunsu_serial_interrupt,
SA_SHIRQ, su_typev[up->su_type], up);
}
if (retval) {
printk("su: Cannot register IRQ\n");
return retval;
}
/* /*
* Now, initialize the UART * Now, initialize the UART
*/ */
...@@ -831,6 +892,9 @@ sunsu_change_speed(struct uart_port *port, unsigned int cflag, ...@@ -831,6 +892,9 @@ sunsu_change_speed(struct uart_port *port, unsigned int cflag,
} }
serial_outp(up, UART_FCR, fcr); /* set fcr */ serial_outp(up, UART_FCR, fcr); /* set fcr */
} }
up->cflag = cflag;
spin_unlock_irqrestore(&up->port.lock, flags); spin_unlock_irqrestore(&up->port.lock, flags);
} }
...@@ -875,7 +939,6 @@ static struct uart_ops sunsu_pops = { ...@@ -875,7 +939,6 @@ static struct uart_ops sunsu_pops = {
.startup = sunsu_startup, .startup = sunsu_startup,
.shutdown = sunsu_shutdown, .shutdown = sunsu_shutdown,
.change_speed = sunsu_change_speed, .change_speed = sunsu_change_speed,
.pm = sunsu_pm,
.type = sunsu_type, .type = sunsu_type,
.release_port = sunsu_release_port, .release_port = sunsu_release_port,
.request_port = sunsu_request_port, .request_port = sunsu_request_port,
...@@ -891,7 +954,7 @@ static struct uart_sunsu_port sunsu_ports[UART_NR]; ...@@ -891,7 +954,7 @@ static struct uart_sunsu_port sunsu_ports[UART_NR];
static spinlock_t sunsu_serio_lock = SPIN_LOCK_UNLOCKED; static spinlock_t sunsu_serio_lock = SPIN_LOCK_UNLOCKED;
static void sunsu_serio_write(struct serio *serio, unsigned char ch) static int sunsu_serio_write(struct serio *serio, unsigned char ch)
{ {
struct uart_sunsu_port *up = serio->driver; struct uart_sunsu_port *up = serio->driver;
unsigned long flags; unsigned long flags;
...@@ -904,9 +967,11 @@ static void sunsu_serio_write(struct serio *serio, unsigned char ch) ...@@ -904,9 +967,11 @@ static void sunsu_serio_write(struct serio *serio, unsigned char ch)
} while (!(lsr & UART_LSR_THRE)); } while (!(lsr & UART_LSR_THRE));
/* Send the character out. */ /* Send the character out. */
sunsu_writeb(up, UART_TX, c); serial_out(up, UART_TX, ch);
spin_unlock_irqrestore(&sunsu_serio_lock, flags); spin_unlock_irqrestore(&sunsu_serio_lock, flags);
return 0;
} }
static int sunsu_serio_open(struct serio *serio) static int sunsu_serio_open(struct serio *serio)
...@@ -951,7 +1016,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up) ...@@ -951,7 +1016,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up)
#endif #endif
unsigned long flags; unsigned long flags;
if (!up->port_node || !up->port_type) if (!up->port_node || !up->su_type)
return; return;
/* /*
...@@ -1118,7 +1183,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up) ...@@ -1118,7 +1183,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up)
} }
serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
} }
serial_outp(up, UART_LCR, scratch2); serial_outp(up, UART_LCR, save_lcr);
if (up->port.type == PORT_16450) { if (up->port.type == PORT_16450) {
scratch = serial_in(up, UART_SCR); scratch = serial_in(up, UART_SCR);
serial_outp(up, UART_SCR, 0xa5); serial_outp(up, UART_SCR, 0xa5);
...@@ -1131,13 +1196,11 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up) ...@@ -1131,13 +1196,11 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up)
up->port.type = PORT_8250; up->port.type = PORT_8250;
} }
up->port.xmit_fifo_size = uart_config[up->port.type].dfl_xmit_fifo_size; up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size;
if (up->port.type == PORT_UNKNOWN) if (up->port.type == PORT_UNKNOWN)
goto out; goto out;
sprintf(up->name, "su(%s)", su_typev[up->port_type]);
/* /*
* Reset the UART. * Reset the UART.
*/ */
...@@ -1168,59 +1231,7 @@ static struct uart_driver sunsu_reg = { ...@@ -1168,59 +1231,7 @@ static struct uart_driver sunsu_reg = {
.major = TTY_MAJOR, .major = TTY_MAJOR,
}; };
static int __init sunsu_serial_init(void) static int __init sunsu_kbd_ms_init(void)
{
int instance, ret;
/* How many instances do we need? */
instance = 0;
for (i = 0; i < UART_NR; i++) {
if (up->port_type == SU_PORT_MS ||
up->port_type == SU_PORT_KBD)
continue;
up->port.type = PORT_UNKNOWN;
up->port.baud_base = BAUD_BASE;
sunsu_autoconfig(up);
if (up->port.type == PORT_UNKNOWN)
continue;
up->port.line = instance++;
up->port.ops = &sunsu_pops;
}
sunsu_reg.minor = sunserial_current_minor;
sunserial_current_minor += instance;
sunsu_reg.nr = instance;
sunsu_reg.cons = &sunsu_console;
ret = uart_register_driver(&sunsu_reg);
if (ret < 0)
return ret;
instance = 0;
for (i = 0; i < UART_NR; i++) {
struct uart_sunsu_port *up = &sunsu_port[i];
/* Do not register Keyboard/Mouse lines with UART
* layer.
*/
if (up->port_type == SU_PORT_MS ||
up->port_type == SU_PORT_KBD)
continue;
if (up->port.type == PORT_UNKNOWN)
continue;
uart_add_one_port(&sunsu_reg, up);
}
return 0;
}
static int __init su_kbd_ms_init(void)
{ {
struct uart_sunsu_port *up; struct uart_sunsu_port *up;
int i; int i;
...@@ -1228,12 +1239,12 @@ static int __init su_kbd_ms_init(void) ...@@ -1228,12 +1239,12 @@ static int __init su_kbd_ms_init(void)
for (i = 0, up = sunsu_ports; i < 2; i++, up++) { for (i = 0, up = sunsu_ports; i < 2; i++, up++) {
up->port.line = i; up->port.line = i;
up->port.type = PORT_UNKNOWN; up->port.type = PORT_UNKNOWN;
up->port.baud_base = BAUD_BASE; up->port.uartclk = (SU_BASE_BAUD * 16);
if (up->port_type == SU_PORT_KBD) if (up->su_type == SU_PORT_KBD)
up->port.cflag = B1200 | CS8 | CLOCAL | CREAD; up->cflag = B1200 | CS8 | CLOCAL | CREAD;
else else
up->port.cflag = B4800 | CS8 | CLOCAL | CREAD; up->cflag = B4800 | CS8 | CLOCAL | CREAD;
sunsu_autoconfig(up); sunsu_autoconfig(up);
if (up->port.type == PORT_UNKNOWN) if (up->port.type == PORT_UNKNOWN)
...@@ -1250,14 +1261,14 @@ static int __init su_kbd_ms_init(void) ...@@ -1250,14 +1261,14 @@ static int __init su_kbd_ms_init(void)
up->serio.driver = up; up->serio.driver = up;
up->serio.type = SERIO_RS232; up->serio.type = SERIO_RS232;
if (up->port_type == SU_PORT_KBD) { if (up->su_type == SU_PORT_KBD) {
up->serio.type |= SERIO_SUNKBD; up->serio.type |= SERIO_SUNKBD;
up->serio.name = "sukbd"; up->serio.name = "sukbd";
} else { } else {
up->serio.type |= SERIO_SUN; up->serio.type |= SERIO_SUN;
up->serio.name = "sums"; up->serio.name = "sums";
} }
up->phys = (i == 0 ? "su/serio0" : "su/serio1"); up->serio.phys = (i == 0 ? "su/serio0" : "su/serio1");
up->serio.write = sunsu_serio_write; up->serio.write = sunsu_serio_write;
up->serio.open = sunsu_serio_open; up->serio.open = sunsu_serio_open;
...@@ -1266,7 +1277,7 @@ static int __init su_kbd_ms_init(void) ...@@ -1266,7 +1277,7 @@ static int __init su_kbd_ms_init(void)
serio_register_port(&up->serio); serio_register_port(&up->serio);
#endif #endif
sunsu_startup(up); sunsu_startup(&up->port);
} }
return 0; return 0;
} }
...@@ -1409,13 +1420,67 @@ static int __init sunsu_serial_console_init(void) ...@@ -1409,13 +1420,67 @@ static int __init sunsu_serial_console_init(void)
return 0; return 0;
index = serial_console - 1; index = serial_console - 1;
if (su_table[index].port == 0 || su_table[index].port_node == 0) if (sunsu_ports[index].port_node == 0)
return 0; return 0;
sunsu_cons.index = index; sunsu_cons.index = index;
register_console(&sunsu_cons); register_console(&sunsu_cons);
return 0; return 0;
} }
static int __init sunsu_serial_init(void)
{
int instance, ret, i;
/* How many instances do we need? */
instance = 0;
for (i = 0; i < UART_NR; i++) {
struct uart_sunsu_port *up = &sunsu_ports[i];
if (up->su_type == SU_PORT_MS ||
up->su_type == SU_PORT_KBD)
continue;
up->port.type = PORT_UNKNOWN;
up->port.uartclk = (SU_BASE_BAUD * 16);
sunsu_autoconfig(up);
if (up->port.type == PORT_UNKNOWN)
continue;
up->port.line = instance++;
up->port.ops = &sunsu_pops;
}
sunsu_reg.minor = sunserial_current_minor;
sunserial_current_minor += instance;
sunsu_reg.nr = instance;
sunsu_reg.cons = &sunsu_cons;
ret = uart_register_driver(&sunsu_reg);
if (ret < 0)
return ret;
instance = 0;
for (i = 0; i < UART_NR; i++) {
struct uart_sunsu_port *up = &sunsu_ports[i];
/* Do not register Keyboard/Mouse lines with UART
* layer.
*/
if (up->su_type == SU_PORT_MS ||
up->su_type == SU_PORT_KBD)
continue;
if (up->port.type == PORT_UNKNOWN)
continue;
uart_add_one_port(&sunsu_reg, &up->port);
}
return 0;
}
static int su_node_ok(int node, char *name, int namelen) static int su_node_ok(int node, char *name, int namelen)
{ {
if (strncmp(name, "su", namelen) == 0 || if (strncmp(name, "su", namelen) == 0 ||
...@@ -1461,7 +1526,7 @@ struct su_probe_scan { ...@@ -1461,7 +1526,7 @@ struct su_probe_scan {
*/ */
static void __init su_probe_any(struct su_probe_scan *t, int sunode) static void __init su_probe_any(struct su_probe_scan *t, int sunode)
{ {
struct su_struct *info; struct uart_sunsu_port *up;
int len; int len;
if (t->devices >= UART_NR) if (t->devices >= UART_NR)
...@@ -1473,13 +1538,13 @@ static void __init su_probe_any(struct su_probe_scan *t, int sunode) ...@@ -1473,13 +1538,13 @@ static void __init su_probe_any(struct su_probe_scan *t, int sunode)
continue; /* Broken PROM node */ continue; /* Broken PROM node */
if (su_node_ok(sunode, t->prop, len)) { if (su_node_ok(sunode, t->prop, len)) {
info = &su_table[t->devices]; up = &sunsu_ports[t->devices];
if (t->kbnode != 0 && sunode == t->kbnode) { if (t->kbnode != 0 && sunode == t->kbnode) {
t->kbx = t->devices; t->kbx = t->devices;
info->port_type = SU_PORT_KBD; up->su_type = SU_PORT_KBD;
} else if (t->msnode != 0 && sunode == t->msnode) { } else if (t->msnode != 0 && sunode == t->msnode) {
t->msx = t->devices; t->msx = t->devices;
info->port_type = SU_PORT_MS; up->su_type = SU_PORT_MS;
} else { } else {
#ifdef CONFIG_SPARC64 #ifdef CONFIG_SPARC64
/* /*
...@@ -1492,10 +1557,9 @@ static void __init su_probe_any(struct su_probe_scan *t, int sunode) ...@@ -1492,10 +1557,9 @@ static void __init su_probe_any(struct su_probe_scan *t, int sunode)
if (prom_getbool(sunode, "keyboard")) if (prom_getbool(sunode, "keyboard"))
continue; continue;
#endif #endif
info->port_type = SU_PORT_PORT; up->su_type = SU_PORT_PORT;
} }
info->is_console = 0; up->port_node = sunode;
info->port_node = sunode;
++t->devices; ++t->devices;
} else { } else {
su_probe_any(t, prom_getchild(sunode)); su_probe_any(t, prom_getchild(sunode));
...@@ -1547,9 +1611,9 @@ static int __init sunsu_probe(void) ...@@ -1547,9 +1611,9 @@ static int __init sunsu_probe(void)
* Thus, we ignore values of .msx and .kbx, then compact ports. * Thus, we ignore values of .msx and .kbx, then compact ports.
*/ */
if (scan.msx != -1 && scan.kbx != -1) { if (scan.msx != -1 && scan.kbx != -1) {
sunsu_ports[0].port_type = SU_PORT_MS; sunsu_ports[0].su_type = SU_PORT_MS;
sunsu_ports[0].port_node = scan.msnode; sunsu_ports[0].port_node = scan.msnode;
sunsu_ports[1].port_type = SU_PORT_KBD; sunsu_ports[1].su_type = SU_PORT_KBD;
sunsu_ports[1].port_node = scan.kbnode; sunsu_ports[1].port_node = scan.kbnode;
sunsu_kbd_ms_init(); sunsu_kbd_ms_init();
...@@ -1584,13 +1648,13 @@ static void __exit sunsu_exit(void) ...@@ -1584,13 +1648,13 @@ static void __exit sunsu_exit(void)
for (i = 0; i < UART_NR; i++) { for (i = 0; i < UART_NR; i++) {
struct uart_sunsu_port *up = &sunsu_ports[i]; struct uart_sunsu_port *up = &sunsu_ports[i];
if (up->port_type == SU_PORT_MS || if (up->su_type == SU_PORT_MS ||
up->port_type == SU_PORT_KBD) { up->su_type == SU_PORT_KBD) {
#ifdef CONFIG_SERIO #ifdef CONFIG_SERIO
serio_unregister_port(&up->serio); serio_unregister_port(&up->serio);
#endif #endif
} else if (up->port.type != PORT_UNKNOWN) { } else if (up->port.type != PORT_UNKNOWN) {
uart_remove_one_port(&sunsu_reg, up); uart_remove_one_port(&sunsu_reg, &up->port);
saw_uart++; saw_uart++;
} }
} }
......
...@@ -286,7 +286,8 @@ static void sunzilog_change_mouse_baud(struct uart_sunzilog_port *up) ...@@ -286,7 +286,8 @@ static void sunzilog_change_mouse_baud(struct uart_sunzilog_port *up)
} }
static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up, static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
unsigned char ch, int is_break) unsigned char ch, int is_break,
struct pt_regs *regs)
{ {
if (ZS_IS_KEYB(up)) { if (ZS_IS_KEYB(up)) {
if (ch == SUNKBD_RESET) { if (ch == SUNKBD_RESET) {
...@@ -304,6 +305,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up, ...@@ -304,6 +305,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
up->kbd_id = 0; up->kbd_id = 0;
return; return;
} }
kbd_pt_regs = regs;
#ifdef CONFIG_SERIO #ifdef CONFIG_SERIO
serio_interrupt(&up->serio, ch, 0); serio_interrupt(&up->serio, ch, 0);
#endif #endif
...@@ -363,7 +365,7 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up, ...@@ -363,7 +365,7 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up,
ch &= up->parity_mask; ch &= up->parity_mask;
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); sunzilog_kbdms_receive_chars(up, ch, 0, regs);
goto next_char; goto next_char;
} }
...@@ -440,7 +442,8 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up, ...@@ -440,7 +442,8 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up,
} }
static void sunzilog_status_handle(struct uart_sunzilog_port *up, static void sunzilog_status_handle(struct uart_sunzilog_port *up,
struct zilog_channel *channel) struct zilog_channel *channel,
struct pt_regs *regs)
{ {
unsigned char status; unsigned char status;
...@@ -452,7 +455,7 @@ static void sunzilog_status_handle(struct uart_sunzilog_port *up, ...@@ -452,7 +455,7 @@ static void sunzilog_status_handle(struct uart_sunzilog_port *up,
ZS_WSYNC(channel); ZS_WSYNC(channel);
if ((status & BRK_ABRT) && ZS_IS_MOUSE(up)) if ((status & BRK_ABRT) && ZS_IS_MOUSE(up))
sunzilog_kbdms_receive_chars(up, 0, 1); sunzilog_kbdms_receive_chars(up, 0, 1, regs);
if (ZS_WANTS_MODEM_STATUS(up)) { if (ZS_WANTS_MODEM_STATUS(up)) {
if (status & SYNC) if (status & SYNC)
...@@ -558,7 +561,7 @@ static void sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -558,7 +561,7 @@ static void sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (r3 & CHARxIP) if (r3 & CHARxIP)
sunzilog_receive_chars(up, channel, regs); sunzilog_receive_chars(up, channel, regs);
if (r3 & CHAEXT) if (r3 & CHAEXT)
sunzilog_status_handle(up, channel); sunzilog_status_handle(up, channel, regs);
if (r3 & CHATxIP) if (r3 & CHATxIP)
sunzilog_transmit_chars(up, channel); sunzilog_transmit_chars(up, channel);
} }
...@@ -577,7 +580,7 @@ static void sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -577,7 +580,7 @@ static void sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (r3 & CHBRxIP) if (r3 & CHBRxIP)
sunzilog_receive_chars(up, channel, regs); sunzilog_receive_chars(up, channel, regs);
if (r3 & CHBEXT) if (r3 & CHBEXT)
sunzilog_status_handle(up, channel); sunzilog_status_handle(up, channel, regs);
if (r3 & CHBTxIP) if (r3 & CHBTxIP)
sunzilog_transmit_chars(up, channel); sunzilog_transmit_chars(up, channel);
} }
......
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