patch-2.1.79 linux/drivers/sbus/char/sunserial.c
Next file: linux/drivers/sbus/char/sunserial.h
Previous file: linux/drivers/sbus/char/sunmouse.c
Back to the patch index
Back to the overall index
- Lines: 404
- Date:
Mon Jan 12 15:15:45 1998
- Orig file:
v2.1.78/linux/drivers/sbus/char/sunserial.c
- Orig date:
Thu Sep 4 17:07:31 1997
diff -u --recursive --new-file v2.1.78/linux/drivers/sbus/char/sunserial.c linux/drivers/sbus/char/sunserial.c
@@ -1,4 +1,4 @@
-/* $Id: sunserial.c,v 1.50 1997/09/03 11:54:59 ecd Exp $
+/* $Id: sunserial.c,v 1.56 1997/12/19 07:33:07 ecd Exp $
* serial.c: Serial port driver infrastructure for the Sparc.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -9,17 +9,19 @@
#include <linux/errno.h>
#include <linux/tty.h>
#include <linux/serial.h>
+#include <linux/string.h>
+#include <linux/kbd_diacr.h>
+#include <linux/version.h>
+#include <linux/init.h>
#include <asm/oplib.h>
#include "sunserial.h"
-static void nop_rs_cons_hook(int chip, int out, int line)
-{
- printk("Oops: %s called\n", __FUNCTION__);
-}
+int serial_console;
-static void nop_rs_kgdb_hook(int channel)
+__initfunc(static void
+nop_rs_kgdb_hook(int channel))
{
printk("Oops: %s called\n", __FUNCTION__);
}
@@ -36,10 +38,8 @@
return 0;
}
-
struct sunserial_operations rs_ops = {
0,
- nop_rs_cons_hook,
nop_rs_kgdb_hook,
nop_rs_change_mouse_baud,
nop_rs_read_proc
@@ -47,25 +47,41 @@
int rs_init(void)
{
- struct rs_initfunc *init;
+ struct initfunc *init;
int err = -ENODEV;
init = rs_ops.rs_init;
while (init) {
- err = init->rs_init();
+ err = init->init();
init = init->next;
}
return err;
}
-void rs_cons_hook(int chip, int out, int line)
+__initfunc(void
+rs_kgdb_hook(int channel))
{
- rs_ops.rs_cons_hook(chip, out, line);
+ rs_ops.rs_kgdb_hook(channel);
}
-void rs_kgdb_hook(int channel)
+__initfunc(static void sun_serial_finish_init(void))
{
- rs_ops.rs_kgdb_hook(channel);
+ extern unsigned char *linux_serial_image;
+ extern int con_is_present(void);
+ char buffer[2048];
+
+ if (con_is_present())
+ return;
+
+ sprintf (buffer, linux_serial_image, UTS_RELEASE);
+ printk(buffer);
+}
+
+__initfunc(long
+serial_console_init(long kmem_start, long kmem_end))
+{
+ sun_serial_finish_init();
+ return kmem_start;
}
void rs_change_mouse_baud(int baud)
@@ -88,45 +104,299 @@
{
}
+
+static void nop_compute_shiftstate (void)
+{
+ printk("Oops: %s called\n", __FUNCTION__);
+}
+
+static void nop_setledstate (struct kbd_struct *kbd, unsigned int ledstate)
+{
+ printk("Oops: %s called\n", __FUNCTION__);
+}
+
+static unsigned char nop_getledstate (void)
+{
+ printk("Oops: %s called\n", __FUNCTION__);
+ return 0;
+}
+
+static int nop_setkeycode (unsigned int scancode, unsigned int keycode)
+{
+ printk("Oops: %s called\n", __FUNCTION__);
+ return -EINVAL;
+}
+
+static int nop_getkeycode (unsigned int scancode)
+{
+ printk("Oops: %s called\n", __FUNCTION__);
+ return -EINVAL;
+}
+
+struct sunkbd_operations kbd_ops = {
+ 0,
+ nop_compute_shiftstate,
+ nop_setledstate,
+ nop_getledstate,
+ nop_setkeycode,
+ nop_getkeycode
+};
+
+int kbd_init(void)
+{
+ struct initfunc *init;
+ int err = -ENODEV;
+
+ init = kbd_ops.kbd_init;
+ while (init) {
+ err = init->init();
+ init = init->next;
+ }
+ return err;
+}
+
+void compute_shiftstate (void)
+{
+ kbd_ops.compute_shiftstate();
+}
+
+void setledstate (struct kbd_struct *kbd, unsigned int ledstate)
+{
+ kbd_ops.setledstate(kbd, ledstate);
+}
+
+unsigned char getledstate (void)
+{
+ return kbd_ops.getledstate();
+}
+
+int setkeycode (unsigned int scancode, unsigned int keycode)
+{
+ return kbd_ops.setkeycode(scancode, keycode);
+}
+
+int getkeycode (unsigned int scancode)
+{
+ return kbd_ops.getkeycode(scancode);
+}
+
+
void
sunserial_setinitfunc(unsigned long *memory_start, int (*init) (void))
{
- struct rs_initfunc *rs_init;
+ struct initfunc *rs_init;
*memory_start = (*memory_start + 7) & ~(7);
- rs_init = (struct rs_initfunc *) *memory_start;
- *memory_start += sizeof(struct rs_initfunc);
+ rs_init = (struct initfunc *) *memory_start;
+ *memory_start += sizeof(struct initfunc);
- rs_init->rs_init = init;
+ rs_init->init = init;
rs_init->next = rs_ops.rs_init;
rs_ops.rs_init = rs_init;
}
+void
+sunserial_console_termios(struct console *con)
+{
+ char mode[16], buf[16], *s;
+ char *mode_prop = "ttyX-mode";
+ char *cd_prop = "ttyX-ignore-cd";
+ char *dtr_prop = "ttyX-rts-dtr-off";
+ int baud, bits, stop, cflag;
+ char parity;
+ int carrier = 0;
+ int rtsdtr = 1;
+ int topnd, nd;
+
+ if (!serial_console)
+ return;
+
+ if (serial_console == 1) {
+ mode_prop[3] = 'a';
+ cd_prop[3] = 'a';
+ dtr_prop[3] = 'a';
+ } else {
+ mode_prop[3] = 'b';
+ cd_prop[3] = 'b';
+ dtr_prop[3] = 'b';
+ }
+
+ topnd = prom_getchild(prom_root_node);
+ nd = prom_searchsiblings(topnd, "options");
+ if (!nd) {
+ strcpy(mode, "9600,8,n,1,-");
+ goto no_options;
+ }
+
+ if (!prom_node_has_property(nd, mode_prop)) {
+ strcpy(mode, "9600,8,n,1,-");
+ goto no_options;
+ }
+
+ memset(mode, 0, sizeof(mode));
+ prom_getstring(nd, mode_prop, mode, sizeof(mode));
+
+ if (prom_node_has_property(nd, cd_prop)) {
+ memset(buf, 0, sizeof(buf));
+ prom_getstring(nd, cd_prop, buf, sizeof(buf));
+ if (!strcmp(buf, "false"))
+ carrier = 1;
+
+ /* XXX: this is unused below. */
+ }
+
+ if (prom_node_has_property(nd, cd_prop)) {
+ memset(buf, 0, sizeof(buf));
+ prom_getstring(nd, cd_prop, buf, sizeof(buf));
+ if (!strcmp(buf, "false"))
+ rtsdtr = 0;
+
+ /* XXX: this is unused below. */
+ }
+
+no_options:
+ cflag = CREAD | HUPCL | CLOCAL;
+
+ s = mode;
+ baud = simple_strtoul(s, 0, 0);
+ s = strchr(s, ',');
+ bits = simple_strtoul(++s, 0, 0);
+ s = strchr(s, ',');
+ parity = *(++s);
+ s = strchr(s, ',');
+ stop = simple_strtoul(++s, 0, 0);
+ s = strchr(s, ',');
+ /* XXX handshake is not handled here. */
+
+ switch (baud) {
+ case 150: cflag |= B150; break;
+ case 300: cflag |= B300; break;
+ case 600: cflag |= B600; break;
+ case 1200: cflag |= B1200; break;
+ case 2400: cflag |= B2400; break;
+ case 4800: cflag |= B4800; break;
+ case 9600: cflag |= B9600; break;
+ case 19200: cflag |= B19200; break;
+ case 38400: cflag |= B38400; break;
+ default: cflag |= B9600; break;
+ }
+
+ switch (bits) {
+ case 5: cflag |= CS5; break;
+ case 6: cflag |= CS6; break;
+ case 7: cflag |= CS7; break;
+ case 8: cflag |= CS8; break;
+ default: cflag |= CS8; break;
+ }
+
+ switch (parity) {
+ case 'o': cflag |= (PARENB | PARODD); break;
+ case 'e': cflag |= PARENB; break;
+ case 'n': default: break;
+ }
+
+ switch (stop) {
+ case 2: cflag |= CSTOPB; break;
+ case 1: default: break;
+ }
+
+ con->cflag = cflag;
+}
+
+void
+sunkbd_setinitfunc(unsigned long *memory_start, int (*init) (void))
+{
+ struct initfunc *kbd_init;
+
+ *memory_start = (*memory_start + 7) & ~(7);
+ kbd_init = (struct initfunc *) *memory_start;
+ *memory_start += sizeof(struct initfunc);
+
+ kbd_init->init = init;
+ kbd_init->next = kbd_ops.kbd_init;
+ kbd_ops.kbd_init = kbd_init;
+}
+
+#ifdef CONFIG_PCI
+void
+sunkbd_install_keymaps(unsigned long *memory_start,
+ ushort **src_key_maps, unsigned int src_keymap_count,
+ char *src_func_buf, char **src_func_table,
+ int src_funcbufsize, int src_funcbufleft,
+ struct kbdiacr *src_accent_table,
+ unsigned int src_accent_table_size)
+{
+ extern unsigned int keymap_count;
+ int i, j;
+
+ for (i = 0; i < MAX_NR_KEYMAPS; i++) {
+ if (src_key_maps[i]) {
+ if (!key_maps[i]) {
+ key_maps[i] = (ushort *)*memory_start;
+ *memory_start += NR_KEYS * sizeof(ushort);
+ }
+ for (j = 0; j < NR_KEYS; j++)
+ key_maps[i][j] = src_key_maps[i][j];
+ }
+ key_maps[i] = src_key_maps[i];
+ }
+ keymap_count = src_keymap_count;
+
+ for (i = 0; i < MAX_NR_FUNC; i++)
+ func_table[i] = src_func_table[i];
+ funcbufptr = src_func_buf;
+ funcbufsize = src_funcbufsize;
+ funcbufleft = src_funcbufleft;
+
+ for (i = 0; i < MAX_DIACR; i++)
+ accent_table[i] = src_accent_table[i];
+ accent_table_size = src_accent_table_size;
+}
+#endif
+
extern int zs_probe(unsigned long *);
#ifdef CONFIG_SAB82532
extern int sab82532_probe(unsigned long *);
#endif
-#ifdef __sparc_v9__
+#ifdef CONFIG_PCI
extern int ps2kbd_probe(unsigned long *);
extern int su_probe(unsigned long *);
#endif
-unsigned long
-sun_serial_setup(unsigned long memory_start)
+__initfunc(unsigned long
+sun_serial_setup(unsigned long memory_start))
{
+ int ret = -ENODEV;
+
/* Probe for controllers. */
- if (zs_probe(&memory_start) == 0)
+ ret = zs_probe(&memory_start);
+ if (!ret)
return memory_start;
#ifdef CONFIG_SAB82532
- sab82532_probe(&memory_start);
+ ret = sab82532_probe(&memory_start);
#endif
-#ifdef __sparc_v9__
- if (ps2kbd_probe(&memory_start) == 0)
- return memory_start;
- if (su_probe(&memory_start) == 0)
- return memory_start;
+#ifdef CONFIG_PCI
+ /*
+ * Keyboard serial devices.
+ *
+ * Well done, Sun, prom_devopen("/pci@1f,4000/ebus@1/su@14,3083f8")
+ * hangs the machine if no keyboard is connected to the device...
+ * All PCI PROMs seem to do this, I have seen this on the Ultra 450
+ * with version 3.5 PROM, and on the Ultra/AX with 3.1.5 PROM.
+ *
+ * So be very careful not to probe for keyboards if we are on a
+ * serial console.
+ */
+ if (!serial_console) {
+ if (ps2kbd_probe(&memory_start) == 0)
+ return memory_start;
+ if (su_probe(&memory_start) == 0)
+ return memory_start;
+ }
#endif
+ if (!ret)
+ return memory_start;
prom_printf("No serial devices found, bailing out.\n");
prom_halt();
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov