patch-2.4.0-test12 linux/arch/parisc/kernel/pdc_cons.c
Next file: linux/arch/parisc/kernel/process.c
Previous file: linux/arch/parisc/kernel/pdc.c
Back to the patch index
Back to the overall index
- Lines: 180
- Date:
Tue Dec 5 12:29:39 2000
- Orig file:
v2.4.0-test11/linux/arch/parisc/kernel/pdc_cons.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/pdc_cons.c linux/arch/parisc/kernel/pdc_cons.c
@@ -0,0 +1,179 @@
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <asm/page.h>
+#include <asm/types.h>
+#include <asm/system.h>
+#include <asm/pdc.h> /* for iodc_call() proto and friends */
+#include <asm/real.h>
+
+static int __attribute__((aligned(8))) iodc_retbuf[32];
+static char __attribute__((aligned(64))) iodc_dbuf[4096];
+
+/*
+ * pdc_putc:
+ * Console character print using IODC.
+ *
+ * Note that only these special chars are architected for console IODC io:
+ * BEL, BS, CR, and LF. Others are passed through.
+ * Since the HP console requires CR+LF to perform a 'newline', we translate
+ * "\n" to "\r\n".
+ */
+
+static int posx; /* for simple TAB-Simulation... */
+
+/* XXX Should we spinlock posx usage */
+
+void pdc_putc(unsigned char c)
+{
+ unsigned int n;
+ unsigned long flags;
+
+ switch (c) {
+ case '\n':
+ iodc_dbuf[0] = '\r';
+ iodc_dbuf[1] = '\n';
+ n = 2;
+ posx = 0;
+ break;
+ case '\t':
+ pdc_putc(' ');
+ while (posx & 7) /* expand TAB */
+ pdc_putc(' ');
+ return; /* return since IODC can't handle this */
+ case '\b':
+ posx-=2; /* BS */
+ default:
+ iodc_dbuf[0] = c;
+ n = 1;
+ posx++;
+ break;
+ }
+ {
+ real32_call(PAGE0->mem_cons.iodc_io,
+ (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
+ PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers),
+ __pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0);
+ }
+}
+
+static void pdc_console_write(struct console *co, const char *s, unsigned count)
+{
+ while(count--)
+ pdc_putc(*s++);
+}
+
+int pdc_console_wait_key(struct console *co)
+{
+ int ch = 'X';
+ int status;
+
+ /* Bail if no console input device. */
+ if (!PAGE0->mem_kbd.iodc_io)
+ return 0;
+
+ /* wait for a keyboard (rs232)-input */
+ do {
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ status = real32_call(PAGE0->mem_kbd.iodc_io,
+ (unsigned long)PAGE0->mem_kbd.hpa, ENTRY_IO_CIN,
+ PAGE0->mem_kbd.spa, __pa(PAGE0->mem_kbd.dp.layers),
+ __pa(iodc_retbuf), 0, __pa(iodc_dbuf), 1, 0);
+ restore_flags(flags);
+ ch = *iodc_dbuf; /* save the character directly to ch */
+ } while (*iodc_retbuf == 0); /* wait for a key */
+ return ch;
+}
+
+int pdc_getc(void)
+{
+ return pdc_console_wait_key(NULL);
+}
+
+static int pdc_console_setup(struct console *co, char *options)
+{
+ return 0;
+}
+
+static struct console pdc_cons = {
+ name: "ttyB",
+ write: pdc_console_write,
+ read: NULL,
+ device: NULL,
+ wait_key: pdc_console_wait_key,
+ unblank: NULL,
+ setup: pdc_console_setup,
+ flags: CON_PRINTBUFFER|CON_ENABLED, // |CON_CONSDEV,
+ index: -1,
+};
+
+static int pdc_console_initialized;
+
+void pdc_console_init(void)
+{
+ if (pdc_console_initialized)
+ return;
+ ++pdc_console_initialized;
+
+ /* If the console is duplex then copy the COUT parameters to CIN. */
+ if (PAGE0->mem_cons.cl_class == CL_DUPLEX)
+ memcpy(&PAGE0->mem_kbd, &PAGE0->mem_cons, sizeof(PAGE0->mem_cons));
+
+ pdc_console_write(0, "PDC Console Initialized\n", 24);
+ /* register the pdc console */
+ register_console(&pdc_cons);
+}
+
+
+/* Unregister the pdc console with the printk console layer */
+void pdc_console_die(void)
+{
+ printk("Switching from PDC console\n");
+ if (!pdc_console_initialized)
+ return;
+ --pdc_console_initialized;
+
+#ifdef CONFIG_VT_CONSOLE
+ {
+ /* fixme (needed?): Wait for console-tasklet to finish !*/
+ extern struct tasklet_struct console_tasklet;
+ tasklet_schedule(&console_tasklet);
+ }
+#endif
+
+ unregister_console(&pdc_cons);
+}
+
+
+/*
+ * Used for emergencies. Currently only used if an HPMC occurs. If an
+ * HPMC occurs, it is possible that the current console may not be
+ * properly initialed after the PDC IO reset. This routine unregisters all
+ * of the current consoles, reinitializes the pdc console and
+ * registers it.
+ */
+
+void pdc_console_restart(void)
+{
+ struct console *console;
+ extern int log_size;
+
+ if (pdc_console_initialized)
+ return;
+
+ while ((console = console_drivers) != (struct console *)0)
+ unregister_console(console_drivers);
+
+ log_size = 0;
+ pdc_console_init();
+ printk("Switched to PDC console\n");
+ return;
+}
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)