1f33c8020SAxel Dörfler /* 2855ab2b3SAxel Dörfler * Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3f33c8020SAxel Dörfler * Distributed under the terms of the MIT License. 4f33c8020SAxel Dörfler */ 5f33c8020SAxel Dörfler 6f33c8020SAxel Dörfler 7f33c8020SAxel Dörfler #include "blue_screen.h" 8f33c8020SAxel Dörfler 967f20716SAxel Dörfler #include <KernelExport.h> 10f33c8020SAxel Dörfler #include <frame_buffer_console.h> 11f33c8020SAxel Dörfler #include <console.h> 126eba0636SMichael Lotz #include <debug.h> 13f33c8020SAxel Dörfler #include <arch/debug_console.h> 14f33c8020SAxel Dörfler 15f33c8020SAxel Dörfler #include <string.h> 16f33c8020SAxel Dörfler #include <stdio.h> 17f33c8020SAxel Dörfler 18855ab2b3SAxel Dörfler #include "debug_commands.h" 19855ab2b3SAxel Dörfler 20f33c8020SAxel Dörfler 21f33c8020SAxel Dörfler #define USE_SCROLLING 0 22f33c8020SAxel Dörfler #define NO_CLEAR 1 23f33c8020SAxel Dörfler 2467f20716SAxel Dörfler #define MAX_ARGS 8 2567f20716SAxel Dörfler 2667f20716SAxel Dörfler #define FMASK 0x0f 2767f20716SAxel Dörfler #define BMASK 0x70 2867f20716SAxel Dörfler 2967f20716SAxel Dörfler typedef enum { 3067f20716SAxel Dörfler CONSOLE_STATE_NORMAL = 0, 3167f20716SAxel Dörfler CONSOLE_STATE_GOT_ESCAPE, 3267f20716SAxel Dörfler CONSOLE_STATE_SEEN_BRACKET, 3367f20716SAxel Dörfler CONSOLE_STATE_NEW_ARG, 3467f20716SAxel Dörfler CONSOLE_STATE_PARSING_ARG, 3567f20716SAxel Dörfler } console_state; 3667f20716SAxel Dörfler 3770c3e1a4SAxel Dörfler typedef enum { 3870c3e1a4SAxel Dörfler LINE_ERASE_WHOLE, 3970c3e1a4SAxel Dörfler LINE_ERASE_LEFT, 4070c3e1a4SAxel Dörfler LINE_ERASE_RIGHT 4170c3e1a4SAxel Dörfler } erase_line_mode; 4270c3e1a4SAxel Dörfler 43f33c8020SAxel Dörfler struct screen_info { 44f33c8020SAxel Dörfler int32 columns; 45f33c8020SAxel Dörfler int32 rows; 46f33c8020SAxel Dörfler int32 x, y; 47f33c8020SAxel Dörfler uint8 attr; 4867f20716SAxel Dörfler bool bright_attr; 4967f20716SAxel Dörfler bool reverse_attr; 50855ab2b3SAxel Dörfler int32 in_command_rows; 51855ab2b3SAxel Dörfler bool paging; 52fec23a53SMichael Lotz bool paging_timeout; 5333965e02SAxel Dörfler bool boot_debug_output; 54855ab2b3SAxel Dörfler bool ignore_output; 5567f20716SAxel Dörfler 5667f20716SAxel Dörfler // state machine 5767f20716SAxel Dörfler console_state state; 5867f20716SAxel Dörfler int32 arg_count; 5967f20716SAxel Dörfler int32 args[MAX_ARGS]; 60f33c8020SAxel Dörfler } sScreen; 61f33c8020SAxel Dörfler 62f33c8020SAxel Dörfler console_module_info *sModule; 63f33c8020SAxel Dörfler 64f33c8020SAxel Dörfler 65f33c8020SAxel Dörfler static inline void 66f33c8020SAxel Dörfler hide_cursor(void) 67f33c8020SAxel Dörfler { 68f33c8020SAxel Dörfler sModule->move_cursor(-1, -1); 69f33c8020SAxel Dörfler } 70f33c8020SAxel Dörfler 71f33c8020SAxel Dörfler 72f33c8020SAxel Dörfler static inline void 73f33c8020SAxel Dörfler update_cursor(int32 x, int32 y) 74f33c8020SAxel Dörfler { 75f33c8020SAxel Dörfler sModule->move_cursor(x, y); 76f33c8020SAxel Dörfler } 77f33c8020SAxel Dörfler 78f33c8020SAxel Dörfler 7967f20716SAxel Dörfler static inline void 8067f20716SAxel Dörfler move_cursor(int32 x, int32 y) 8167f20716SAxel Dörfler { 8267f20716SAxel Dörfler sScreen.x = x; 8367f20716SAxel Dörfler sScreen.y = y; 8467f20716SAxel Dörfler update_cursor(x, y); 8567f20716SAxel Dörfler } 8667f20716SAxel Dörfler 8767f20716SAxel Dörfler 88f33c8020SAxel Dörfler #if USE_SCROLLING 89f33c8020SAxel Dörfler 90855ab2b3SAxel Dörfler /*! Scroll from the cursor line up to the top of the scroll region up one 91855ab2b3SAxel Dörfler line. 92855ab2b3SAxel Dörfler */ 93f33c8020SAxel Dörfler static void 94f33c8020SAxel Dörfler scroll_up(void) 95f33c8020SAxel Dörfler { 96f33c8020SAxel Dörfler // move the screen up one 97f33c8020SAxel Dörfler sModule->blit(0, 1, sScreen.columns, sScreen.rows - 1, 0, 0); 98f33c8020SAxel Dörfler 99f33c8020SAxel Dörfler // clear the bottom line 100f33c8020SAxel Dörfler sModule->fill_glyph(0, 0, sScreen.columns, 1, ' ', sScreen.attr); 101f33c8020SAxel Dörfler } 102f33c8020SAxel Dörfler #endif 103f33c8020SAxel Dörfler 104f33c8020SAxel Dörfler 105f33c8020SAxel Dörfler static void 106f33c8020SAxel Dörfler next_line(void) 107f33c8020SAxel Dörfler { 108f937627dSIngo Weinhold bool abortCommand = false; 109f937627dSIngo Weinhold 110a39bfc19SAxel Dörfler #if USE_SCROLLING 111a39bfc19SAxel Dörfler // TODO: scrolling is usually too slow; we could probably just remove it 112a39bfc19SAxel Dörfler if (sScreen.y == sScreen.rows - 1) 113a39bfc19SAxel Dörfler scroll_up(); 114a39bfc19SAxel Dörfler else 115a39bfc19SAxel Dörfler sScreen.y++; 116a39bfc19SAxel Dörfler #else 117855ab2b3SAxel Dörfler if (in_command_invocation()) 118855ab2b3SAxel Dörfler sScreen.in_command_rows++; 119855ab2b3SAxel Dörfler else 120855ab2b3SAxel Dörfler sScreen.in_command_rows = 0; 121855ab2b3SAxel Dörfler 122a39bfc19SAxel Dörfler if (sScreen.paging && ((sScreen.in_command_rows > 0 123a39bfc19SAxel Dörfler && ((sScreen.in_command_rows + 3) % sScreen.rows) == 0) 124a39bfc19SAxel Dörfler || (sScreen.boot_debug_output && sScreen.y == sScreen.rows - 1))) { 125fec23a53SMichael Lotz if (sScreen.paging_timeout) 126fec23a53SMichael Lotz spin(1000 * 1000 * 3); 127fec23a53SMichael Lotz else { 128a39bfc19SAxel Dörfler // Use the paging mechanism: either, we're in the debugger, and a 129a39bfc19SAxel Dörfler // command is being executed, or we're currently showing boot debug 130a39bfc19SAxel Dörfler // output 131f937627dSIngo Weinhold const char *text = in_command_invocation() 132f937627dSIngo Weinhold ? "Press key to continue, Q to quit, S to skip output" 133bc2836bbSMichael Lotz : "Press key to continue, S to skip output, P to disable paging"; 134855ab2b3SAxel Dörfler int32 length = strlen(text); 135855ab2b3SAxel Dörfler if (sScreen.x + length > sScreen.columns) { 136855ab2b3SAxel Dörfler // make sure we don't overwrite too much 137855ab2b3SAxel Dörfler text = "P"; 138855ab2b3SAxel Dörfler length = 1; 139855ab2b3SAxel Dörfler } 140855ab2b3SAxel Dörfler 141855ab2b3SAxel Dörfler for (int32 i = 0; i < length; i++) { 142a39bfc19SAxel Dörfler // yellow on black (or reverse, during boot) 143855ab2b3SAxel Dörfler sModule->put_glyph(sScreen.columns - length + i, sScreen.y, 144a39bfc19SAxel Dörfler text[i], sScreen.boot_debug_output ? 0x6f : 0xf6); 145855ab2b3SAxel Dörfler } 146855ab2b3SAxel Dörfler 1476eba0636SMichael Lotz char c = kgetc(); 148f937627dSIngo Weinhold if (c == 's') { 149855ab2b3SAxel Dörfler sScreen.ignore_output = true; 150bc2836bbSMichael Lotz } else if (c == 'q' && in_command_invocation()) { 151bc2836bbSMichael Lotz abortCommand = true; 15273aa393dSIngo Weinhold sScreen.ignore_output = true; 153bc2836bbSMichael Lotz } else if (c == 'p' && !in_command_invocation()) 154bc2836bbSMichael Lotz sScreen.paging = false; 155fec23a53SMichael Lotz else if (c == 't' && !in_command_invocation()) 156fec23a53SMichael Lotz sScreen.paging_timeout = true; 157855ab2b3SAxel Dörfler 158855ab2b3SAxel Dörfler // remove on screen text again 159855ab2b3SAxel Dörfler sModule->fill_glyph(sScreen.columns - length, sScreen.y, length, 160855ab2b3SAxel Dörfler 1, ' ', sScreen.attr); 161855ab2b3SAxel Dörfler } 162*ab542128SMichael Lotz 163*ab542128SMichael Lotz if (sScreen.in_command_rows > 0) 164*ab542128SMichael Lotz sScreen.in_command_rows += 2; 165fec23a53SMichael Lotz } 166a39bfc19SAxel Dörfler if (sScreen.y == sScreen.rows - 1) { 167f33c8020SAxel Dörfler sScreen.y = 0; 168855ab2b3SAxel Dörfler sModule->fill_glyph(0, 0, sScreen.columns, 2, ' ', sScreen.attr); 169a39bfc19SAxel Dörfler } else 170f33c8020SAxel Dörfler sScreen.y++; 171a39bfc19SAxel Dörfler #endif 172f33c8020SAxel Dörfler 173f33c8020SAxel Dörfler #if NO_CLEAR 174855ab2b3SAxel Dörfler if (sScreen.y + 2 < sScreen.rows) { 175855ab2b3SAxel Dörfler sModule->fill_glyph(0, (sScreen.y + 2) % sScreen.rows, sScreen.columns, 176855ab2b3SAxel Dörfler 1, ' ', sScreen.attr); 177855ab2b3SAxel Dörfler } 178f33c8020SAxel Dörfler #endif 179f33c8020SAxel Dörfler sScreen.x = 0; 180f937627dSIngo Weinhold 181f937627dSIngo Weinhold if (abortCommand) { 182f937627dSIngo Weinhold abort_debugger_command(); 183f937627dSIngo Weinhold // should not return 184f937627dSIngo Weinhold } 185f33c8020SAxel Dörfler } 186f33c8020SAxel Dörfler 187f33c8020SAxel Dörfler 188f33c8020SAxel Dörfler static void 18970c3e1a4SAxel Dörfler erase_line(erase_line_mode mode) 19070c3e1a4SAxel Dörfler { 19170c3e1a4SAxel Dörfler switch (mode) { 19270c3e1a4SAxel Dörfler case LINE_ERASE_WHOLE: 193855ab2b3SAxel Dörfler sModule->fill_glyph(0, sScreen.y, sScreen.columns, 1, ' ', 194855ab2b3SAxel Dörfler sScreen.attr); 19570c3e1a4SAxel Dörfler break; 19670c3e1a4SAxel Dörfler case LINE_ERASE_LEFT: 197855ab2b3SAxel Dörfler sModule->fill_glyph(0, sScreen.y, sScreen.x + 1, 1, ' ', 198855ab2b3SAxel Dörfler sScreen.attr); 19970c3e1a4SAxel Dörfler break; 20070c3e1a4SAxel Dörfler case LINE_ERASE_RIGHT: 201855ab2b3SAxel Dörfler sModule->fill_glyph(sScreen.x, sScreen.y, sScreen.columns 202855ab2b3SAxel Dörfler - sScreen.x, 1, ' ', sScreen.attr); 20370c3e1a4SAxel Dörfler break; 20470c3e1a4SAxel Dörfler } 20570c3e1a4SAxel Dörfler } 20670c3e1a4SAxel Dörfler 20770c3e1a4SAxel Dörfler 20870c3e1a4SAxel Dörfler static void 209f33c8020SAxel Dörfler back_space(void) 210f33c8020SAxel Dörfler { 211f33c8020SAxel Dörfler if (sScreen.x <= 0) 212f33c8020SAxel Dörfler return; 213f33c8020SAxel Dörfler 214f33c8020SAxel Dörfler sScreen.x--; 215f33c8020SAxel Dörfler sModule->put_glyph(sScreen.x, sScreen.y, ' ', sScreen.attr); 216f33c8020SAxel Dörfler } 217f33c8020SAxel Dörfler 218f33c8020SAxel Dörfler 219f33c8020SAxel Dörfler static void 220f33c8020SAxel Dörfler put_character(char c) 221f33c8020SAxel Dörfler { 222f33c8020SAxel Dörfler if (++sScreen.x >= sScreen.columns) { 223f33c8020SAxel Dörfler next_line(); 224f33c8020SAxel Dörfler sScreen.x++; 225f33c8020SAxel Dörfler } 226f33c8020SAxel Dörfler 227f33c8020SAxel Dörfler sModule->put_glyph(sScreen.x - 1, sScreen.y, c, sScreen.attr); 228f33c8020SAxel Dörfler } 229f33c8020SAxel Dörfler 230f33c8020SAxel Dörfler 231f33c8020SAxel Dörfler static void 23267f20716SAxel Dörfler set_vt100_attributes(int32 *args, int32 argCount) 23367f20716SAxel Dörfler { 23467f20716SAxel Dörfler if (argCount == 0) { 23567f20716SAxel Dörfler // that's the default (attributes off) 23667f20716SAxel Dörfler argCount++; 23767f20716SAxel Dörfler args[0] = 0; 23867f20716SAxel Dörfler } 23967f20716SAxel Dörfler 24067f20716SAxel Dörfler for (int32 i = 0; i < argCount; i++) { 24167f20716SAxel Dörfler switch (args[i]) { 24267f20716SAxel Dörfler case 0: // reset 24333965e02SAxel Dörfler sScreen.attr = sScreen.boot_debug_output ? 0xf0 : 0x0f; 24467f20716SAxel Dörfler sScreen.bright_attr = true; 24567f20716SAxel Dörfler sScreen.reverse_attr = false; 24667f20716SAxel Dörfler break; 24767f20716SAxel Dörfler case 1: // bright 24867f20716SAxel Dörfler sScreen.bright_attr = true; 24967f20716SAxel Dörfler sScreen.attr |= 0x08; // set the bright bit 25067f20716SAxel Dörfler break; 25167f20716SAxel Dörfler case 2: // dim 25267f20716SAxel Dörfler sScreen.bright_attr = false; 25367f20716SAxel Dörfler sScreen.attr &= ~0x08; // unset the bright bit 25467f20716SAxel Dörfler break; 25567f20716SAxel Dörfler case 4: // underscore we can't do 25667f20716SAxel Dörfler break; 25767f20716SAxel Dörfler case 5: // blink 25867f20716SAxel Dörfler sScreen.attr |= 0x80; // set the blink bit 25967f20716SAxel Dörfler break; 26067f20716SAxel Dörfler case 7: // reverse 26167f20716SAxel Dörfler sScreen.reverse_attr = true; 262855ab2b3SAxel Dörfler sScreen.attr = ((sScreen.attr & BMASK) >> 4) 263855ab2b3SAxel Dörfler | ((sScreen.attr & FMASK) << 4); 26467f20716SAxel Dörfler if (sScreen.bright_attr) 26567f20716SAxel Dörfler sScreen.attr |= 0x08; 26667f20716SAxel Dörfler break; 26767f20716SAxel Dörfler case 8: // hidden? 26867f20716SAxel Dörfler break; 26967f20716SAxel Dörfler 27067f20716SAxel Dörfler /* foreground colors */ 271855ab2b3SAxel Dörfler case 30: // black 272855ab2b3SAxel Dörfler case 31: // red 273855ab2b3SAxel Dörfler case 32: // green 274855ab2b3SAxel Dörfler case 33: // yellow 275855ab2b3SAxel Dörfler case 34: // blue 276855ab2b3SAxel Dörfler case 35: // magenta 277855ab2b3SAxel Dörfler case 36: // cyan 278855ab2b3SAxel Dörfler case 37: // white 279855ab2b3SAxel Dörfler { 280855ab2b3SAxel Dörfler const uint8 colors[] = {0, 4, 2, 6, 1, 5, 3, 7}; 281855ab2b3SAxel Dörfler sScreen.attr = (sScreen.attr & ~FMASK) | colors[args[i] - 30] 282855ab2b3SAxel Dörfler | (sScreen.bright_attr ? 0x08 : 0); 283855ab2b3SAxel Dörfler break; 284855ab2b3SAxel Dörfler } 28567f20716SAxel Dörfler 28667f20716SAxel Dörfler /* background colors */ 28767f20716SAxel Dörfler case 40: sScreen.attr = (sScreen.attr & ~BMASK) | (0 << 4); break; // black 28867f20716SAxel Dörfler case 41: sScreen.attr = (sScreen.attr & ~BMASK) | (4 << 4); break; // red 28967f20716SAxel Dörfler case 42: sScreen.attr = (sScreen.attr & ~BMASK) | (2 << 4); break; // green 29067f20716SAxel Dörfler case 43: sScreen.attr = (sScreen.attr & ~BMASK) | (6 << 4); break; // yellow 29167f20716SAxel Dörfler case 44: sScreen.attr = (sScreen.attr & ~BMASK) | (1 << 4); break; // blue 29267f20716SAxel Dörfler case 45: sScreen.attr = (sScreen.attr & ~BMASK) | (5 << 4); break; // magenta 29367f20716SAxel Dörfler case 46: sScreen.attr = (sScreen.attr & ~BMASK) | (3 << 4); break; // cyan 29467f20716SAxel Dörfler case 47: sScreen.attr = (sScreen.attr & ~BMASK) | (7 << 4); break; // white 29567f20716SAxel Dörfler } 29667f20716SAxel Dörfler } 29767f20716SAxel Dörfler } 29867f20716SAxel Dörfler 29967f20716SAxel Dörfler 30067f20716SAxel Dörfler static bool 30167f20716SAxel Dörfler process_vt100_command(const char c, bool seenBracket, int32 *args, int32 argCount) 30267f20716SAxel Dörfler { 30367f20716SAxel Dörfler bool ret = true; 30467f20716SAxel Dörfler 30567f20716SAxel Dörfler // kprintf("process_vt100_command: c '%c', argCount %ld, arg[0] %ld, arg[1] %ld, seenBracket %d\n", 30667f20716SAxel Dörfler // c, argCount, args[0], args[1], seenBracket); 30767f20716SAxel Dörfler 30867f20716SAxel Dörfler if (seenBracket) { 30967f20716SAxel Dörfler switch (c) { 31067f20716SAxel Dörfler case 'H': /* set cursor position */ 31167f20716SAxel Dörfler case 'f': { 31267f20716SAxel Dörfler int32 row = argCount > 0 ? args[0] : 1; 31367f20716SAxel Dörfler int32 col = argCount > 1 ? args[1] : 1; 31467f20716SAxel Dörfler if (row > 0) 31567f20716SAxel Dörfler row--; 31667f20716SAxel Dörfler if (col > 0) 31767f20716SAxel Dörfler col--; 31867f20716SAxel Dörfler move_cursor(col, row); 31967f20716SAxel Dörfler break; 32067f20716SAxel Dörfler } 32167f20716SAxel Dörfler case 'A': { /* move up */ 32267f20716SAxel Dörfler int32 deltay = argCount > 0 ? -args[0] : -1; 32367f20716SAxel Dörfler if (deltay == 0) 32467f20716SAxel Dörfler deltay = -1; 32567f20716SAxel Dörfler move_cursor(sScreen.x, sScreen.y + deltay); 32667f20716SAxel Dörfler break; 32767f20716SAxel Dörfler } 32867f20716SAxel Dörfler case 'e': 32967f20716SAxel Dörfler case 'B': { /* move down */ 33067f20716SAxel Dörfler int32 deltay = argCount > 0 ? args[0] : 1; 33167f20716SAxel Dörfler if (deltay == 0) 33267f20716SAxel Dörfler deltay = 1; 33367f20716SAxel Dörfler move_cursor(sScreen.x, sScreen.y + deltay); 33467f20716SAxel Dörfler break; 33567f20716SAxel Dörfler } 33667f20716SAxel Dörfler case 'D': { /* move left */ 33767f20716SAxel Dörfler int32 deltax = argCount > 0 ? -args[0] : -1; 33867f20716SAxel Dörfler if (deltax == 0) 33967f20716SAxel Dörfler deltax = -1; 34067f20716SAxel Dörfler move_cursor(sScreen.x + deltax, sScreen.y); 34167f20716SAxel Dörfler break; 34267f20716SAxel Dörfler } 34367f20716SAxel Dörfler case 'a': 34467f20716SAxel Dörfler case 'C': { /* move right */ 34567f20716SAxel Dörfler int32 deltax = argCount > 0 ? args[0] : 1; 34667f20716SAxel Dörfler if (deltax == 0) 34767f20716SAxel Dörfler deltax = 1; 34867f20716SAxel Dörfler move_cursor(sScreen.x + deltax, sScreen.y); 34967f20716SAxel Dörfler break; 35067f20716SAxel Dörfler } 35167f20716SAxel Dörfler case '`': 35267f20716SAxel Dörfler case 'G': { /* set X position */ 35367f20716SAxel Dörfler int32 newx = argCount > 0 ? args[0] : 1; 35467f20716SAxel Dörfler if (newx > 0) 35567f20716SAxel Dörfler newx--; 35667f20716SAxel Dörfler move_cursor(newx, sScreen.y); 35767f20716SAxel Dörfler break; 35867f20716SAxel Dörfler } 35967f20716SAxel Dörfler case 'd': { /* set y position */ 36067f20716SAxel Dörfler int32 newy = argCount > 0 ? args[0] : 1; 36167f20716SAxel Dörfler if (newy > 0) 36267f20716SAxel Dörfler newy--; 36367f20716SAxel Dörfler move_cursor(sScreen.x, newy); 36467f20716SAxel Dörfler break; 36567f20716SAxel Dörfler } 36667f20716SAxel Dörfler #if 0 36767f20716SAxel Dörfler case 's': /* save current cursor */ 36867f20716SAxel Dörfler save_cur(console, false); 36967f20716SAxel Dörfler break; 37067f20716SAxel Dörfler case 'u': /* restore cursor */ 37167f20716SAxel Dörfler restore_cur(console, false); 37267f20716SAxel Dörfler break; 37367f20716SAxel Dörfler case 'r': { /* set scroll region */ 37467f20716SAxel Dörfler int32 low = argCount > 0 ? args[0] : 1; 37567f20716SAxel Dörfler int32 high = argCount > 1 ? args[1] : sScreen.lines; 37667f20716SAxel Dörfler if (low <= high) 37767f20716SAxel Dörfler set_scroll_region(console, low - 1, high - 1); 37867f20716SAxel Dörfler break; 37967f20716SAxel Dörfler } 38067f20716SAxel Dörfler case 'L': { /* scroll virtual down at cursor */ 38167f20716SAxel Dörfler int32 lines = argCount > 0 ? args[0] : 1; 38267f20716SAxel Dörfler while (lines > 0) { 38367f20716SAxel Dörfler scrdown(console); 38467f20716SAxel Dörfler lines--; 38567f20716SAxel Dörfler } 38667f20716SAxel Dörfler break; 38767f20716SAxel Dörfler } 38867f20716SAxel Dörfler case 'M': { /* scroll virtual up at cursor */ 38967f20716SAxel Dörfler int32 lines = argCount > 0 ? args[0] : 1; 39067f20716SAxel Dörfler while (lines > 0) { 39167f20716SAxel Dörfler scrup(console); 39267f20716SAxel Dörfler lines--; 39367f20716SAxel Dörfler } 39467f20716SAxel Dörfler break; 39567f20716SAxel Dörfler } 39670c3e1a4SAxel Dörfler #endif 39767f20716SAxel Dörfler case 'K': 39867f20716SAxel Dörfler if (argCount == 0 || args[0] == 0) { 39967f20716SAxel Dörfler // erase to end of line 40070c3e1a4SAxel Dörfler erase_line(LINE_ERASE_RIGHT); 40167f20716SAxel Dörfler } else if (argCount > 0) { 40267f20716SAxel Dörfler if (args[0] == 1) 40370c3e1a4SAxel Dörfler erase_line(LINE_ERASE_LEFT); 40467f20716SAxel Dörfler else if (args[0] == 2) 40570c3e1a4SAxel Dörfler erase_line(LINE_ERASE_WHOLE); 40667f20716SAxel Dörfler } 40767f20716SAxel Dörfler break; 40870c3e1a4SAxel Dörfler #if 0 40967f20716SAxel Dörfler case 'J': 41067f20716SAxel Dörfler if (argCount == 0 || args[0] == 0) { 41167f20716SAxel Dörfler // erase to end of screen 41267f20716SAxel Dörfler erase_screen(console, SCREEN_ERASE_DOWN); 41367f20716SAxel Dörfler } else { 41467f20716SAxel Dörfler if (args[0] == 1) 41567f20716SAxel Dörfler erase_screen(console, SCREEN_ERASE_UP); 41667f20716SAxel Dörfler else if (args[0] == 2) 41767f20716SAxel Dörfler erase_screen(console, SCREEN_ERASE_WHOLE); 41867f20716SAxel Dörfler } 41967f20716SAxel Dörfler break; 42067f20716SAxel Dörfler #endif 42167f20716SAxel Dörfler case 'm': 42267f20716SAxel Dörfler if (argCount >= 0) 42367f20716SAxel Dörfler set_vt100_attributes(args, argCount); 42467f20716SAxel Dörfler break; 42567f20716SAxel Dörfler default: 42667f20716SAxel Dörfler ret = false; 42767f20716SAxel Dörfler } 42867f20716SAxel Dörfler } else { 42967f20716SAxel Dörfler switch (c) { 43067f20716SAxel Dörfler #if 0 43167f20716SAxel Dörfler case 'c': 43267f20716SAxel Dörfler reset_console(console); 43367f20716SAxel Dörfler break; 43467f20716SAxel Dörfler case 'D': 43567f20716SAxel Dörfler rlf(console); 43667f20716SAxel Dörfler break; 43767f20716SAxel Dörfler case 'M': 43867f20716SAxel Dörfler lf(console); 43967f20716SAxel Dörfler break; 44067f20716SAxel Dörfler case '7': 44167f20716SAxel Dörfler save_cur(console, true); 44267f20716SAxel Dörfler break; 44367f20716SAxel Dörfler case '8': 44467f20716SAxel Dörfler restore_cur(console, true); 44567f20716SAxel Dörfler break; 44667f20716SAxel Dörfler #endif 44767f20716SAxel Dörfler default: 44867f20716SAxel Dörfler ret = false; 44967f20716SAxel Dörfler } 45067f20716SAxel Dörfler } 45167f20716SAxel Dörfler 45267f20716SAxel Dörfler return ret; 45367f20716SAxel Dörfler } 45467f20716SAxel Dörfler 45567f20716SAxel Dörfler 45667f20716SAxel Dörfler static void 457f33c8020SAxel Dörfler parse_character(char c) 458f33c8020SAxel Dörfler { 45967f20716SAxel Dörfler switch (sScreen.state) { 46067f20716SAxel Dörfler case CONSOLE_STATE_NORMAL: 461f33c8020SAxel Dörfler // just output the stuff 462f33c8020SAxel Dörfler switch (c) { 463f33c8020SAxel Dörfler case '\n': 464f33c8020SAxel Dörfler next_line(); 465f33c8020SAxel Dörfler break; 466f33c8020SAxel Dörfler case 0x8: 467f33c8020SAxel Dörfler back_space(); 468f33c8020SAxel Dörfler break; 469f33c8020SAxel Dörfler case '\t': 47067f20716SAxel Dörfler // ToDo: real tab... 471f31dc4ddSAxel Dörfler sScreen.x = (sScreen.x + 8) & ~7; 472f31dc4ddSAxel Dörfler if (sScreen.x >= sScreen.columns) 473f31dc4ddSAxel Dörfler next_line(); 474f33c8020SAxel Dörfler break; 475f33c8020SAxel Dörfler 476f33c8020SAxel Dörfler case '\r': 477f33c8020SAxel Dörfler case '\0': 47867f20716SAxel Dörfler case '\a': // beep 479f33c8020SAxel Dörfler break; 480f33c8020SAxel Dörfler 48167f20716SAxel Dörfler case 0x1b: 48267f20716SAxel Dörfler // escape character 48367f20716SAxel Dörfler sScreen.arg_count = -1; 48467f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_GOT_ESCAPE; 48567f20716SAxel Dörfler break; 486f33c8020SAxel Dörfler default: 487f33c8020SAxel Dörfler put_character(c); 488f33c8020SAxel Dörfler } 48967f20716SAxel Dörfler break; 49067f20716SAxel Dörfler case CONSOLE_STATE_GOT_ESCAPE: 49167f20716SAxel Dörfler // look for either commands with no argument, or the '[' character 49267f20716SAxel Dörfler switch (c) { 49367f20716SAxel Dörfler case '[': 49467f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_SEEN_BRACKET; 49567f20716SAxel Dörfler break; 49667f20716SAxel Dörfler default: 49767f20716SAxel Dörfler sScreen.args[sScreen.arg_count] = 0; 498855ab2b3SAxel Dörfler process_vt100_command(c, false, sScreen.args, 499855ab2b3SAxel Dörfler sScreen.arg_count + 1); 50067f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_NORMAL; 50167f20716SAxel Dörfler } 50267f20716SAxel Dörfler break; 50367f20716SAxel Dörfler case CONSOLE_STATE_SEEN_BRACKET: 50467f20716SAxel Dörfler switch (c) { 50567f20716SAxel Dörfler case '0'...'9': 50667f20716SAxel Dörfler sScreen.arg_count = 0; 50767f20716SAxel Dörfler sScreen.args[sScreen.arg_count] = c - '0'; 50867f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_PARSING_ARG; 50967f20716SAxel Dörfler break; 51067f20716SAxel Dörfler case '?': 511855ab2b3SAxel Dörfler // private DEC mode parameter follows - we ignore those 512855ab2b3SAxel Dörfler // anyway 51367f20716SAxel Dörfler break; 51467f20716SAxel Dörfler default: 515855ab2b3SAxel Dörfler process_vt100_command(c, true, sScreen.args, 516855ab2b3SAxel Dörfler sScreen.arg_count + 1); 51767f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_NORMAL; 51867f20716SAxel Dörfler } 51967f20716SAxel Dörfler break; 52067f20716SAxel Dörfler case CONSOLE_STATE_NEW_ARG: 52167f20716SAxel Dörfler switch (c) { 52267f20716SAxel Dörfler case '0'...'9': 52367f20716SAxel Dörfler sScreen.arg_count++; 52467f20716SAxel Dörfler if (sScreen.arg_count == MAX_ARGS) { 52567f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_NORMAL; 52667f20716SAxel Dörfler break; 52767f20716SAxel Dörfler } 52867f20716SAxel Dörfler sScreen.args[sScreen.arg_count] = c - '0'; 52967f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_PARSING_ARG; 53067f20716SAxel Dörfler break; 53167f20716SAxel Dörfler default: 532855ab2b3SAxel Dörfler process_vt100_command(c, true, sScreen.args, 533855ab2b3SAxel Dörfler sScreen.arg_count + 1); 53467f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_NORMAL; 53567f20716SAxel Dörfler } 53667f20716SAxel Dörfler break; 53767f20716SAxel Dörfler case CONSOLE_STATE_PARSING_ARG: 53867f20716SAxel Dörfler // parse args 53967f20716SAxel Dörfler switch (c) { 54067f20716SAxel Dörfler case '0'...'9': 54167f20716SAxel Dörfler sScreen.args[sScreen.arg_count] *= 10; 54267f20716SAxel Dörfler sScreen.args[sScreen.arg_count] += c - '0'; 54367f20716SAxel Dörfler break; 54467f20716SAxel Dörfler case ';': 54567f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_NEW_ARG; 54667f20716SAxel Dörfler break; 54767f20716SAxel Dörfler default: 548855ab2b3SAxel Dörfler process_vt100_command(c, true, sScreen.args, 549855ab2b3SAxel Dörfler sScreen.arg_count + 1); 55067f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_NORMAL; 55167f20716SAxel Dörfler } 55267f20716SAxel Dörfler } 553f33c8020SAxel Dörfler } 554f33c8020SAxel Dörfler 555f33c8020SAxel Dörfler 556855ab2b3SAxel Dörfler static int 557855ab2b3SAxel Dörfler set_paging(int argc, char **argv) 558855ab2b3SAxel Dörfler { 559855ab2b3SAxel Dörfler if (argc > 1 && !strcmp(argv[1], "--help")) { 560855ab2b3SAxel Dörfler kprintf("usage: %s [on|off]\n", argv[0]); 561855ab2b3SAxel Dörfler return 0; 562855ab2b3SAxel Dörfler } 563855ab2b3SAxel Dörfler 564855ab2b3SAxel Dörfler if (argc == 1) 565855ab2b3SAxel Dörfler sScreen.paging = !sScreen.paging; 566855ab2b3SAxel Dörfler else if (!strcmp(argv[1], "on")) 567855ab2b3SAxel Dörfler sScreen.paging = true; 568855ab2b3SAxel Dörfler else if (!strcmp(argv[1], "off")) 569855ab2b3SAxel Dörfler sScreen.paging = false; 570855ab2b3SAxel Dörfler else 571855ab2b3SAxel Dörfler sScreen.paging = parse_expression(argv[1]) != 0; 572855ab2b3SAxel Dörfler 573855ab2b3SAxel Dörfler kprintf("paging is turned %s now.\n", sScreen.paging ? "on" : "off"); 574855ab2b3SAxel Dörfler return 0; 575855ab2b3SAxel Dörfler } 576855ab2b3SAxel Dörfler 577855ab2b3SAxel Dörfler 578f33c8020SAxel Dörfler // #pragma mark - 579f33c8020SAxel Dörfler 580f33c8020SAxel Dörfler 581f33c8020SAxel Dörfler status_t 582f33c8020SAxel Dörfler blue_screen_init(void) 583f33c8020SAxel Dörfler { 584f33c8020SAxel Dörfler extern console_module_info gFrameBufferConsoleModule; 585f33c8020SAxel Dörfler 586f33c8020SAxel Dörfler // we can't use get_module() here, since it's too early in the boot process 587f33c8020SAxel Dörfler 588f33c8020SAxel Dörfler if (!frame_buffer_console_available()) 589f33c8020SAxel Dörfler return B_ERROR; 590f33c8020SAxel Dörfler 591f33c8020SAxel Dörfler sModule = &gFrameBufferConsoleModule; 592855ab2b3SAxel Dörfler sScreen.paging = true; 593fec23a53SMichael Lotz sScreen.paging_timeout = false; 594855ab2b3SAxel Dörfler 595855ab2b3SAxel Dörfler add_debugger_command("paging", set_paging, "Enable or disable paging"); 596f33c8020SAxel Dörfler return B_OK; 597f33c8020SAxel Dörfler } 598f33c8020SAxel Dörfler 599f33c8020SAxel Dörfler 600173d0b2fSAxel Dörfler status_t 60192447917SAxel Dörfler blue_screen_enter(bool debugOutput) 602f33c8020SAxel Dörfler { 60392447917SAxel Dörfler sScreen.attr = debugOutput ? 0xf0 : 0x0f; 60492447917SAxel Dörfler // black on white for KDL, white on black for debug output 60533965e02SAxel Dörfler sScreen.boot_debug_output = debugOutput; 60633965e02SAxel Dörfler sScreen.ignore_output = false; 60733965e02SAxel Dörfler 608f33c8020SAxel Dörfler sScreen.x = sScreen.y = 0; 60967f20716SAxel Dörfler sScreen.state = CONSOLE_STATE_NORMAL; 610f33c8020SAxel Dörfler 611173d0b2fSAxel Dörfler if (sModule == NULL) 612173d0b2fSAxel Dörfler return B_NO_INIT; 613173d0b2fSAxel Dörfler 614f33c8020SAxel Dörfler sModule->get_size(&sScreen.columns, &sScreen.rows); 615f33c8020SAxel Dörfler #if !NO_CLEAR 616f33c8020SAxel Dörfler sModule->clear(sScreen.attr); 617f33c8020SAxel Dörfler #else 618f33c8020SAxel Dörfler sModule->fill_glyph(0, sScreen.y, sScreen.columns, 3, ' ', sScreen.attr); 619f33c8020SAxel Dörfler #endif 620173d0b2fSAxel Dörfler return B_OK; 621f33c8020SAxel Dörfler } 622f33c8020SAxel Dörfler 623f33c8020SAxel Dörfler 624a1587d16SIngo Weinhold void 625a1587d16SIngo Weinhold blue_screen_clear_screen(void) 626a1587d16SIngo Weinhold { 627a1587d16SIngo Weinhold sModule->clear(sScreen.attr); 628a1587d16SIngo Weinhold move_cursor(0, 0); 629a1587d16SIngo Weinhold } 630a1587d16SIngo Weinhold 631a1587d16SIngo Weinhold 632f33c8020SAxel Dörfler char 633f33c8020SAxel Dörfler blue_screen_getchar(void) 634f33c8020SAxel Dörfler { 635f33c8020SAxel Dörfler return arch_debug_blue_screen_getchar(); 636f33c8020SAxel Dörfler } 637f33c8020SAxel Dörfler 638f33c8020SAxel Dörfler 639f33c8020SAxel Dörfler void 640f33c8020SAxel Dörfler blue_screen_putchar(char c) 641f33c8020SAxel Dörfler { 64233965e02SAxel Dörfler if (sScreen.ignore_output 64333965e02SAxel Dörfler && (in_command_invocation() || sScreen.boot_debug_output)) 644855ab2b3SAxel Dörfler return; 645855ab2b3SAxel Dörfler 646855ab2b3SAxel Dörfler sScreen.ignore_output = false; 647f33c8020SAxel Dörfler hide_cursor(); 648f33c8020SAxel Dörfler 649f33c8020SAxel Dörfler parse_character(c); 650f33c8020SAxel Dörfler 651f33c8020SAxel Dörfler update_cursor(sScreen.x, sScreen.y); 652f33c8020SAxel Dörfler } 653f33c8020SAxel Dörfler 654f33c8020SAxel Dörfler 655f33c8020SAxel Dörfler void 656f33c8020SAxel Dörfler blue_screen_puts(const char *text) 657f33c8020SAxel Dörfler { 65833965e02SAxel Dörfler if (sScreen.ignore_output 65933965e02SAxel Dörfler && (in_command_invocation() || sScreen.boot_debug_output)) 660855ab2b3SAxel Dörfler return; 661855ab2b3SAxel Dörfler 662855ab2b3SAxel Dörfler sScreen.ignore_output = false; 663f33c8020SAxel Dörfler hide_cursor(); 664f33c8020SAxel Dörfler 665f33c8020SAxel Dörfler while (text[0] != '\0') { 666f33c8020SAxel Dörfler parse_character(text[0]); 667f33c8020SAxel Dörfler text++; 668f33c8020SAxel Dörfler } 669f33c8020SAxel Dörfler 670f33c8020SAxel Dörfler update_cursor(sScreen.x, sScreen.y); 671f33c8020SAxel Dörfler } 672