📄 cons.c.virtual
字号:
#include <ctype.h>#include <errno.h>#include <event.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys.h>#include <sys/i8255.h>#include <sys/i8259.h>#include <sys/intr.h>#include <sys/ioctl.h>#include <sys/proc.h>#define CONSOLES 4#define LINES 25#define COLS 80#define SCREEN_BASE ((char *) 0xb8000)#define SCREEN_END ((char *) SCREEN_BASE + LINES * 2 * COLS)#define CONS (cons[console])#define CONS_BASE (CONS.buf)#define CONS_END (CONS.buf + LINES * 2 * COLS)#define CONS_CURSOR_X (((CONS.curs - CONS_BASE) / 2) / COLS)#define CONS_CURSOR_Y (((CONS.curs - CONS_BASE) / 2) % COLS)#define TAB_SPACES 8#define NORMAL 0x07#define BRIGHT 0x0f#define REVERSE 0x70#define BLINK 0x87#define CURSOR '_'#define SCAN_CODES 0x60#define SCAN_CODE_LSHFT 0x2a#define SCAN_CODE_RSHFT 0x36#define SCAN_CODE_LSREL 0xaa#define SCAN_CODE_RSREL 0xb6#define SCAN_CODE_LCTRL 0x1d#define SCAN_CODE_RCTRL 0x5a#define SCAN_CODE_LCREL 0x9d#define SCAN_CODE_RCREL 0xda#define SCAN_CODE_F1 0x3b#define SCAN_CODE_F2 0x3c#define SCAN_CODE_F3 0x3d#define SCAN_CODE_F4 0x3e#define NULL_CODE 255#define MAX_CODES 16struct console { proc_t proc; /* Process waiting for input */#define CONS_RAW 0x0001#define CONS_CURSOR_OFF 0x0002#define CONS_BRIGHT 0x0004#define CONS_REVERSE 0x0008#define CONS_BLINK 0x0010#define CONS_SHIFT 0x0020#define CONS_CTRL 0x0040 int flags;#if 0 char *buf; /* Screen buffer */#endif char buf[LINES * COLS * 2]; /* Screen buffer */ char *curs; /* Cursor location */ u_char codes[MAX_CODES]; /* Keyboard scan code queue */ int ch, ct; /* Scan code queue ptrs */};static struct console cons[CONSOLES];static int currcons = 0; /* Current console */static char *screencurs;static char asciishift[SCAN_CODES] = { '\0', ESC, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', '\0', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', '\0', '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '\0', '*', '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};static char asciinormal[SCAN_CODES] = { '\0', ESC, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', '\0', '*', '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};voidclear_screen(int cursor){ for (screencurs = SCREEN_BASE; screencurs < SCREEN_END; screencurs += 2) { *screencurs = ' '; *(screencurs + 1) = NORMAL; } screencurs = SCREEN_BASE; if (cursor) { *screencurs = CURSOR; *(screencurs + 1) = BLINK; }}static voidclear_console(int console){ /* Clear console buffer */ for (CONS.curs = CONS_BASE; CONS.curs < CONS_END; CONS.curs += 2) { *(CONS.curs) = ' '; *(CONS.curs + 1) = NORMAL; } CONS.curs = CONS_BASE;}static voidscroll_screen(int cursor){ char *i, *j; for (i = SCREEN_BASE, j = SCREEN_BASE + 2 * COLS; j < SCREEN_END; i += 2 * COLS, j += 2 * COLS) bcopy(j, i, 2 * COLS); while (i < SCREEN_END) { *(i + 1) = NORMAL; *i = ' '; i += 2; } screencurs = SCREEN_END - 2 * COLS; if (cursor) { *screencurs = CURSOR; *(screencurs + 1) = BLINK; }}static voidscroll_console(int console){ char *i, *j; /* Scroll console buffer */ for (i = CONS_BASE, j = CONS_BASE + 2 * COLS; j < CONS_END; i += 2 * COLS, j += 2 * COLS) bcopy(j, i, 2 * COLS); while (i < CONS_END) { *(i + 1) = NORMAL; *i = ' '; i += 2; } CONS.curs = CONS_END - 2 * COLS;}charconsole_attr(console){ char attr = NORMAL; if (CONS.flags & CONS_BRIGHT) attr = BRIGHT; if (CONS.flags & CONS_REVERSE) attr = REVERSE; if (CONS.flags & CONS_BLINK) attr = BLINK; return attr;}voidput_screen(char c, int cursor){ if (isprint(c)) { if (cursor) { *(screencurs + 1) = NORMAL; *screencurs = ' '; } *(screencurs + 1) = console_attr(currcons); *screencurs = c; screencurs += 2; if (screencurs >= SCREEN_END) scroll_screen(cursor); if (cursor) { *screencurs = CURSOR; *(screencurs + 1) = BLINK; } } else if (c == '\t') { int i; if (cursor) { *(screencurs + 1) = NORMAL; *screencurs = ' '; } for (i = 0; i < TAB_SPACES; i++) { *(screencurs + 1) = console_attr(currcons); *screencurs = ' '; screencurs += 2; if (screencurs >= SCREEN_END) scroll_screen(cursor); } if (cursor) { *screencurs = CURSOR; *(screencurs + 1) = BLINK; } } else if (c == '\n') { if (cursor) { *(screencurs + 1) = NORMAL; *screencurs = ' '; } if (screencurs < SCREEN_END - 2 * COLS) { char *i = SCREEN_BASE; while (i <= screencurs) i += 2 * COLS; screencurs = i; } else scroll_screen(cursor); if (cursor) { *screencurs = CURSOR; *(screencurs + 1) = BLINK; } } else if (c == '\b' && screencurs > SCREEN_BASE) { if (cursor) { *(screencurs + 1) = NORMAL; *screencurs = ' '; } screencurs -= 2; if (cursor) { *screencurs = CURSOR; *(screencurs + 1) = BLINK; } }}voidput(char c){ put_screen(c, 1);}static voidput_console(int console, char c){ disable; if (isprint(c)) { *(CONS.curs + 1) = console_attr(console); *(CONS.curs) = c; CONS.curs += 2; if (CONS.curs >= CONS_END) scroll_console(console); } else if (c == '\t') { int i; for (i = 0; i < TAB_SPACES; i++) { *(CONS.curs + 1) = console_attr(console); *(CONS.curs) = ' '; CONS.curs += 2; if (CONS.curs >= CONS_END) scroll_console(console); } } else if (c == '\n') { if (CONS.curs < CONS_END - 2 * COLS) { char *i = CONS_BASE; while (i <= CONS.curs) i += 2 * COLS; CONS.curs = i; } else scroll_console(console); } else if (c == '\b' && CONS.curs > CONS_BASE) CONS.curs -= 2; if (console == currcons) put_screen(c, (CONS.flags & CONS_CURSOR_OFF ? 0 : 1)); enable;}#define CONSOLE_SWITCH(CONSOLE) \ if (currcons != (CONSOLE)) { \ currcons = (CONSOLE); \ bcopy(cons[(CONSOLE)].buf, SCREEN_BASE, 2 * LINES * COLS); \ screencurs = \ cons[(CONSOLE)].curs - cons[(CONSOLE)].buf + SCREEN_BASE; \ if (!(cons[(CONSOLE)].flags & CONS_CURSOR_OFF)) { \ *screencurs = CURSOR; \ *(screencurs + 1) = BLINK; \ } \ }static voidkbd_isr(){ u_char code; disable; if ((code = inb(I8255_PORT_A)) == SCAN_CODE_F1) { CONSOLE_SWITCH(0); } else if (code == SCAN_CODE_F2) { CONSOLE_SWITCH(1); } else if (code == SCAN_CODE_F3) { CONSOLE_SWITCH(2); } else if (code == SCAN_CODE_F4) { CONSOLE_SWITCH(3); } else if ((cons[currcons].ct + 1) % MAX_CODES != cons[currcons].ch) { cons[currcons].codes[cons[currcons].ct] = code; cons[currcons].ct = (cons[currcons].ct + 1) % MAX_CODES; } enable; /* Issue keyboard eoi */ outb(I8259_MSTR_CTRL, I8259_EOI_KBD);}static charget_console(int console){ u_char code = NULL_CODE; char c = '\0'; if (console < 0) console = currcons; disable; if (CONS.proc != NULL) { enable; proc_exit(EFAIL); kprintf("get_console: system restart\n"); reboot(); /* System restart */ } CONS.proc = current; enable; while (c == '\0') { disable; if (CONS.ch == CONS.ct) { enable; event_wait(EVENT_KBD); continue; } code = CONS.codes[CONS.ch]; CONS.ch = (CONS.ch + 1) % MAX_CODES; enable; if (code == SCAN_CODE_LCTRL || code == SCAN_CODE_RCTRL) CONS.flags |= CONS_CTRL; else if (code == SCAN_CODE_LCREL || code == SCAN_CODE_RCREL) CONS.flags &= ~CONS_CTRL; else if (code == SCAN_CODE_LSHFT || code == SCAN_CODE_RSHFT) CONS.flags |= CONS_SHIFT; else if (code == SCAN_CODE_LSREL || code == SCAN_CODE_RSREL) CONS.flags &= ~CONS_SHIFT; else if (code > 0 && code < SCAN_CODES) { if (CONS.flags & CONS_CTRL) {#if 0 /* Ctrl-c generates a SIGKILL */ if (code == 0x2e) signal(CONS.t, SIGKILL);#endif } else if (CONS.flags & CONS_SHIFT) c = asciishift[code]; else c = asciinormal[code]; } } if (!(CONS.flags & CONS_RAW) && !(CONS.flags & CONS_CTRL)) put_console(console, c); disable; CONS.proc = NULL; enable; return c;}static int initialized = 0;intcons_init(){ u_char code; int i;#if 0 cons[0].buf = (char *) kmalloc(LINES * COLS * 2); cons[1].buf = (char *) kmalloc(LINES * COLS * 2); cons[2].buf = (char *) kmalloc(LINES * COLS * 2); cons[3].buf = (char *) kmalloc(LINES * COLS * 2);#endif for (i = 0; i < CONSOLES; i++) { cons[i].proc = NULL; /* Clear console buffer and set cursor */ clear_console(i); /* Clear keyboard buffer */ cons[i].ch = cons[i].ct = 0; cons[i].flags = CONS_RAW; } /* Setup keyboard interrupt */ isr_inst(INTR_KBD, kbd_isr, NULL); intr_unmask(INTR_KBD); /* Flush keyboard buffer */ code = inb(I8255_PORT_A); code = inb(I8255_PORT_A); /* Issue keyboard eoi */ outb(I8259_MSTR_CTRL, I8259_EOI_KBD); initialized = 1; return 0;}static intcons_ioctl(int console, u_int cmd, void *args){ int result = 0; switch (cmd) {#if 0 case GET_BLOCK_TYPE: *((int *) args) = BLK_FIXED; break;#endif case GET_BUFFER_SIZE: if (args == NULL) return EINVAL; *((u_long *) args) = 1; break; case GET_WINDOW_HEIGHT: *((int *) args) = LINES; break; case GET_WINDOW_WIDTH: *((int *) args) = COLS; break;#if 0 case SET_RAW: disable; CONS.flags |= CONS_RAW; enable; break; case SET_CANON: disable; CONS.flags &= ~CONS_RAW; enable; break;#endif case GET_CURSOR_POS: { cursor_t c = (cursor_t) args; disable; c->x = CONS_CURSOR_X; c->y = CONS_CURSOR_Y; enable; } break; case GET_CURSOR_CHAR: { char *ch = (char *) args; disable; *ch = *(CONS.curs); enable; } break; case SET_CURSOR_ON: disable; CONS.flags &= ~CONS_CURSOR_OFF; if (console == currcons) { screencurs = (CONS.curs - CONS_BASE) + SCREEN_BASE; *screencurs = CURSOR; *(screencurs + 1) = BLINK; } enable; break; case SET_CURSOR_OFF: disable; CONS.flags |= CONS_CURSOR_OFF; enable; break; case SET_CURSOR_POS: { cursor_t c = (cursor_t) args; if (c->x < 0 || c->x >= LINES || c->y < 0 || c->y >= COLS) { result = EFAIL; break; } disable; CONS.curs = CONS_BASE + 2 * (c->x * COLS + c->y); if (console == currcons) { screencurs = (CONS.curs - CONS_BASE) + SCREEN_BASE; if (!(CONS.flags & CONS_CURSOR_OFF)) { *screencurs = CURSOR; *(screencurs + 1) = BLINK; } } enable; } break; case SET_NORMAL_VIDEO: disable; CONS.flags &= ~(CONS_BRIGHT | CONS_REVERSE | CONS_BLINK); enable; break; case SET_BRIGHT_VIDEO: disable; CONS.flags &= ~(CONS_BRIGHT | CONS_REVERSE | CONS_BLINK); CONS.flags |= CONS_BRIGHT; enable; break; case SET_REVERSE_VIDEO: disable; CONS.flags &= ~(CONS_BRIGHT | CONS_REVERSE | CONS_BLINK); CONS.flags |= CONS_REVERSE; enable; break; case SET_BLINK_VIDEO: disable; CONS.flags &= ~(CONS_BRIGHT | CONS_REVERSE | CONS_BLINK); CONS.flags |= CONS_BLINK; enable; break; case CLEAR_TO_EOL: { int i; disable; for (i = 0; i < (2 * COLS) - ((CONS.curs - CONS_BASE) % (2 * COLS)); i += 2) { *(CONS.curs + i) = ' '; *(CONS.curs + i + 1) = NORMAL; if (console == currcons) { *(screencurs + i) = ' '; *(screencurs + i + 1) = NORMAL; } } enable; } break; case CLEAR: disable; clear_console(console); if (console == currcons) clear_screen(CONS.flags & CONS_CURSOR_OFF ? 0 : 1); enable; break; default: result = ENOTTY; } return result;}/******************************************************************************* Console 0 *******************************************************************************/intcons0_init(){ return cons_init();}intcons0_ioctl(u_int cmd, void *args){ return cons_ioctl(0, cmd, args);}intcons0_get(int *c){ *c = get_console(0); return 0;}intcons0_put(int c){ put_console(0, (char) c); return 0;}intcons0_shut(){ return ENOSYS;}/******************************************************************************* Console 1 *******************************************************************************/intcons1_init(){ if (initialized) return 0; else return EFAIL;}intcons1_ioctl(u_int cmd, void *args){ return cons_ioctl(1, cmd, args);}intcons1_get(int *c){ *c = get_console(1); return 0;}intcons1_put(int c){ put_console(1, (char) c); return 0;}intcons1_shut(){ return ENOSYS;}/******************************************************************************* Console 2 *******************************************************************************/intcons2_init(){ if (initialized) return 0; else return EFAIL;}intcons2_ioctl(u_int cmd, void *args){ return cons_ioctl(2, cmd, args);}intcons2_get(int *c){ *c = get_console(2); return 0;}intcons2_put(int c){ put_console(2, (char) c); return 0;}intcons2_shut(){ return ENOSYS;}/******************************************************************************* Console 3 *******************************************************************************/intcons3_init(){ if (initialized) return 0; else return EFAIL;}intcons3_ioctl(u_int cmd, void *args){ return cons_ioctl(3, cmd, args);}intcons3_get(int *c){ *c = get_console(3); return 0;}intcons3_put(int c){ put_console(3, (char) c); return 0;}intcons3_shut(){ return ENOSYS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -