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