diff options
Diffstat (limited to 'qemu/roms/openbios/arch/amd64/console.c')
-rw-r--r-- | qemu/roms/openbios/arch/amd64/console.c | 417 |
1 files changed, 417 insertions, 0 deletions
diff --git a/qemu/roms/openbios/arch/amd64/console.c b/qemu/roms/openbios/arch/amd64/console.c new file mode 100644 index 000000000..71a22b681 --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/console.c @@ -0,0 +1,417 @@ +/* + * Copyright (C) 2003, 2004 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "openbios.h" + +#ifdef CONFIG_DEBUG_CONSOLE + +/* ****************************************************************** + * serial console functions + * ****************************************************************** */ + +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + +#define RBR(x) x==2?0x2f8:0x3f8 +#define THR(x) x==2?0x2f8:0x3f8 +#define IER(x) x==2?0x2f9:0x3f9 +#define IIR(x) x==2?0x2fa:0x3fa +#define LCR(x) x==2?0x2fb:0x3fb +#define MCR(x) x==2?0x2fc:0x3fc +#define LSR(x) x==2?0x2fd:0x3fd +#define MSR(x) x==2?0x2fe:0x3fe +#define SCR(x) x==2?0x2ff:0x3ff +#define DLL(x) x==2?0x2f8:0x3f8 +#define DLM(x) x==2?0x2f9:0x3f9 + +static int uart_charav(int port) +{ + if (!port) + return -1; + return ((inb(LSR(port)) & 1) != 0); +} + +static char uart_getchar(int port) +{ + if (!port) + return -1; + while (!uart_charav(port)); + return ((char) inb(RBR(port)) & 0177); +} + +static void uart_putchar(int port, unsigned char c) +{ + if (!port) + return; + if (c == '\n') + uart_putchar(port, '\r'); + while (!(inb(LSR(port)) & 0x20)); + outb(c, THR(port)); +} + +static void uart_init_line(int port, unsigned long baud) +{ + int i, baudconst; + + if (!port) + return; + + switch (baud) { + case 115200: + baudconst = 1; + break; + case 57600: + baudconst = 2; + break; + case 38400: + baudconst = 3; + break; + case 19200: + baudconst = 6; + break; + case 9600: + default: + baudconst = 12; + break; + } + + outb(0x87, LCR(port)); + outb(0x00, DLM(port)); + outb(baudconst, DLL(port)); + outb(0x07, LCR(port)); + outb(0x0f, MCR(port)); + + for (i = 10; i > 0; i--) { + if (inb(LSR(port)) == (unsigned int) 0) + break; + inb(RBR(port)); + } +} + +int uart_init(int port, unsigned long speed) +{ + if (port) + uart_init_line(port, speed); + return -1; +} + +static void serial_putchar(int c) +{ + uart_putchar(CONFIG_SERIAL_PORT, (unsigned char) (c & 0xff)); +} + +static void serial_cls(void) +{ + serial_putchar(27); + serial_putchar('['); + serial_putchar('H'); + serial_putchar(27); + serial_putchar('['); + serial_putchar('J'); +} + +#endif + +/* ****************************************************************** + * simple polling video/keyboard console functions + * ****************************************************************** */ + +#ifdef CONFIG_DEBUG_CONSOLE_VGA + +/* raw vga text mode */ +#define COLUMNS 80 /* The number of columns. */ +#define LINES 25 /* The number of lines. */ +#define ATTRIBUTE 7 /* The attribute of an character. */ + +#define VGA_BASE 0xB8000 /* The video memory address. */ + +/* VGA Index and Data Registers */ +#define VGA_REG_INDEX 0x03D4 /* VGA index register */ +#define VGA_REG_DATA 0x03D5 /* VGA data register */ + +#define VGA_IDX_CURMSL 0x09 /* cursor maximum scan line */ +#define VGA_IDX_CURSTART 0x0A /* cursor start */ +#define VGA_IDX_CUREND 0x0B /* cursor end */ +#define VGA_IDX_CURLO 0x0F /* cursor position (low 8 bits) */ +#define VGA_IDX_CURHI 0x0E /* cursor position (high 8 bits) */ + +/* Save the X and Y position. */ +static int xpos, ypos; +/* Point to the video memory. */ +static volatile unsigned char *video = (unsigned char *) VGA_BASE; + +static void video_initcursor(void) +{ + u8 val; + outb(VGA_IDX_CURMSL, VGA_REG_INDEX); + val = inb(VGA_REG_DATA) & 0x1f; /* maximum scan line -1 */ + + outb(VGA_IDX_CURSTART, VGA_REG_INDEX); + outb(0, VGA_REG_DATA); + + outb(VGA_IDX_CUREND, VGA_REG_INDEX); + outb(val, VGA_REG_DATA); +} + + + +static void video_poscursor(unsigned int x, unsigned int y) +{ + unsigned short pos; + + /* Calculate new cursor position as a function of x and y */ + pos = (y * COLUMNS) + x; + + /* Output the new position to VGA card */ + outb(VGA_IDX_CURLO, VGA_REG_INDEX); /* output low 8 bits */ + outb((u8) (pos), VGA_REG_DATA); + outb(VGA_IDX_CURHI, VGA_REG_INDEX); /* output high 8 bits */ + outb((u8) (pos >> 8), VGA_REG_DATA); + +}; + + +static void video_newline(void) +{ + xpos = 0; + + if (ypos < LINES - 1) { + ypos++; + } else { + int i; + memmove((void *) video, (void *) (video + 2 * COLUMNS), + (LINES - 1) * COLUMNS * 2); + + for (i = ((LINES - 1) * 2 * COLUMNS); + i < 2 * COLUMNS * LINES;) { + video[i++] = 0; + video[i++] = ATTRIBUTE; + } + } + +} + +/* Put the character C on the screen. */ +static void video_putchar(int c) +{ + int p=1; + + if (c == '\n' || c == '\r') { + video_newline(); + return; + } + + if (c == '\b') { + if (xpos) xpos--; + c=' '; + p=0; + } + + + if (xpos >= COLUMNS) + video_newline(); + + *(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF; + *(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE; + + if (p) + xpos++; + + video_poscursor(xpos, ypos); +} + +static void video_cls(void) +{ + int i; + + for (i = 0; i < 2 * COLUMNS * LINES;) { + video[i++] = 0; + video[i++] = ATTRIBUTE; + } + + + xpos = 0; + ypos = 0; + + video_initcursor(); + video_poscursor(xpos, ypos); +} + +void video_init(void) +{ + video=phys_to_virt((unsigned char*)VGA_BASE); +} + +/* + * keyboard driver + */ + +static char normal[] = { + 0x0, 0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', + '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', + 'p', '[', ']', 0xa, 0x0, 'a', 's', 'd', 'f', 'g', 'h', 'j', + 'k', 'l', ';', 0x27, 0x60, 0x0, 0x5c, 'z', 'x', 'c', 'v', 'b', + 'n', 'm', ',', '.', '/', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '0', 0x7f +}; + +static char shifted[] = { + 0x0, 0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', + '+', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', + 'P', '{', '}', 0xa, 0x0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', + 'K', 'L', ':', 0x22, '~', 0x0, '|', 'Z', 'X', 'C', 'V', 'B', + 'N', 'M', '<', '>', '?', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '7', '8', + '9', 0x0, '4', '5', '6', 0x0, '1', '2', '3', '0', 0x7f +}; + +static int key_ext; +static int key_lshift = 0, key_rshift = 0, key_caps = 0; + +static char last_key; + +static void keyboard_cmd(unsigned char cmd, unsigned char val) +{ + outb(cmd, 0x60); + /* wait until keyboard controller accepts cmds: */ + while (inb(0x64) & 2); + outb(val, 0x60); + while (inb(0x64) & 2); +} + +static char keyboard_poll(void) +{ + unsigned int c; + if (inb(0x64) & 1) { + c = inb(0x60); + switch (c) { + case 0xe0: + key_ext = 1; + return 0; + case 0x2a: + key_lshift = 1; + return 0; + case 0x36: + key_rshift = 1; + return 0; + case 0xaa: + key_lshift = 0; + return 0; + case 0xb6: + key_rshift = 0; + return 0; + case 0x3a: + if (key_caps) { + key_caps = 0; + keyboard_cmd(0xed, 0); + } else { + key_caps = 1; + keyboard_cmd(0xed, 4); /* set caps led */ + } + return 0; + } + + if (key_ext) { + // void printk(const char *format, ...); + printk("extended keycode: %x\n", c); + + key_ext = 0; + return 0; + } + + if (c & 0x80) /* unhandled key release */ + return 0; + + if (key_lshift || key_rshift) + return key_caps ? normal[c] : shifted[c]; + else + return key_caps ? shifted[c] : normal[c]; + } + return 0; +} + +static int keyboard_dataready(void) +{ + if (last_key) + return 1; + + last_key = keyboard_poll(); + + return (last_key != 0); +} + +static unsigned char keyboard_readdata(void) +{ + char tmp; + while (!keyboard_dataready()); + tmp = last_key; + last_key = 0; + return tmp; +} +#endif + + +/* ****************************************************************** + * common functions, implementing simple concurrent console + * ****************************************************************** */ + +int arch_putchar(int c) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + serial_putchar(c); +#endif +#ifdef CONFIG_DEBUG_CONSOLE_VGA + video_putchar(c); +#endif + return c; +} + +int arch_availchar(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + if (uart_charav(CONFIG_SERIAL_PORT)) + return 1; +#endif +#ifdef CONFIG_DEBUG_CONSOLE_VGA + if (keyboard_dataready()) + return 1; +#endif + return 0; +} + +int arch_getchar(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + if (uart_charav(CONFIG_SERIAL_PORT)) + return (uart_getchar(CONFIG_SERIAL_PORT)); +#endif +#ifdef CONFIG_DEBUG_CONSOLE_VGA + if (keyboard_dataready()) + return (keyboard_readdata()); +#endif + return 0; +} + +void cls(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + serial_cls(); +#endif +#ifdef CONFIG_DEBUG_CONSOLE_VGA + video_cls(); +#endif +} + +struct _console_ops arch_console_ops = { + .putchar = arch_putchar, + .availchar = arch_availchar, + .getchar = arch_getchar +}; + +#endif // CONFIG_DEBUG_CONSOLE |