ia64/xen-unstable

view xen/drivers/char/console.c @ 1776:c2f673cea5e4

bitkeeper revision 1.1072.1.1 (40f4e51fLMgcKX4Sn6FNYePX6EqkGA)

Merge http://xen.bkbits.net:8080/xeno-unstable.bk
into gandalf.hpl.hp.com:/var/bk/xeno-unstable.bk
author xenbk@gandalf.hpl.hp.com
date Wed Jul 14 07:47:43 2004 +0000 (2004-07-14)
parents da46c0d041f1 a37ede4b5d41
children e91945007886
line source
1 /******************************************************************************
2 * console.c
3 *
4 * Emergency console I/O for Xen and the domain-0 guest OS.
5 *
6 * Copyright (c) 2002-2004, K A Fraser.
7 */
9 #include <stdarg.h>
10 #include <xen/config.h>
11 #include <xen/lib.h>
12 #include <xen/errno.h>
13 #include <xen/event.h>
14 #include <xen/spinlock.h>
15 #include <xen/console.h>
16 #include <xen/serial.h>
17 #include <xen/keyhandler.h>
18 #include <asm/uaccess.h>
20 extern unsigned char opt_console[], opt_conswitch[];
22 static int xpos, ypos;
23 static unsigned char *video = __va(0xB8000);
25 #define CONSOLE_RING_SIZE 16392
26 typedef struct console_ring_st
27 {
28 char buf[CONSOLE_RING_SIZE];
29 unsigned int len;
30 } console_ring_t;
31 static console_ring_t console_ring;
33 static char printk_prefix[16] = "";
35 static int sercon_handle = -1;
36 static int vgacon_enabled = 0;
38 spinlock_t console_lock = SPIN_LOCK_UNLOCKED;
41 /*
42 * *******************************************************
43 * *************** OUTPUT TO VGA CONSOLE *****************
44 * *******************************************************
45 */
47 /* VGA text (mode 3) definitions. */
48 #define COLUMNS 80
49 #define LINES 25
50 #define ATTRIBUTE 7
52 /* Clear the screen and initialize VIDEO, XPOS and YPOS. */
53 static void cls(void)
54 {
55 memset(video, 0, COLUMNS * LINES * 2);
56 xpos = ypos = 0;
57 outw(10+(1<<(5+8)), 0x3d4); /* cursor off */
58 }
60 static int detect_video(void *video_base)
61 {
62 volatile u16 *p = (volatile u16 *)video_base;
63 u16 saved1 = p[0], saved2 = p[1];
64 int video_found = 1;
66 p[0] = 0xAA55;
67 p[1] = 0x55AA;
68 if ( (p[0] != 0xAA55) || (p[1] != 0x55AA) )
69 video_found = 0;
71 p[0] = 0x55AA;
72 p[1] = 0xAA55;
73 if ( (p[0] != 0x55AA) || (p[1] != 0xAA55) )
74 video_found = 0;
76 p[0] = saved1;
77 p[1] = saved2;
79 return video_found;
80 }
82 static int detect_vga(void)
83 {
84 /*
85 * Look at a number of well-known locations. Even if video is not at
86 * 0xB8000 right now, it will appear there when we set up text mode 3.
87 *
88 * We assume if there is any sign of a video adaptor then it is at least
89 * VGA-compatible (surely noone runs CGA, EGA, .... these days?).
90 *
91 * These checks are basically to detect headless server boxes.
92 */
93 return (detect_video(__va(0xA0000)) ||
94 detect_video(__va(0xB0000)) ||
95 detect_video(__va(0xB8000)));
96 }
98 /* This is actually code from vgaHWRestore in an old version of XFree86 :-) */
99 static void init_vga(void)
100 {
101 /* The following VGA state was saved from a chip in text mode 3. */
102 static unsigned char regs[] = {
103 /* Sequencer registers */
104 0x03, 0x00, 0x03, 0x00, 0x02,
105 /* CRTC registers */
106 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 0x00, 0x4f, 0x20,
107 0x0e, 0x00, 0x00, 0x01, 0xe0, 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96,
108 0xb9, 0xa3, 0xff,
109 /* Graphic registers */
110 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff,
111 /* Attribute registers */
112 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3a,
113 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x0c, 0x00, 0x0f, 0x08, 0x00
114 };
116 int i, j = 0;
117 volatile unsigned char tmp;
119 if ( !vgacon_enabled )
120 return;
122 if ( !detect_vga() )
123 {
124 printk("No VGA adaptor detected!\n");
125 vgacon_enabled = 0;
126 return;
127 }
129 tmp = inb(0x3da);
130 outb(0x00, 0x3c0);
132 for ( i = 0; i < 5; i++ )
133 outw((regs[j++] << 8) | i, 0x3c4);
135 /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17]. */
136 outw(((regs[5+17] & 0x7F) << 8) | 17, 0x3d4);
138 for ( i = 0; i < 25; i++ )
139 outw((regs[j++] << 8) | i, 0x3d4);
141 for ( i = 0; i < 9; i++ )
142 outw((regs[j++] << 8) | i, 0x3ce);
144 for ( i = 0; i < 21; i++ )
145 {
146 tmp = inb(0x3da);
147 outb(i, 0x3c0);
148 outb(regs[j++], 0x3c0);
149 }
151 tmp = inb(0x3da);
152 outb(0x20, 0x3c0);
154 cls();
155 }
157 static void put_newline(void)
158 {
159 xpos = 0;
160 ypos++;
162 if (ypos >= LINES)
163 {
164 static char zeroarr[2*COLUMNS] = { 0 };
165 ypos = LINES-1;
166 memcpy((char*)video,
167 (char*)video + 2*COLUMNS, (LINES-1)*2*COLUMNS);
168 memcpy((char*)video + (LINES-1)*2*COLUMNS,
169 zeroarr, 2*COLUMNS);
170 }
171 }
173 static void putchar_console(int c)
174 {
175 if ( !vgacon_enabled )
176 return;
178 if ( c == '\n' )
179 {
180 put_newline();
181 }
182 else
183 {
184 video[(xpos + ypos * COLUMNS) * 2] = c & 0xFF;
185 video[(xpos + ypos * COLUMNS) * 2 + 1] = ATTRIBUTE;
186 if ( ++xpos >= COLUMNS )
187 put_newline();
188 }
189 }
192 /*
193 * ********************************************************
194 * *************** ACCESS TO CONSOLE RING *****************
195 * ********************************************************
196 */
198 static void putchar_console_ring(int c)
199 {
200 if ( console_ring.len < CONSOLE_RING_SIZE )
201 console_ring.buf[console_ring.len++] = (char)c;
202 }
204 long read_console_ring(unsigned long str, unsigned int count, unsigned cmd)
205 {
206 unsigned int len;
208 len = (console_ring.len < count) ? console_ring.len : count;
210 if ( copy_to_user((char *)str, console_ring.buf, len) )
211 return -EFAULT;
213 if ( cmd & CONSOLE_RING_CLEAR )
214 console_ring.len = 0;
216 return len;
217 }
220 /*
221 * *******************************************************
222 * *************** ACCESS TO SERIAL LINE *****************
223 * *******************************************************
224 */
226 /* Characters received over the serial line are buffered for domain 0. */
227 #define SERIAL_RX_SIZE 128
228 #define SERIAL_RX_MASK(_i) ((_i)&(SERIAL_RX_SIZE-1))
229 static char serial_rx_ring[SERIAL_RX_SIZE];
230 static unsigned int serial_rx_cons, serial_rx_prod;
232 /* CTRL-<switch_char> switches input direction between Xen and DOM0. */
233 #define SWITCH_CODE (opt_conswitch[0]-'a'+1)
234 static int xen_rx = 1; /* FALSE => serial input passed to domain 0. */
236 static void switch_serial_input(void)
237 {
238 static char *input_str[2] = { "DOM0", "Xen" };
239 xen_rx = !xen_rx;
240 if ( SWITCH_CODE != 0 )
241 printk("*** Serial input -> %s "
242 "(type 'CTRL-%c' three times to switch input to %s).\n",
243 input_str[xen_rx], opt_conswitch[0], input_str[!xen_rx]);
244 }
246 static void __serial_rx(unsigned char c, struct pt_regs *regs)
247 {
248 key_handler *handler;
249 struct domain *p;
251 if ( xen_rx )
252 {
253 if ( (handler = get_key_handler(c)) != NULL )
254 (*handler)(c, NULL, regs);
255 }
256 else if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
257 {
258 serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod)] = c;
259 if ( serial_rx_prod++ == serial_rx_cons )
260 {
261 p = find_domain_by_id(0); /* only DOM0 reads the serial buffer */
262 send_guest_virq(p, VIRQ_CONSOLE);
263 put_domain(p);
264 }
265 }
266 }
268 static void serial_rx(unsigned char c, struct pt_regs *regs)
269 {
270 static int switch_code_count = 0;
272 if ( (SWITCH_CODE != 0) && (c == SWITCH_CODE) )
273 {
274 /* We eat CTRL-<switch_char> in groups of 3 to switch console input. */
275 if ( ++switch_code_count == 3 )
276 {
277 switch_serial_input();
278 switch_code_count = 0;
279 }
280 }
281 else
282 {
283 switch_code_count = 0;
284 }
286 /* Finally process the just-received character. */
287 __serial_rx(c, regs);
288 }
290 long do_console_io(int cmd, int count, char *buffer)
291 {
292 char *kbuf;
293 long rc;
295 #ifdef NDEBUG
296 /* Only domain-0 may access the emergency console. */
297 if ( current->domain != 0 )
298 return -EPERM;
299 #endif
301 switch ( cmd )
302 {
303 case CONSOLEIO_write:
304 if ( count > (PAGE_SIZE-1) )
305 count = PAGE_SIZE-1;
306 if ( (kbuf = (char *)get_free_page()) == NULL )
307 return -ENOMEM;
308 kbuf[count] = '\0';
309 rc = count;
310 if ( copy_from_user(kbuf, buffer, count) )
311 rc = -EFAULT;
312 else
313 serial_puts(sercon_handle, kbuf);
314 free_page((unsigned long)kbuf);
315 break;
316 case CONSOLEIO_read:
317 rc = 0;
318 while ( (serial_rx_cons != serial_rx_prod) && (rc < count) )
319 {
320 if ( put_user(serial_rx_ring[SERIAL_RX_MASK(serial_rx_cons)],
321 &buffer[rc]) )
322 {
323 rc = -EFAULT;
324 break;
325 }
326 rc++;
327 serial_rx_cons++;
328 }
329 break;
330 default:
331 rc = -ENOSYS;
332 break;
333 }
335 return rc;
336 }
339 /*
340 * *****************************************************
341 * *************** GENERIC CONSOLE I/O *****************
342 * *****************************************************
343 */
345 static inline void __putstr(const char *str)
346 {
347 int c;
348 serial_puts(sercon_handle, str);
349 while ( (c = *str++) != '\0' )
350 {
351 putchar_console(c);
352 putchar_console_ring(c);
353 }
354 }
356 void printf(const char *fmt, ...)
357 {
358 static char buf[1024];
359 static int start_of_line = 1;
361 va_list args;
362 char *p, *q;
363 unsigned long flags;
365 spin_lock_irqsave(&console_lock, flags);
367 va_start(args, fmt);
368 (void)vsnprintf(buf, sizeof(buf), fmt, args);
369 va_end(args);
371 p = buf;
372 while ( (q = strchr(p, '\n')) != NULL )
373 {
374 *q = '\0';
375 if ( start_of_line )
376 __putstr(printk_prefix);
377 __putstr(p);
378 __putstr("\n");
379 start_of_line = 1;
380 p = q + 1;
381 }
383 if ( *p != '\0' )
384 {
385 if ( start_of_line )
386 __putstr(printk_prefix);
387 __putstr(p);
388 start_of_line = 0;
389 }
391 spin_unlock_irqrestore(&console_lock, flags);
392 }
394 void set_printk_prefix(const char *prefix)
395 {
396 strcpy(printk_prefix, prefix);
397 }
399 void init_console(void)
400 {
401 unsigned char *p;
403 /* Where should console output go? */
404 for ( p = opt_console; p != NULL; p = strchr(p, ',') )
405 {
406 if ( *p == ',' )
407 p++;
408 if ( strncmp(p, "com", 3) == 0 )
409 sercon_handle = parse_serial_handle(p);
410 else if ( strncmp(p, "vga", 3) == 0 )
411 vgacon_enabled = 1;
412 }
414 init_vga();
416 serial_set_rx_handler(sercon_handle, serial_rx);
417 }
419 void console_endboot(int disable_vga)
420 {
421 if ( disable_vga )
422 vgacon_enabled = 0;
424 /*
425 * If user specifies so, we fool the switch routine to redirect input
426 * straight back to Xen. I use this convoluted method so we still print
427 * a useful 'how to switch' message.
428 */
429 if ( opt_conswitch[1] == 'x' )
430 xen_rx = !xen_rx;
432 /* Serial input is directed to DOM0 by default. */
433 switch_serial_input();
434 }
437 /*
438 * **************************************************************
439 * *************** Debugging/tracing/error-report ***************
440 * **************************************************************
441 */
443 void panic(const char *fmt, ...)
444 {
445 va_list args;
446 char buf[128];
447 unsigned long flags;
448 extern void machine_restart(char *);
450 va_start(args, fmt);
451 (void)vsnprintf(buf, sizeof(buf), fmt, args);
452 va_end(args);
454 /* Spit out multiline message in one go. */
455 spin_lock_irqsave(&console_lock, flags);
456 __putstr("\n****************************************\n");
457 __putstr(buf);
458 __putstr("Aieee! CPU");
459 sprintf(buf, "%d", smp_processor_id());
460 __putstr(buf);
461 __putstr(" is toast...\n");
462 __putstr("****************************************\n\n");
463 __putstr("Reboot in five seconds...\n");
464 spin_unlock_irqrestore(&console_lock, flags);
466 mdelay(5000);
467 machine_restart(0);
468 }
471 void __out_of_line_bug(int line)
472 {
473 printk("kernel BUG in header file at line %d\n", line);
474 BUG();
475 for ( ; ; ) ;
476 }