1 /*
2 * linux/arch/parisc/kernel/pdc_console.c
3 *
4 * The PDC console is a simple console, which can be used for debugging
5 * boot related problems on HP PA-RISC machines.
6 *
7 * This code uses the ROM (=PDC) based functions to read and write characters
8 * from and to PDC's boot path.
9 * Since all character read from that path must be polled, this code never
10 * can or will be a fully functional linux console.
11 */
12
13 /* Define EARLY_BOOTUP_DEBUG to debug kernel related boot problems.
14 * On production kernels EARLY_BOOTUP_DEBUG should be undefined. */
15 #undef EARLY_BOOTUP_DEBUG
16
17
18 #include <linux/config.h>
19 #include <linux/kernel.h>
20 #include <linux/console.h>
21 #include <linux/string.h>
22 #include <linux/init.h>
23 #include <linux/delay.h>
24 #include <linux/sched.h>
25 #include <linux/interrupt.h>
26 #include <asm/page.h>
27 #include <asm/types.h>
28 #include <asm/system.h>
29 #include <asm/pdc.h> /* for iodc_call() proto and friends */
30
31
pdc_console_write(struct console * co,const char * s,unsigned count)32 static void pdc_console_write(struct console *co, const char *s, unsigned count)
33 {
34 while(count--)
35 pdc_iodc_putc(*s++);
36 }
37
pdc_outc(unsigned char c)38 void pdc_outc(unsigned char c)
39 {
40 pdc_iodc_outc(c);
41 }
42
43
pdc_console_poll_key(struct console * co)44 int pdc_console_poll_key(struct console *co)
45 {
46 return pdc_iodc_getc();
47 }
48
pdc_console_setup(struct console * co,char * options)49 static int pdc_console_setup(struct console *co, char *options)
50 {
51 return 0;
52 }
53
54 #if defined(CONFIG_PDC_CONSOLE) || defined(CONFIG_SERIAL_MUX)
55 #define PDC_CONSOLE_DEVICE pdc_console_device
pdc_console_device(struct console * c)56 static kdev_t pdc_console_device (struct console *c)
57 {
58 return MKDEV(MUX_MAJOR, 0);
59 }
60 #else
61 #define PDC_CONSOLE_DEVICE NULL
62 #endif
63
64 static struct console pdc_cons = {
65 name: "ttyB",
66 write: pdc_console_write,
67 #warning UPSTREAM 2.4.19 removed the next 4 lines but we did not
68 read: NULL,
69 device: PDC_CONSOLE_DEVICE,
70 unblank: NULL,
71 setup: pdc_console_setup,
72 flags: CON_BOOT|CON_PRINTBUFFER|CON_ENABLED,
73 index: -1,
74 };
75
76 static int pdc_console_initialized;
77 extern unsigned long con_start; /* kernel/printk.c */
78 extern unsigned long log_end; /* kernel/printk.c */
79
80
pdc_console_init_force(void)81 static void pdc_console_init_force(void)
82 {
83 if (pdc_console_initialized)
84 return;
85 ++pdc_console_initialized;
86
87 /* If the console is duplex then copy the COUT parameters to CIN. */
88 if (PAGE0->mem_cons.cl_class == CL_DUPLEX)
89 memcpy(&PAGE0->mem_kbd, &PAGE0->mem_cons, sizeof(PAGE0->mem_cons));
90
91 /* register the pdc console */
92 register_console(&pdc_cons);
93 }
94
pdc_console_init(void)95 void pdc_console_init(void)
96 {
97 #if defined(EARLY_BOOTUP_DEBUG) || defined(CONFIG_PDC_CONSOLE) || defined(CONFIG_SERIAL_MUX)
98 pdc_console_init_force();
99 #endif
100 #ifdef EARLY_BOOTUP_DEBUG
101 printk(KERN_INFO "Initialized PDC Console for debugging.\n");
102 #endif
103 }
104
105
106 /* Unregister the pdc console with the printk console layer */
pdc_console_die(void)107 void pdc_console_die(void)
108 {
109 if (!pdc_console_initialized)
110 return;
111 --pdc_console_initialized;
112
113 printk(KERN_INFO "Switching from PDC console\n");
114
115 /* Don't repeat what we've already printed */
116 con_start = log_end;
117
118 unregister_console(&pdc_cons);
119 }
120
121
122 /*
123 * Used for emergencies. Currently only used if an HPMC occurs. If an
124 * HPMC occurs, it is possible that the current console may not be
125 * properly initialed after the PDC IO reset. This routine unregisters all
126 * of the current consoles, reinitializes the pdc console and
127 * registers it.
128 */
129
pdc_console_restart(void)130 void pdc_console_restart(void)
131 {
132 struct console *console;
133
134 if (pdc_console_initialized)
135 return;
136
137 while ((console = console_drivers) != NULL)
138 unregister_console(console_drivers);
139
140 /* Don't repeat what we've already printed */
141 con_start = log_end;
142
143 /* force registering the pdc console */
144 pdc_console_init_force();
145 }
146
147