cynix

x86 UNIX-like OS
git clone git://git.2f30.org/cynix
Log | Files | Refs | README | LICENSE

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