1 /* 2 * PDC Console support - ie use firmware to dump text via boot console 3 * 4 * Copyright (C) 1999-2003 Matthew Wilcox <willy at parisc-linux.org> 5 * Copyright (C) 2000 Martin K Petersen <mkp at mkp.net> 6 * Copyright (C) 2000 John Marvin <jsm at parisc-linux.org> 7 * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org> 8 * Copyright (C) 2000 Philipp Rumpf <prumpf with tux.org> 9 * Copyright (C) 2000 Michael Ang <mang with subcarrier.org> 10 * Copyright (C) 2000 Grant Grundler <grundler with parisc-linux.org> 11 * Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org> 12 * Copyright (C) 2001 Helge Deller <deller at parisc-linux.org> 13 * Copyright (C) 2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org> 14 * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org> 15 * 16 * 17 * This program is free software; you can redistribute it and/or modify 18 * it under the terms of the GNU General Public License as published by 19 * the Free Software Foundation; either version 2 of the License, or 20 * (at your option) any later version. 21 * 22 * This program is distributed in the hope that it will be useful, 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 * GNU General Public License for more details. 26 * 27 * You should have received a copy of the GNU General Public License 28 * along with this program; if not, write to the Free Software 29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 30 */ 31 32 /* 33 * The PDC console is a simple console, which can be used for debugging 34 * boot related problems on HP PA-RISC machines. 35 * 36 * This code uses the ROM (=PDC) based functions to read and write characters 37 * from and to PDC's boot path. 38 * Since all character read from that path must be polled, this code never 39 * can or will be a fully functional linux console. 40 */ 41 42 /* Define EARLY_BOOTUP_DEBUG to debug kernel related boot problems. 43 * On production kernels EARLY_BOOTUP_DEBUG should be undefined. */ 44 #define EARLY_BOOTUP_DEBUG 45 46 47 #include <linux/kernel.h> 48 #include <linux/console.h> 49 #include <linux/string.h> 50 #include <linux/init.h> 51 #include <linux/major.h> 52 #include <linux/tty.h> 53 #include <asm/pdc.h> /* for iodc_call() proto and friends */ 54 55 static DEFINE_SPINLOCK(pdc_console_lock); 56 57 static void pdc_console_write(struct console *co, const char *s, unsigned count) 58 { 59 int i = 0; 60 unsigned long flags; 61 62 spin_lock_irqsave(&pdc_console_lock, flags); 63 do { 64 i += pdc_iodc_print(s + i, count - i); 65 } while (i < count); 66 spin_unlock_irqrestore(&pdc_console_lock, flags); 67 } 68 69 int pdc_console_poll_key(struct console *co) 70 { 71 int c; 72 unsigned long flags; 73 74 spin_lock_irqsave(&pdc_console_lock, flags); 75 c = pdc_iodc_getc(); 76 spin_unlock_irqrestore(&pdc_console_lock, flags); 77 78 return c; 79 } 80 81 static int pdc_console_setup(struct console *co, char *options) 82 { 83 return 0; 84 } 85 86 #if defined(CONFIG_PDC_CONSOLE) 87 #include <linux/vt_kern.h> 88 89 static struct tty_driver * pdc_console_device (struct console *c, int *index) 90 { 91 extern struct tty_driver console_driver; 92 *index = c->index ? c->index-1 : fg_console; 93 return &console_driver; 94 } 95 #else 96 #define pdc_console_device NULL 97 #endif 98 99 static struct console pdc_cons = { 100 .name = "ttyB", 101 .write = pdc_console_write, 102 .device = pdc_console_device, 103 .setup = pdc_console_setup, 104 .flags = CON_BOOT | CON_PRINTBUFFER | CON_ENABLED, 105 .index = -1, 106 }; 107 108 static int pdc_console_initialized; 109 110 static void pdc_console_init_force(void) 111 { 112 if (pdc_console_initialized) 113 return; 114 ++pdc_console_initialized; 115 116 /* If the console is duplex then copy the COUT parameters to CIN. */ 117 if (PAGE0->mem_cons.cl_class == CL_DUPLEX) 118 memcpy(&PAGE0->mem_kbd, &PAGE0->mem_cons, sizeof(PAGE0->mem_cons)); 119 120 /* register the pdc console */ 121 register_console(&pdc_cons); 122 } 123 124 void __init pdc_console_init(void) 125 { 126 #if defined(EARLY_BOOTUP_DEBUG) || defined(CONFIG_PDC_CONSOLE) 127 pdc_console_init_force(); 128 #endif 129 #ifdef EARLY_BOOTUP_DEBUG 130 printk(KERN_INFO "Initialized PDC Console for debugging.\n"); 131 #endif 132 } 133 134 135 /* 136 * Used for emergencies. Currently only used if an HPMC occurs. If an 137 * HPMC occurs, it is possible that the current console may not be 138 * properly initialised after the PDC IO reset. This routine unregisters 139 * all of the current consoles, reinitializes the pdc console and 140 * registers it. 141 */ 142 143 void pdc_console_restart(void) 144 { 145 struct console *console; 146 147 if (pdc_console_initialized) 148 return; 149 150 /* If we've already seen the output, don't bother to print it again */ 151 if (console_drivers != NULL) 152 pdc_cons.flags &= ~CON_PRINTBUFFER; 153 154 while ((console = console_drivers) != NULL) 155 unregister_console(console_drivers); 156 157 /* force registering the pdc console */ 158 pdc_console_init_force(); 159 } 160