30 |
#define DEBUG_VGA 0 |
#define DEBUG_VGA 0 |
31 |
|
|
32 |
#define VGA_WIDTH 640 |
#define VGA_WIDTH 640 |
33 |
#define VGA_HEIGHT 480 |
#define VGA_HEIGHT 350 |
34 |
#define CHAR_WIDTH 8 |
#define CHAR_WIDTH 8 |
35 |
#define CHAR_HEIGHT 16 |
#define CHAR_HEIGHT 16 |
36 |
#define TEXT_WIDTH (VGA_WIDTH / CHAR_WIDTH) |
#define TEXT_WIDTH (VGA_WIDTH / CHAR_WIDTH) |
37 |
#define TEXT_HEIGHT (VGA_HEIGHT / CHAR_HEIGHT) |
#define TEXT_HEIGHT (VGA_HEIGHT / CHAR_HEIGHT) |
38 |
#define VGA_MEM ((unsigned char *) 0xA0000) |
#define VGA_MEM ((unsigned char *) 0xA0000) |
39 |
|
#define PAGE_OFFSET(x) ((x) * (VGA_WIDTH * VGA_HEIGHT / 8)) |
40 |
|
|
41 |
#define DEFAULT_FG_COLOR 0xa |
#define DEFAULT_FG_COLOR 0xa |
42 |
#define DEFAULT_BG_COLOR 0x0 |
#define DEFAULT_BG_COLOR 0x0 |
65 |
static struct colored_char text_buf[TEXT_WIDTH * TEXT_HEIGHT]; |
static struct colored_char text_buf[TEXT_WIDTH * TEXT_HEIGHT]; |
66 |
static unsigned char *vga_font; |
static unsigned char *vga_font; |
67 |
static unsigned char saved_map_mask; |
static unsigned char saved_map_mask; |
68 |
|
static int page = 0; |
69 |
|
|
70 |
/* Read a byte from a port. */ |
/* Read a byte from a port. */ |
71 |
static inline unsigned char |
static inline unsigned char |
91 |
#define SEQUENCER_DATA_PORT 0x3C5 |
#define SEQUENCER_DATA_PORT 0x3C5 |
92 |
#define MAP_MASK_REGISTER 0x02 |
#define MAP_MASK_REGISTER 0x02 |
93 |
|
|
94 |
|
#define CRTC_ADDR_PORT 0x3D4 |
95 |
|
#define CRTC_DATA_PORT 0x3D5 |
96 |
|
#define START_ADDR_HIGH_REGISTER 0x0C |
97 |
|
#define START_ADDR_LOW_REGISTER 0x0D |
98 |
|
|
99 |
|
#define GRAPHICS_ADDR_PORT 0x3CE |
100 |
|
#define GRAPHICS_DATA_PORT 0x3CF |
101 |
|
#define READ_MAP_REGISTER 0x04 |
102 |
|
|
103 |
|
#define INPUT_STATUS1_REGISTER 0x3DA |
104 |
|
#define INPUT_STATUS1_VERTR_BIT 0x08 |
105 |
|
|
106 |
|
static inline void |
107 |
|
wait_vretrace (void) |
108 |
|
{ |
109 |
|
/* Wait until there is a vertical retrace. */ |
110 |
|
while (! (inb (INPUT_STATUS1_REGISTER) & INPUT_STATUS1_VERTR_BIT)); |
111 |
|
} |
112 |
|
|
113 |
/* Get Map Mask Register. */ |
/* Get Map Mask Register. */ |
114 |
static unsigned char |
static unsigned char |
115 |
get_map_mask (void) |
get_map_mask (void) |
141 |
outb (SEQUENCER_ADDR_PORT, old_addr); |
outb (SEQUENCER_ADDR_PORT, old_addr); |
142 |
} |
} |
143 |
|
|
144 |
|
/* Set Read Map Register. */ |
145 |
|
static void |
146 |
|
set_read_map (unsigned char map) |
147 |
|
{ |
148 |
|
unsigned char old_addr; |
149 |
|
|
150 |
|
old_addr = inb (GRAPHICS_ADDR_PORT); |
151 |
|
|
152 |
|
outb (GRAPHICS_ADDR_PORT, READ_MAP_REGISTER); |
153 |
|
outb (GRAPHICS_DATA_PORT, map); |
154 |
|
|
155 |
|
outb (GRAPHICS_ADDR_PORT, old_addr); |
156 |
|
} |
157 |
|
|
158 |
|
/* Set start address. */ |
159 |
|
static void |
160 |
|
set_start_address (unsigned int start) |
161 |
|
{ |
162 |
|
unsigned char old_addr; |
163 |
|
|
164 |
|
old_addr = inb (CRTC_ADDR_PORT); |
165 |
|
|
166 |
|
outb (CRTC_ADDR_PORT, START_ADDR_LOW_REGISTER); |
167 |
|
outb (CRTC_DATA_PORT, start & 0xFF); |
168 |
|
|
169 |
|
outb (CRTC_ADDR_PORT, START_ADDR_HIGH_REGISTER); |
170 |
|
outb (CRTC_DATA_PORT, start >> 8); |
171 |
|
|
172 |
|
outb (CRTC_ADDR_PORT, old_addr); |
173 |
|
} |
174 |
|
|
175 |
static grub_err_t |
static grub_err_t |
176 |
grub_vga_init (void) |
grub_vga_init (void) |
177 |
{ |
{ |
178 |
vga_font = grub_vga_get_font (); |
vga_font = grub_vga_get_font (); |
179 |
text_mode = grub_vga_set_mode (0x12); |
text_mode = grub_vga_set_mode (0x10); |
180 |
cursor_state = 1; |
cursor_state = 1; |
181 |
fg_color = DEFAULT_FG_COLOR; |
fg_color = DEFAULT_FG_COLOR; |
182 |
bg_color = DEFAULT_BG_COLOR; |
bg_color = DEFAULT_BG_COLOR; |
183 |
saved_map_mask = get_map_mask (); |
saved_map_mask = get_map_mask (); |
184 |
set_map_mask (0x0f); |
set_map_mask (0x0f); |
185 |
|
set_start_address (PAGE_OFFSET (page)); |
186 |
|
|
187 |
return GRUB_ERR_NONE; |
return GRUB_ERR_NONE; |
188 |
} |
} |
269 |
static int |
static int |
270 |
check_vga_mem (void *p) |
check_vga_mem (void *p) |
271 |
{ |
{ |
272 |
return p >= (void *) VGA_MEM && p <= (void *) (VGA_MEM + VGA_WIDTH * VGA_HEIGHT / 8); |
return (p >= (void *) (VGA_MEM + PAGE_OFFSET (page)) |
273 |
|
&& p <= (void *) (VGA_MEM + PAGE_OFFSET (page) |
274 |
|
+ VGA_WIDTH * VGA_HEIGHT / 8)); |
275 |
} |
} |
276 |
|
|
277 |
static void |
static void |
280 |
struct colored_char *p = text_buf + xpos + ypos * TEXT_WIDTH; |
struct colored_char *p = text_buf + xpos + ypos * TEXT_WIDTH; |
281 |
unsigned char bitmap[32]; |
unsigned char bitmap[32]; |
282 |
unsigned width; |
unsigned width; |
283 |
unsigned char *mem_base = VGA_MEM + xpos + ypos * CHAR_HEIGHT * TEXT_WIDTH; |
unsigned char *mem_base; |
284 |
unsigned plane; |
unsigned plane; |
285 |
|
|
286 |
mem_base -= p->index; |
mem_base = (VGA_MEM + xpos + |
287 |
|
ypos * CHAR_HEIGHT * TEXT_WIDTH + PAGE_OFFSET (page)) - p->index; |
288 |
p -= p->index; |
p -= p->index; |
289 |
|
|
290 |
if (! get_vga_glyph (p->code, bitmap, &width)) |
if (! get_vga_glyph (p->code, bitmap, &width)) |
324 |
static void |
static void |
325 |
write_cursor (void) |
write_cursor (void) |
326 |
{ |
{ |
327 |
unsigned char *mem = (VGA_MEM + xpos |
unsigned char *mem = (VGA_MEM + PAGE_OFFSET (page) + xpos |
328 |
+ (ypos * CHAR_HEIGHT + CHAR_HEIGHT - 3) * TEXT_WIDTH); |
+ (ypos * CHAR_HEIGHT + CHAR_HEIGHT - 3) * TEXT_WIDTH); |
329 |
if (check_vga_mem (mem)) |
if (check_vga_mem (mem)) |
330 |
*mem = 0xff; |
*mem = 0xff; |
340 |
unsigned i; |
unsigned i; |
341 |
unsigned plane; |
unsigned plane; |
342 |
|
|
343 |
|
/* Do all the work in the other page. */ |
344 |
grub_memmove (text_buf, text_buf + TEXT_WIDTH, |
grub_memmove (text_buf, text_buf + TEXT_WIDTH, |
345 |
sizeof (struct colored_char) * TEXT_WIDTH * (TEXT_HEIGHT - 1)); |
sizeof (struct colored_char) * TEXT_WIDTH * (TEXT_HEIGHT - 1)); |
346 |
|
|
353 |
text_buf[i].index = 0; |
text_buf[i].index = 0; |
354 |
} |
} |
355 |
|
|
356 |
for (plane = 0x1; plane <= 0x8; plane <<= 1) |
for (plane = 1; plane <= 4; plane++) |
357 |
{ |
{ |
358 |
set_map_mask (plane); |
set_read_map (plane); |
359 |
grub_memmove (VGA_MEM, VGA_MEM + VGA_WIDTH * CHAR_HEIGHT / 8, |
set_map_mask (1 << plane); |
360 |
|
grub_memmove (VGA_MEM + PAGE_OFFSET (1 - page), VGA_MEM |
361 |
|
+ PAGE_OFFSET (page) + VGA_WIDTH * CHAR_HEIGHT / 8, |
362 |
VGA_WIDTH * (VGA_HEIGHT - CHAR_HEIGHT) / 8); |
VGA_WIDTH * (VGA_HEIGHT - CHAR_HEIGHT) / 8); |
363 |
} |
} |
364 |
|
|
365 |
set_map_mask (0x0f); |
set_map_mask (0x0f); |
366 |
grub_memset (VGA_MEM + VGA_WIDTH * (VGA_HEIGHT - CHAR_HEIGHT) / 8, 0, |
grub_memset (VGA_MEM + PAGE_OFFSET (1 - page) |
367 |
|
+ VGA_WIDTH * (VGA_HEIGHT - CHAR_HEIGHT) / 8, 0, |
368 |
VGA_WIDTH * CHAR_HEIGHT / 8); |
VGA_WIDTH * CHAR_HEIGHT / 8); |
369 |
|
|
370 |
|
/* Activate the other page. */ |
371 |
|
page = 1 - page; |
372 |
|
wait_vretrace (); |
373 |
|
set_start_address (PAGE_OFFSET (page)); |
374 |
} |
} |
375 |
|
|
376 |
static void |
static void |
398 |
break; |
break; |
399 |
|
|
400 |
case '\n': |
case '\n': |
401 |
if (ypos >= TEXT_HEIGHT) |
if (ypos >= TEXT_HEIGHT - 1) |
402 |
scroll_up (); |
scroll_up (); |
403 |
else |
else |
404 |
ypos++; |
ypos++; |
448 |
{ |
{ |
449 |
xpos = 0; |
xpos = 0; |
450 |
|
|
451 |
if (ypos >= TEXT_HEIGHT) |
if (ypos >= TEXT_HEIGHT - 1) |
452 |
scroll_up (); |
scroll_up (); |
453 |
else |
else |
454 |
ypos++; |
ypos++; |
503 |
{ |
{ |
504 |
unsigned i; |
unsigned i; |
505 |
|
|
506 |
|
wait_vretrace (); |
507 |
for (i = 0; i < TEXT_WIDTH * TEXT_HEIGHT; i++) |
for (i = 0; i < TEXT_WIDTH * TEXT_HEIGHT; i++) |
508 |
{ |
{ |
509 |
text_buf[i].code = ' '; |
text_buf[i].code = ' '; |
513 |
text_buf[i].index = 0; |
text_buf[i].index = 0; |
514 |
} |
} |
515 |
|
|
516 |
grub_memset (VGA_MEM, 0, VGA_WIDTH * VGA_HEIGHT / 8); |
grub_memset (VGA_MEM + PAGE_OFFSET (page), 0, VGA_WIDTH * VGA_HEIGHT / 8); |
517 |
|
|
518 |
xpos = ypos = 0; |
xpos = ypos = 0; |
519 |
} |
} |