rev |
line source |
nuclear@0
|
1 #include <string.h>
|
nuclear@0
|
2 #include "vid.h"
|
nuclear@35
|
3 #include "intr.h"
|
nuclear@2
|
4 #include "asmops.h"
|
nuclear@2
|
5
|
nuclear@2
|
6 /* height of our virtual console text buffer */
|
nuclear@12
|
7 #define VIRT_HEIGHT 200
|
nuclear@2
|
8
|
nuclear@2
|
9 /* CRTC ports */
|
nuclear@2
|
10 #define CRTC_ADDR 0x3d4
|
nuclear@2
|
11 #define CRTC_DATA 0x3d5
|
nuclear@2
|
12
|
nuclear@2
|
13 /* CRTC registers */
|
nuclear@2
|
14 #define CRTC_START_HIGH 0xc
|
nuclear@2
|
15 #define CRTC_START_LOW 0xd
|
nuclear@2
|
16 #define CRTC_CURSOR_HIGH 0xe
|
nuclear@2
|
17 #define CRTC_CURSOR_LOW 0xf
|
nuclear@2
|
18
|
nuclear@2
|
19 /* construct a character with its attributes */
|
nuclear@2
|
20 #define VMEM_CHAR(c, fg, bg) \
|
nuclear@2
|
21 ((uint16_t)(c) | (((uint16_t)(fg) & 0xf) << 8) | (((uint16_t)(bg) & 0xf) << 12))
|
nuclear@2
|
22
|
nuclear@2
|
23 static void set_start_line(int line);
|
nuclear@0
|
24
|
nuclear@0
|
25 static uint16_t *vmem = (uint16_t*)0xb8000;
|
nuclear@2
|
26 static int start_line;
|
nuclear@0
|
27
|
nuclear@2
|
28
|
nuclear@2
|
29 void clear_scr(void)
|
nuclear@0
|
30 {
|
nuclear@35
|
31 int istate = get_intr_state();
|
nuclear@35
|
32 disable_intr();
|
nuclear@35
|
33
|
nuclear@2
|
34 memset16(vmem, VMEM_CHAR(' ', LTGRAY, BLACK), WIDTH * HEIGHT);
|
nuclear@2
|
35 start_line = 0;
|
nuclear@2
|
36 set_start_line(0);
|
nuclear@2
|
37 set_cursor(0, 0);
|
nuclear@35
|
38
|
nuclear@35
|
39 set_intr_state(istate);
|
nuclear@0
|
40 }
|
nuclear@0
|
41
|
nuclear@1
|
42 void set_char(char c, int x, int y, int fg, int bg)
|
nuclear@0
|
43 {
|
nuclear@2
|
44 vmem[(y + start_line) * WIDTH + x] = VMEM_CHAR(c, fg, bg);
|
nuclear@2
|
45 }
|
nuclear@2
|
46
|
nuclear@2
|
47 void set_cursor(int x, int y)
|
nuclear@2
|
48 {
|
nuclear@2
|
49 int loc;
|
nuclear@35
|
50 int istate = get_intr_state();
|
nuclear@35
|
51 disable_intr();
|
nuclear@2
|
52
|
nuclear@2
|
53 if(x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) {
|
nuclear@2
|
54 loc = 0xffff;
|
nuclear@2
|
55 } else {
|
nuclear@2
|
56 loc = (y + start_line) * WIDTH + x;
|
nuclear@2
|
57 }
|
nuclear@2
|
58
|
nuclear@2
|
59 outb(CRTC_CURSOR_LOW, CRTC_ADDR);
|
nuclear@2
|
60 outb(loc, CRTC_DATA);
|
nuclear@2
|
61 outb(CRTC_CURSOR_HIGH, CRTC_ADDR);
|
nuclear@2
|
62 outb(loc >> 8, CRTC_DATA);
|
nuclear@35
|
63
|
nuclear@35
|
64 set_intr_state(istate);
|
nuclear@0
|
65 }
|
nuclear@0
|
66
|
nuclear@1
|
67 void scroll_scr(void)
|
nuclear@0
|
68 {
|
nuclear@35
|
69 int new_line, istate = get_intr_state();
|
nuclear@35
|
70 disable_intr();
|
nuclear@35
|
71
|
nuclear@2
|
72 if(++start_line > VIRT_HEIGHT - HEIGHT) {
|
nuclear@2
|
73 /* The bottom of the visible range reached the end of our text buffer.
|
nuclear@2
|
74 * Copy the rest of the lines to the top and reset start_line.
|
nuclear@2
|
75 */
|
nuclear@12
|
76 memcpy(vmem, vmem + start_line * WIDTH, (HEIGHT - 1) * WIDTH * 2);
|
nuclear@2
|
77 start_line = 0;
|
nuclear@2
|
78 }
|
nuclear@2
|
79
|
nuclear@2
|
80 /* clear the next line that will be revealed by scrolling */
|
nuclear@35
|
81 new_line = start_line + HEIGHT - 1;
|
nuclear@2
|
82 memset16(vmem + new_line * WIDTH, VMEM_CHAR(' ', LTGRAY, BLACK), WIDTH);
|
nuclear@35
|
83 set_start_line(start_line);
|
nuclear@2
|
84
|
nuclear@35
|
85 set_intr_state(istate);
|
nuclear@0
|
86 }
|
nuclear@2
|
87
|
nuclear@2
|
88 static void set_start_line(int line)
|
nuclear@2
|
89 {
|
nuclear@2
|
90 int start_addr = line * WIDTH;
|
nuclear@2
|
91
|
nuclear@2
|
92 outb(CRTC_START_LOW, CRTC_ADDR);
|
nuclear@2
|
93 outb(start_addr & 0xff, CRTC_DATA);
|
nuclear@2
|
94 outb(CRTC_START_HIGH, CRTC_ADDR);
|
nuclear@2
|
95 outb((start_addr >> 8) & 0xff, CRTC_DATA);
|
nuclear@2
|
96 }
|