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