12 #define TEXT_ADDR ((char*)0xb8000)
14 #define CRTC_ADDR 0x3d4
15 #define CRTC_DATA 0x3d5
17 #define CRTC_REG_CURSTART 0x0a
18 #define CRTC_REG_CUREND 0x0b
19 #define CRTC_REG_START_H 0x0c
20 #define CRTC_REG_START_L 0x0d
21 #define CRTC_REG_CURLOC_H 0x0e
22 #define CRTC_REG_CURLOC_L 0x0f
24 #define VMEM_CHAR(c, attr) \
25 ((uint16_t)(c) | ((uint16_t)(attr) << 8))
27 static void scroll(void);
28 static void crtc_cursor(int x, int y);
29 static void crtc_setstart(int y);
30 static inline unsigned char crtc_read(int reg);
31 static inline void crtc_write(int reg, unsigned char val);
32 static inline void crtc_write_bits(int reg, unsigned char val, unsigned char mask);
34 extern int cursor_x, cursor_y;
35 static unsigned char txattr = 0x07;
36 static int start_line;
41 ser_open(0, 9600, SER_8N1);
47 crtc_cursor(cursor_x, cursor_y);
49 printf("curloc: %x %x\n", (unsigned int)crtc_read(CRTC_REG_CURLOC_H),
50 (unsigned int)crtc_read(CRTC_REG_CURLOC_L));
51 printf("curstart: %x\n", (unsigned int)crtc_read(CRTC_REG_CURSTART));
52 printf("curend: %x\n", (unsigned int)crtc_read(CRTC_REG_CUREND));
59 void con_show_cursor(int show)
62 unsigned char val = show ? 0 : 0x20;
64 crtc_write_bits(CRTC_REG_CURSTART, val, 0x20);
68 void con_cursor(int x, int y)
77 void con_fgcolor(int c)
79 txattr = (txattr & 0xf0) | c;
82 void con_bgcolor(int c)
84 txattr = (txattr & 0x0f) | (c << 4);
90 memset(TEXT_ADDR, 0, NCOLS * NROWS * 2);
95 cursor_x = cursor_y = 0;
100 static inline void linefeed(void)
102 if(++cursor_y >= NROWS) {
108 void con_putchar(int c)
118 crtc_cursor(cursor_x, cursor_y);
122 cursor_x = (cursor_x & 0x7) + 8;
123 if(cursor_x >= NCOLS) {
127 crtc_cursor(cursor_x, cursor_y);
131 ptr = (uint16_t*)TEXT_ADDR;
132 ptr[(cursor_y + start_line) * NCOLS + cursor_x] = VMEM_CHAR(c, txattr);
134 if(++cursor_x >= NCOLS) {
138 crtc_cursor(cursor_x, cursor_y);
147 static void scroll(void)
151 if(++start_line > VIRT_ROWS - NROWS) {
152 /* The bottom of the visible range reached the end of our text buffer.
153 * Copy the rest of the lines to the top and reset start_line.
155 memcpy(TEXT_ADDR, TEXT_ADDR + start_line * NCOLS, (NROWS - 1) * NCOLS * 2);
159 /* clear the next line that will be revealed by scrolling */
160 new_line = start_line + NROWS - 1;
161 memset16(TEXT_ADDR + new_line * NCOLS, VMEM_CHAR(' ', txattr), NCOLS);
162 crtc_setstart(start_line);
165 static void crtc_cursor(int x, int y)
169 addr = (y + start_line) * NCOLS + x;
171 crtc_write(CRTC_REG_CURLOC_L, addr);
172 crtc_write(CRTC_REG_CURLOC_H, addr >> 8);
175 static void crtc_setstart(int y)
177 unsigned int addr = y * NCOLS;
179 crtc_write(CRTC_REG_START_L, addr);
180 crtc_write(CRTC_REG_START_H, addr >> 8);
183 static inline unsigned char crtc_read(int reg)
185 outb(reg, CRTC_ADDR);
186 return inb(CRTC_DATA);
189 static inline void crtc_write(int reg, unsigned char val)
191 outb(reg, CRTC_ADDR);
192 outb(val, CRTC_DATA);
195 static inline void crtc_write_bits(int reg, unsigned char val, unsigned char mask)
198 outb(reg, CRTC_ADDR);
199 prev = inb(CRTC_DATA);
200 val = (prev & ~mask) | (val & mask);
201 outb(val, CRTC_DATA);