nuclear@0: #include nuclear@0: #include "vid.h" nuclear@35: #include "intr.h" nuclear@2: #include "asmops.h" nuclear@2: nuclear@2: /* height of our virtual console text buffer */ nuclear@12: #define VIRT_HEIGHT 200 nuclear@2: nuclear@2: /* CRTC ports */ nuclear@2: #define CRTC_ADDR 0x3d4 nuclear@2: #define CRTC_DATA 0x3d5 nuclear@2: nuclear@2: /* CRTC registers */ nuclear@2: #define CRTC_START_HIGH 0xc nuclear@2: #define CRTC_START_LOW 0xd nuclear@2: #define CRTC_CURSOR_HIGH 0xe nuclear@2: #define CRTC_CURSOR_LOW 0xf nuclear@2: nuclear@2: /* construct a character with its attributes */ nuclear@2: #define VMEM_CHAR(c, fg, bg) \ nuclear@2: ((uint16_t)(c) | (((uint16_t)(fg) & 0xf) << 8) | (((uint16_t)(bg) & 0xf) << 12)) nuclear@2: nuclear@2: static void set_start_line(int line); nuclear@0: nuclear@0: static uint16_t *vmem = (uint16_t*)0xb8000; nuclear@2: static int start_line; nuclear@0: nuclear@2: nuclear@2: void clear_scr(void) nuclear@0: { nuclear@35: int istate = get_intr_state(); nuclear@35: disable_intr(); nuclear@35: nuclear@2: memset16(vmem, VMEM_CHAR(' ', LTGRAY, BLACK), WIDTH * HEIGHT); nuclear@2: start_line = 0; nuclear@2: set_start_line(0); nuclear@2: set_cursor(0, 0); nuclear@35: nuclear@35: set_intr_state(istate); nuclear@0: } nuclear@0: nuclear@1: void set_char(char c, int x, int y, int fg, int bg) nuclear@0: { nuclear@2: vmem[(y + start_line) * WIDTH + x] = VMEM_CHAR(c, fg, bg); nuclear@2: } nuclear@2: nuclear@2: void set_cursor(int x, int y) nuclear@2: { nuclear@2: int loc; nuclear@35: int istate = get_intr_state(); nuclear@35: disable_intr(); nuclear@2: nuclear@2: if(x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) { nuclear@2: loc = 0xffff; nuclear@2: } else { nuclear@2: loc = (y + start_line) * WIDTH + x; nuclear@2: } nuclear@2: nuclear@2: outb(CRTC_CURSOR_LOW, CRTC_ADDR); nuclear@2: outb(loc, CRTC_DATA); nuclear@2: outb(CRTC_CURSOR_HIGH, CRTC_ADDR); nuclear@2: outb(loc >> 8, CRTC_DATA); nuclear@35: nuclear@35: set_intr_state(istate); nuclear@0: } nuclear@0: nuclear@1: void scroll_scr(void) nuclear@0: { nuclear@35: int new_line, istate = get_intr_state(); nuclear@35: disable_intr(); nuclear@35: nuclear@2: if(++start_line > VIRT_HEIGHT - HEIGHT) { nuclear@2: /* The bottom of the visible range reached the end of our text buffer. nuclear@2: * Copy the rest of the lines to the top and reset start_line. nuclear@2: */ nuclear@12: memcpy(vmem, vmem + start_line * WIDTH, (HEIGHT - 1) * WIDTH * 2); nuclear@2: start_line = 0; nuclear@2: } nuclear@2: nuclear@2: /* clear the next line that will be revealed by scrolling */ nuclear@35: new_line = start_line + HEIGHT - 1; nuclear@2: memset16(vmem + new_line * WIDTH, VMEM_CHAR(' ', LTGRAY, BLACK), WIDTH); nuclear@35: set_start_line(start_line); nuclear@2: nuclear@35: set_intr_state(istate); nuclear@0: } nuclear@2: nuclear@2: static void set_start_line(int line) nuclear@2: { nuclear@2: int start_addr = line * WIDTH; nuclear@2: nuclear@2: outb(CRTC_START_LOW, CRTC_ADDR); nuclear@2: outb(start_addr & 0xff, CRTC_DATA); nuclear@2: outb(CRTC_START_HIGH, CRTC_ADDR); nuclear@2: outb((start_addr >> 8) & 0xff, CRTC_DATA); nuclear@2: }