]> git.neil.brown.name Git - history.git/commitdiff
SPARC UART: More build fixes.
authorDavid S. Miller <davem@nuts.ninka.net>
Wed, 31 Jul 2002 17:01:38 +0000 (10:01 -0700)
committerDavid S. Miller <davem@nuts.ninka.net>
Wed, 31 Jul 2002 17:01:38 +0000 (10:01 -0700)
drivers/serial/suncore.h
drivers/serial/sunsu.c
drivers/serial/sunzilog.c

index a1ef4d18a472d43576423e39c9f80b0e8d774e9a..59f09d8cae67b1a6630104679b3f447effbdeafc 100644 (file)
 #ifndef _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 unsigned int suncore_mouse_baud_cflag_next(unsigned int, int *);
 extern int suncore_mouse_baud_detection(unsigned char, int);
 
+extern struct pt_regs *kbd_pt_regs;
+
 extern int serial_console;
 extern int stop_a_enabled;
 extern int sunserial_current_minor;
index cb7fe331bcc363d469cc66ba4f8f3ddf4e060997..7f252737444157ad953103067506f485f59ca3ef 100644 (file)
  *   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
 #include <linux/serio.h>
 #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 "sunkbd.h"
-#include "sunmouse.h"
 
 /* We are on a NS PC87303 clocked with 24.0 MHz, which results
  * 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 };
-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.
@@ -51,6 +76,28 @@ static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = {
        { "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_
 
 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)
        serial_out(up, UART_ICR, value);
 }
 
+#if 0 /* Unused currently */
 static unsigned int serial_icr_read(struct uart_sunsu_port *up, int offset)
 {
        unsigned int value;
@@ -132,6 +180,7 @@ static unsigned int serial_icr_read(struct uart_sunsu_port *up, int offset)
 
        return value;
 }
+#endif
 
 #ifdef CONFIG_SERIAL_8250_RSA
 /*
@@ -257,7 +306,7 @@ static void sunsu_enable_ms(struct uart_port *port)
 }
 
 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;
        unsigned char ch;
@@ -283,7 +332,7 @@ receive_chars(struct uart_sunsu_port *up, int *status, struct pt_regs *regs)
                        if (*status & UART_LSR_BI) {
                                *status &= ~(UART_LSR_FE | UART_LSR_PE);
                                up->port.icount.brk++;
-                               if (SU_IS_CONS(up))
+                               if (up->port.line == up->port.cons->index)
                                        saw_console_brk = 1;
                                /*
                                 * 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)
        do {
                status = serial_inp(up, UART_LSR);
                if (status & UART_LSR_DR)
-                       receive_serial_chars(up, &status, regs);
+                       receive_chars(up, &status, regs);
                check_modem_status(up);
                if (status & UART_LSR_THRE)
                        transmit_chars(up);
@@ -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)
 {
-       unsigned int cur_cflag = up->port.cflag;
+       unsigned int cur_cflag = up->cflag;
        int quot, new_baud;
 
-       up->port.cflag &= ~CBAUD;
-       up->port.cflag |= suncore_mouse_baud_cflag_next(cur_cflag, &new_baud);
+       up->cflag &= ~CBAUD;
+       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);
 
-       sunsu_change_speed(up, up->port.cflag, 0, quot);
+       sunsu_change_speed(&up->port, up->cflag, 0, quot);
 
        spin_lock(&up->port.lock);
 }
@@ -447,7 +496,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg
        do {
                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) {
                                up->kbd_id = 1;
                                up->l1_down = 0;
@@ -470,7 +519,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg
 #ifdef CONFIG_SERIO
                        serio_interrupt(&up->serio, ch, 0);
 #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);
 
                        switch (ret) {
@@ -629,6 +678,18 @@ static int sunsu_startup(struct uart_port *port)
                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
         */
@@ -831,6 +892,9 @@ sunsu_change_speed(struct uart_port *port, unsigned int cflag,
                }
                serial_outp(up, UART_FCR, fcr);         /* set fcr */
        }
+
+       up->cflag = cflag;
+
        spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
@@ -875,7 +939,6 @@ static struct uart_ops sunsu_pops = {
        .startup        = sunsu_startup,
        .shutdown       = sunsu_shutdown,
        .change_speed   = sunsu_change_speed,
-       .pm             = sunsu_pm,
        .type           = sunsu_type,
        .release_port   = sunsu_release_port,
        .request_port   = sunsu_request_port,
@@ -891,7 +954,7 @@ static struct uart_sunsu_port sunsu_ports[UART_NR];
 
 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;
        unsigned long flags;
@@ -904,9 +967,11 @@ static void sunsu_serio_write(struct serio *serio, unsigned char ch)
        } while (!(lsr & UART_LSR_THRE));
 
        /* Send the character out. */
-       sunsu_writeb(up, UART_TX, c);
+       serial_out(up, UART_TX, ch);
 
        spin_unlock_irqrestore(&sunsu_serio_lock, flags);
+
+       return 0;
 }
 
 static int sunsu_serio_open(struct serio *serio)
@@ -951,7 +1016,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up)
 #endif
        unsigned long flags;
 
-       if (!up->port_node || !up->port_type)
+       if (!up->port_node || !up->su_type)
                return;
 
        /*
@@ -1118,7 +1183,7 @@ ebus_done:
                }
                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) {
                scratch = serial_in(up, UART_SCR);
                serial_outp(up, UART_SCR, 0xa5);
@@ -1131,13 +1196,11 @@ ebus_done:
                        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)
                goto out;
 
-       sprintf(up->name, "su(%s)", su_typev[up->port_type]);
-
        /*
         * Reset the UART.
         */
@@ -1168,59 +1231,7 @@ static struct uart_driver sunsu_reg = {
        .major                  = TTY_MAJOR,
 };
 
-static int __init sunsu_serial_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)
+static int __init sunsu_kbd_ms_init(void)
 {
        struct uart_sunsu_port *up;
        int i;
@@ -1228,12 +1239,12 @@ static int __init su_kbd_ms_init(void)
        for (i = 0, up = sunsu_ports; i < 2; i++, up++) {
                up->port.line = i;
                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)
-                       up->port.cflag = B1200 | CS8 | CLOCAL | CREAD;
+               if (up->su_type == SU_PORT_KBD)
+                       up->cflag = B1200 | CS8 | CLOCAL | CREAD;
                else
-                       up->port.cflag = B4800 | CS8 | CLOCAL | CREAD;
+                       up->cflag = B4800 | CS8 | CLOCAL | CREAD;
 
                sunsu_autoconfig(up);
                if (up->port.type == PORT_UNKNOWN)
@@ -1250,14 +1261,14 @@ static int __init su_kbd_ms_init(void)
                up->serio.driver = up;
 
                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.name = "sukbd";
                } else {
                        up->serio.type |= SERIO_SUN;
                        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.open = sunsu_serio_open;
@@ -1266,7 +1277,7 @@ static int __init su_kbd_ms_init(void)
                serio_register_port(&up->serio);
 #endif
 
-               sunsu_startup(up);
+               sunsu_startup(&up->port);
        }
        return 0;
 }
@@ -1409,13 +1420,67 @@ static int __init sunsu_serial_console_init(void)
                return 0;
 
        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;
        sunsu_cons.index = index;
        register_console(&sunsu_cons);
        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)
 {
        if (strncmp(name, "su", namelen) == 0 ||
@@ -1461,7 +1526,7 @@ struct su_probe_scan {
  */
 static void __init su_probe_any(struct su_probe_scan *t, int sunode)
 {
-       struct su_struct *info;
+       struct uart_sunsu_port *up;
        int len;
 
        if (t->devices >= UART_NR)
@@ -1473,13 +1538,13 @@ static void __init su_probe_any(struct su_probe_scan *t, int sunode)
                        continue;               /* Broken PROM node */
 
                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) {
                                t->kbx = t->devices;
-                               info->port_type = SU_PORT_KBD;
+                               up->su_type = SU_PORT_KBD;
                        } else if (t->msnode != 0 && sunode == t->msnode) {
                                t->msx = t->devices;
-                               info->port_type = SU_PORT_MS;
+                               up->su_type = SU_PORT_MS;
                        } else {
 #ifdef CONFIG_SPARC64
                                /*
@@ -1492,10 +1557,9 @@ static void __init su_probe_any(struct su_probe_scan *t, int sunode)
                                if (prom_getbool(sunode, "keyboard"))
                                        continue;
 #endif
-                               info->port_type = SU_PORT_PORT;
+                               up->su_type = SU_PORT_PORT;
                        }
-                       info->is_console = 0;
-                       info->port_node = sunode;
+                       up->port_node = sunode;
                        ++t->devices;
                } else {
                        su_probe_any(t, prom_getchild(sunode));
@@ -1547,9 +1611,9 @@ static int __init sunsu_probe(void)
         * Thus, we ignore values of .msx and .kbx, then compact ports.
         */
        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[1].port_type = SU_PORT_KBD;
+               sunsu_ports[1].su_type = SU_PORT_KBD;
                sunsu_ports[1].port_node = scan.kbnode;
 
                sunsu_kbd_ms_init();
@@ -1584,13 +1648,13 @@ static void __exit sunsu_exit(void)
        for (i = 0; i < UART_NR; i++) {
                struct uart_sunsu_port *up = &sunsu_ports[i];
 
-               if (up->port_type == SU_PORT_MS ||
-                   up->port_type == SU_PORT_KBD) {
+               if (up->su_type == SU_PORT_MS ||
+                   up->su_type == SU_PORT_KBD) {
 #ifdef CONFIG_SERIO
                        serio_unregister_port(&up->serio);
 #endif
                } else if (up->port.type != PORT_UNKNOWN) {
-                       uart_remove_one_port(&sunsu_reg, up);
+                       uart_remove_one_port(&sunsu_reg, &up->port);
                        saw_uart++;
                }
        }
index 31917b5d775e1eb0f131917f1d4760e4e7096da5..19133aaea388b1f076ed0805cabf00778a97a2ae 100644 (file)
@@ -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,
-                                        unsigned char ch, int is_break)
+                                        unsigned char ch, int is_break,
+                                        struct pt_regs *regs)
 {
        if (ZS_IS_KEYB(up)) {
                if (ch == SUNKBD_RESET) {
@@ -304,6 +305,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
                        up->kbd_id = 0;
                        return;
                }
+               kbd_pt_regs = regs;
 #ifdef CONFIG_SERIO
                serio_interrupt(&up->serio, ch, 0);
 #endif
@@ -363,7 +365,7 @@ static void sunzilog_receive_chars(struct uart_sunzilog_port *up,
                ch &= up->parity_mask;
 
                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;
                }
 
@@ -440,7 +442,8 @@ static void sunzilog_receive_chars(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;
 
@@ -452,7 +455,7 @@ static void sunzilog_status_handle(struct uart_sunzilog_port *up,
        ZS_WSYNC(channel);
 
        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 (status & SYNC)
@@ -558,7 +561,7 @@ static void sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        if (r3 & CHARxIP)
                                sunzilog_receive_chars(up, channel, regs);
                        if (r3 & CHAEXT)
-                               sunzilog_status_handle(up, channel);
+                               sunzilog_status_handle(up, channel, regs);
                        if (r3 & CHATxIP)
                                sunzilog_transmit_chars(up, channel);
                }
@@ -577,7 +580,7 @@ static void sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        if (r3 & CHBRxIP)
                                sunzilog_receive_chars(up, channel, regs);
                        if (r3 & CHBEXT)
-                               sunzilog_status_handle(up, channel);
+                               sunzilog_status_handle(up, channel, regs);
                        if (r3 & CHBTxIP)
                                sunzilog_transmit_chars(up, channel);
                }