tty.c (4490B)
1 /* 2 * core/tty.c 3 * 4 * Copyright (C) 2009 stateless 5 */ 6 7 #include <tty.h> 8 #include <x86.h> 9 #include <keyboard.h> 10 #include <ctype.h> 11 #include <tss.h> 12 #include <string.h> 13 #include <syscall.h> 14 15 unsigned short int cursor_x = 0; 16 unsigned short int cursor_y = 0; 17 volatile unsigned char *framebuffer = (unsigned char *)FRAMEBUFFER_ADDR; 18 enum vga_colours curr_col = 0; 19 20 static void *tty_sleep_chan = (void *) & tty_sleep_chan; 21 static void *tty_suspend_chan = (void *) & tty_suspend_chan; 22 static struct task_t *ctrl_tty_task = NULL; 23 24 void 25 ccurr_col(enum vga_colours bg, enum vga_colours fg) 26 { 27 uint32_t state; 28 29 save_flags(&state); 30 cli(); 31 curr_col = 0; 32 curr_col |= fg; 33 curr_col = curr_col | (bg << 4); 34 load_flags(state); 35 } 36 37 void 38 clear_scr(void) 39 { 40 uint32_t state; 41 int y, x; 42 43 save_flags(&state); 44 cli(); 45 for (y = 0; y < BUF_HEIGHT; ++y) { 46 for (x = 0; x < BUF_WIDTH; ++x) { 47 framebuffer[((y * BUF_WIDTH + x) << 1)] = 0; 48 framebuffer[((y * BUF_WIDTH + x) << 1) + 1] = curr_col; 49 } 50 } 51 gotoxy(0, 0); 52 load_flags(state); 53 } 54 55 void 56 gotoxy(unsigned short newy, unsigned short newx) 57 { 58 uint32_t state; 59 60 save_flags(&state); 61 cli(); 62 cursor_x = newx; 63 cursor_y = newy; 64 load_flags(state); 65 } 66 67 void 68 erase_line(int y) 69 { 70 int x; 71 uint32_t state; 72 73 save_flags(&state); 74 cli(); 75 for (x = 0; x < BUF_WIDTH; ++x) { 76 framebuffer[((y * BUF_WIDTH + x) << 1)] = 0; 77 framebuffer[((y * BUF_WIDTH + x) << 1) + 1] = curr_col; 78 } 79 load_flags(state); 80 } 81 82 void 83 scroll(void) 84 { 85 int y, x; 86 volatile unsigned char *dst, *src; 87 uint32_t state; 88 89 save_flags(&state); 90 cli(); 91 if (cursor_y >= BUF_HEIGHT) { 92 for (y = 0; y < BUF_HEIGHT - 1; ++y) { 93 erase_line(y); 94 dst = framebuffer + ((y * BUF_WIDTH) << 1); 95 src = framebuffer + (((y + 1) * BUF_WIDTH) << 1); 96 for (x = 0; x < BUF_WIDTH * 2; ++x) 97 *(dst + x) = *(src + x); 98 } 99 erase_line(BUF_HEIGHT - 1); 100 gotoxy(BUF_HEIGHT - 1, 0); 101 } 102 load_flags(state); 103 } 104 105 void 106 blink(void) 107 { 108 uint32_t state; 109 uint8_t temp; 110 111 save_flags(&state); 112 cli(); 113 outb(0x3d4, 0xa); 114 temp = inb(0x3d5); 115 temp ^= 0x20; 116 outb(0x3d5, temp); 117 load_flags(state); 118 } 119 120 int 121 tty_putchar(int c) 122 { 123 uint32_t state; 124 volatile unsigned char *ptr; 125 126 save_flags(&state); 127 cli(); 128 if (c == '\b' && cursor_x) { 129 gotoxy(cursor_y, cursor_x - 1); 130 } else if (c == '\n') { 131 gotoxy(cursor_y + 1, 0); 132 } else if (c == '\r') { 133 gotoxy(cursor_y, 0); 134 } else if (c == '\t') { 135 gotoxy(cursor_y, cursor_x + 4); 136 } else { 137 ptr = framebuffer + ((cursor_y * BUF_WIDTH + cursor_x) << 1); 138 *ptr = c & 0xff; 139 *(ptr + 1) = curr_col & 0xff; 140 gotoxy(cursor_y, cursor_x + 1); 141 } 142 if (cursor_x >= BUF_WIDTH) 143 gotoxy(cursor_y + 1, 0); 144 scroll(); 145 load_flags(state); 146 return c; 147 } 148 149 void 150 update_cursor(uint16_t row, uint16_t col) 151 { 152 uint32_t state; 153 uint16_t position = (row * 80) + col; 154 155 save_flags(&state); 156 cli(); 157 outb(0x3d4, 0xf); 158 outb(0x3d5, (position & 0xff)); 159 outb(0x3d4, 0xe); 160 outb(0x3d5, ((position >> 8) & 0xff)); 161 load_flags(state); 162 } 163 164 void * 165 tty_get_sleep_chan(void) 166 { 167 return tty_sleep_chan; 168 } 169 170 void 171 attach_tty(struct task_t *ctask) 172 { 173 if (strcmp(ctask->name, "idle")) 174 ctrl_tty_task = ctask; 175 } 176 177 int 178 is_tty_attached(void) 179 { 180 return !ctrl_tty_task ? 0 : 1; 181 } 182 183 int 184 is_ctrl_task(struct task_t *ctask) 185 { 186 return ctrl_tty_task == ctask; 187 } 188 189 void 190 tty_suspend(void) 191 { 192 sys_suspend_task(tty_suspend_chan); 193 } 194 195 void 196 tty_resume(void) 197 { 198 sys_resume_task(tty_suspend_chan); 199 } 200 201 struct task_t * 202 tty_get_ctrl_task(void) { 203 return ctrl_tty_task; 204 } 205 206 ssize_t 207 tty_read(void *buf, size_t count) 208 { 209 int c; 210 size_t i = 0; 211 char *p; 212 volatile unsigned char *ptr; 213 214 p = buf; 215 while (i < count) { 216 do { 217 if (!is_ctrl_task(curr_proc)) 218 tty_suspend(); 219 again: 220 sys_suspend_task(tty_sleep_chan); 221 c = kbd_getchar(); 222 if (c != -1 && (isprint(c) || c == 127)) { 223 if (c == 127) { 224 if (p == buf) 225 goto again; 226 gotoxy(cursor_y, cursor_x - 1); 227 update_cursor(cursor_y, cursor_x); 228 *--p = '\0'; 229 c = ' '; 230 ptr = framebuffer + 231 ((cursor_y * BUF_WIDTH + cursor_x) << 1); 232 *ptr = c & 0xff; 233 *(ptr + 1) = curr_col & 0xff; 234 goto again; 235 } 236 if (*p != '\n') 237 update_cursor(cursor_y, cursor_x + 1); 238 tty_putchar(c); 239 *p = c; 240 if (*p == '\n') { 241 /* HACK */ 242 curr_proc->esp = curr_proc->old_esp; 243 return i + 1; 244 } 245 ++p; 246 break; 247 } 248 } while (1); 249 ++i; 250 } 251 /* HACK */ 252 curr_proc->esp = curr_proc->old_esp; 253 return count; 254 } 255 256 int 257 raw_tty_getchar(void) 258 { 259 int c; 260 261 do { 262 c = kbd_getchar(); 263 if (c != -1) 264 return c; 265 } while (1); 266 } 267