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 27 static uint16 *sScreenBase = (uint16 *)0xb8000; 28 static uint32 sScreenWidth = 80; 29 static uint32 sScreenHeight = 25; 30 static uint32 sScreenOffset = 0; 31 static uint16 sColor = 0x0f00; 32 33 static Console sInput, sOutput; 34 FILE *stdin, *stdout, *stderr; 35 36 37 static void 38 scroll_up() 39 { 40 memcpy(sScreenBase, sScreenBase + sScreenWidth, 41 sScreenWidth * sScreenHeight * 2 - sScreenWidth * 2); 42 sScreenOffset = (sScreenHeight - 1) * sScreenWidth; 43 44 for (uint32 i = 0; i < sScreenWidth; i++) 45 sScreenBase[sScreenOffset + i] = sColor | ' '; 46 } 47 48 49 // #pragma mark - 50 51 52 Console::Console() 53 : ConsoleNode() 54 { 55 } 56 57 58 ssize_t 59 Console::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize) 60 { 61 // don't seek in character devices 62 // not implemented (and not yet? needed) 63 return B_ERROR; 64 } 65 66 67 ssize_t 68 Console::WriteAt(void *cookie, off_t /*pos*/, const void *buffer, size_t bufferSize) 69 { 70 const char *string = (const char *)buffer; 71 72 if (gKernelArgs.frame_buffer.enabled) 73 return bufferSize; 74 75 for (uint32 i = 0; i < bufferSize; i++) { 76 if (string[0] == '\n') 77 sScreenOffset += sScreenWidth - (sScreenOffset % sScreenWidth); 78 else 79 sScreenBase[sScreenOffset++] = sColor | string[0]; 80 81 if (sScreenOffset >= sScreenWidth * sScreenHeight) 82 scroll_up(); 83 84 string++; 85 } 86 return bufferSize; 87 } 88 89 90 // #pragma mark - 91 92 93 void 94 console_clear_screen(void) 95 { 96 if (gKernelArgs.frame_buffer.enabled) 97 return; 98 99 for (uint32 i = 0; i < sScreenWidth * sScreenHeight; i++) 100 sScreenBase[i] = sColor; 101 102 // reset cursor position as well 103 sScreenOffset = 0; 104 } 105 106 107 int32 108 console_width(void) 109 { 110 return sScreenWidth; 111 } 112 113 114 int32 115 console_height(void) 116 { 117 return sScreenHeight; 118 } 119 120 121 void 122 console_set_cursor(int32 x, int32 y) 123 { 124 if (y >= (int32)sScreenHeight) 125 y = sScreenHeight - 1; 126 else if (y < 0) 127 y = 0; 128 if (x >= (int32)sScreenWidth) 129 x = sScreenWidth - 1; 130 else if (x < 0) 131 x = 0; 132 133 sScreenOffset = x + y * sScreenWidth; 134 video_move_text_cursor(x, y); 135 } 136 137 138 void 139 console_show_cursor(void) 140 { 141 video_show_text_cursor(); 142 } 143 144 145 void 146 console_hide_cursor(void) 147 { 148 video_hide_text_cursor(); 149 } 150 151 152 void 153 console_set_color(int32 foreground, int32 background) 154 { 155 sColor = (background & 0xf) << 12 | (foreground & 0xf) << 8; 156 } 157 158 159 int 160 console_wait_for_key(void) 161 { 162 union key key = wait_for_key(); 163 164 if (key.code.ascii == 0) { 165 switch (key.code.bios) { 166 case BIOS_KEY_UP: 167 return TEXT_CONSOLE_KEY_UP; 168 case BIOS_KEY_DOWN: 169 return TEXT_CONSOLE_KEY_DOWN; 170 case BIOS_KEY_LEFT: 171 return TEXT_CONSOLE_KEY_LEFT; 172 case BIOS_KEY_RIGHT: 173 return TEXT_CONSOLE_KEY_RIGHT; 174 case BIOS_KEY_PAGE_UP: 175 return TEXT_CONSOLE_KEY_PAGE_UP; 176 case BIOS_KEY_PAGE_DOWN: 177 return TEXT_CONSOLE_KEY_PAGE_DOWN; 178 case BIOS_KEY_HOME: 179 return TEXT_CONSOLE_KEY_HOME; 180 case BIOS_KEY_END: 181 return TEXT_CONSOLE_KEY_END; 182 default: 183 return 0; 184 } 185 } else 186 return key.code.ascii; 187 } 188 189 190 status_t 191 console_init(void) 192 { 193 // ToDo: make screen size changeable via stage2_args 194 195 console_clear_screen(); 196 197 // enable stdio functionality 198 stdin = (FILE *)&sInput; 199 stdout = stderr = (FILE *)&sOutput; 200 201 return B_OK; 202 } 203 204