1 /* 2 * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Copyright 2011, Rene Gollent, rene@gollent.com. All rights reserved. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "console.h" 9 #include "keyboard.h" 10 #include "video.h" 11 12 #include <SupportDefs.h> 13 #include <util/kernel_cpp.h> 14 #include <boot/stage2.h> 15 16 #include <string.h> 17 18 19 class Console : public ConsoleNode { 20 public: 21 Console(); 22 23 virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize); 24 virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize); 25 26 virtual void ClearScreen(); 27 virtual int32 Width(); 28 virtual int32 Height(); 29 virtual void SetCursor(int32 x, int32 y); 30 virtual void SetCursorVisible(bool visible); 31 virtual void SetColors(int32 foreground, int32 background); 32 }; 33 34 static uint16 *sScreenBase = (uint16 *)0xb8000; 35 static uint32 sScreenWidth = 80; 36 static uint32 sScreenHeight = 25; 37 static uint32 sScreenOffset = 0; 38 static uint16 sColor = 0x0f00; 39 40 extern ConsoleNode* gConsoleNode; 41 static Console sConsole; 42 FILE *stdin, *stdout, *stderr; 43 44 45 static void 46 scroll_up() 47 { 48 memcpy(sScreenBase, sScreenBase + sScreenWidth, 49 sScreenWidth * sScreenHeight * 2 - sScreenWidth * 2); 50 sScreenOffset = (sScreenHeight - 1) * sScreenWidth; 51 52 for (uint32 i = 0; i < sScreenWidth; i++) 53 sScreenBase[sScreenOffset + i] = sColor | ' '; 54 } 55 56 57 // #pragma mark - 58 59 60 Console::Console() 61 : ConsoleNode() 62 { 63 } 64 65 66 ssize_t 67 Console::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize) 68 { 69 // don't seek in character devices 70 // not implemented (and not yet? needed) 71 return B_ERROR; 72 } 73 74 75 ssize_t 76 Console::WriteAt(void *cookie, off_t /*pos*/, const void *buffer, size_t bufferSize) 77 { 78 const char *string = (const char *)buffer; 79 80 if (gKernelArgs.frame_buffer.enabled) 81 return bufferSize; 82 83 for (uint32 i = 0; i < bufferSize; i++) { 84 if (string[0] == '\n') 85 sScreenOffset += sScreenWidth - (sScreenOffset % sScreenWidth); 86 else 87 sScreenBase[sScreenOffset++] = sColor | string[0]; 88 89 if (sScreenOffset >= sScreenWidth * sScreenHeight) 90 scroll_up(); 91 92 string++; 93 } 94 return bufferSize; 95 } 96 97 98 void 99 Console::ClearScreen() 100 { 101 if (gKernelArgs.frame_buffer.enabled) 102 return; 103 104 for (uint32 i = 0; i < sScreenWidth * sScreenHeight; i++) 105 sScreenBase[i] = sColor; 106 107 // reset cursor position as well 108 sScreenOffset = 0; 109 } 110 111 112 int32 113 Console::Width() 114 { 115 return sScreenWidth; 116 } 117 118 119 int32 120 Console::Height() 121 { 122 return sScreenHeight; 123 } 124 125 126 void 127 Console::SetCursor(int32 x, int32 y) 128 { 129 if (y >= (int32)sScreenHeight) 130 y = sScreenHeight - 1; 131 else if (y < 0) 132 y = 0; 133 if (x >= (int32)sScreenWidth) 134 x = sScreenWidth - 1; 135 else if (x < 0) 136 x = 0; 137 138 sScreenOffset = x + y * sScreenWidth; 139 video_move_text_cursor(x, y); 140 } 141 142 143 void 144 Console::SetCursorVisible(bool visible) 145 { 146 if (visible) 147 video_show_text_cursor(); 148 else 149 video_hide_text_cursor(); 150 } 151 152 153 void 154 Console::SetColors(int32 foreground, int32 background) 155 { 156 sColor = (background & 0xf) << 12 | (foreground & 0xf) << 8; 157 } 158 159 160 int 161 console_wait_for_key(void) 162 { 163 union key key = wait_for_key(); 164 165 if (key.code.ascii == 0) { 166 switch (key.code.bios) { 167 case BIOS_KEY_UP: 168 return TEXT_CONSOLE_KEY_UP; 169 case BIOS_KEY_DOWN: 170 return TEXT_CONSOLE_KEY_DOWN; 171 case BIOS_KEY_LEFT: 172 return TEXT_CONSOLE_KEY_LEFT; 173 case BIOS_KEY_RIGHT: 174 return TEXT_CONSOLE_KEY_RIGHT; 175 case BIOS_KEY_PAGE_UP: 176 return TEXT_CONSOLE_KEY_PAGE_UP; 177 case BIOS_KEY_PAGE_DOWN: 178 return TEXT_CONSOLE_KEY_PAGE_DOWN; 179 case BIOS_KEY_HOME: 180 return TEXT_CONSOLE_KEY_HOME; 181 case BIOS_KEY_END: 182 return TEXT_CONSOLE_KEY_END; 183 default: 184 return 0; 185 } 186 } else 187 return key.code.ascii; 188 } 189 190 191 status_t 192 console_init(void) 193 { 194 // ToDo: make screen size changeable via stage2_args 195 196 gConsoleNode = &sConsole; 197 198 console_clear_screen(); 199 200 // enable stdio functionality 201 stdin = (FILE *)&sConsole; 202 stdout = stderr = (FILE *)&sConsole; 203 204 return B_OK; 205 } 206 207