1 /*
2 * Copyright 2005-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
6 * Distributed under the terms of the NewOS License.
7 */
8
9
10 #include <KernelExport.h>
11 #include <Drivers.h>
12 #include <ISA.h>
13
14 #include <console.h>
15
16 #include <string.h>
17
18
19 #define SCREEN_START 0xb8000
20 #define SCREEN_END 0xc0000
21 #define LINES 25
22 #define COLUMNS 80
23
24 #define TEXT_INDEX 0x3d4
25 #define TEXT_DATA 0x3d5
26
27 #define TEXT_CURSOR_LO 0x0f
28 #define TEXT_CURSOR_HI 0x0e
29
30 static uint16 *sOrigin;
31 static isa_module_info *sISA;
32
33
34 static int
text_init(void)35 text_init(void)
36 {
37 addr_t i;
38
39 if (get_module(B_ISA_MODULE_NAME, (module_info **)&sISA) < 0) {
40 dprintf("text module_init: no isa bus found..\n");
41 return -1;
42 }
43
44 map_physical_memory("video_mem", SCREEN_START, SCREEN_END - SCREEN_START,
45 B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void *)&sOrigin);
46 dprintf("console/text: mapped vid mem to virtual address %p\n", sOrigin);
47
48 /* pre-touch all of the memory so that we dont fault while deep inside the kernel and displaying something */
49 for (i = (addr_t)sOrigin; i < (addr_t)sOrigin + (SCREEN_END - SCREEN_START);
50 i += B_PAGE_SIZE) {
51 uint16 val = *(volatile uint16 *)i;
52 *(volatile uint16 *)i = val;
53 }
54 return 0;
55 }
56
57
58 static int
text_uninit(void)59 text_uninit(void)
60 {
61 put_module(B_ISA_MODULE_NAME);
62
63 // ToDo: unmap video memory (someday)
64 return 0;
65 }
66
67
68 static status_t
get_size(int32 * width,int32 * height)69 get_size(int32 *width, int32 *height)
70 {
71 *width = COLUMNS;
72 *height = LINES;
73 return 0;
74 }
75
76
77 static void
move_cursor(int32 x,int32 y)78 move_cursor(int32 x, int32 y)
79 {
80 short int pos;
81
82 if (x < 0 || y < 0)
83 pos = LINES * COLUMNS + 1;
84 else
85 pos = y * COLUMNS + x;
86
87 sISA->write_io_8(TEXT_INDEX, TEXT_CURSOR_LO);
88 sISA->write_io_8(TEXT_DATA, (char)pos);
89 sISA->write_io_8(TEXT_INDEX, TEXT_CURSOR_HI);
90 sISA->write_io_8(TEXT_DATA, (char)(pos >> 8));
91 }
92
93
94 static void
put_glyph(int32 x,int32 y,uint8 glyph,uint8 attr)95 put_glyph(int32 x, int32 y, uint8 glyph, uint8 attr)
96 {
97 uint16 pair = ((uint16)attr << 8) | (uint16)glyph;
98 uint16 *p = sOrigin + (y * COLUMNS) + x;
99 *p = pair;
100 }
101
102
103 static void
fill_glyph(int32 x,int32 y,int32 width,int32 height,uint8 glyph,uint8 attr)104 fill_glyph(int32 x, int32 y, int32 width, int32 height, uint8 glyph, uint8 attr)
105 {
106 uint16 pair = ((uint16)attr << 8) | (uint16)glyph;
107 int32 y_limit = y + height;
108
109 while (y < y_limit) {
110 uint16 *p = sOrigin + (y * COLUMNS) + x;
111 uint16 *p_limit = p + width;
112 while (p < p_limit) *p++ = pair;
113 y++;
114 }
115 }
116
117
118 static void
blit(int32 srcx,int32 srcy,int32 width,int32 height,int32 destx,int32 desty)119 blit(int32 srcx, int32 srcy, int32 width, int32 height, int32 destx, int32 desty)
120 {
121 if ((srcx == 0) && (width == COLUMNS)) {
122 // whole lines
123 memmove(sOrigin + (desty * COLUMNS), sOrigin + (srcy * COLUMNS), height * COLUMNS * 2);
124 } else {
125 // FIXME
126 }
127 }
128
129
130 static void
clear(uint8 attr)131 clear(uint8 attr)
132 {
133 uint16 *base = (uint16 *)sOrigin;
134 uint32 i;
135
136 for (i = 0; i < COLUMNS * LINES; i++)
137 base[i] = (attr << 8) | 0x20;
138 }
139
140
141 static status_t
text_std_ops(int32 op,...)142 text_std_ops(int32 op, ...)
143 {
144 switch (op) {
145 case B_MODULE_INIT:
146 return text_init();
147 case B_MODULE_UNINIT:
148 return text_uninit();
149
150 default:
151 return B_ERROR;
152 }
153 }
154
155
156 static console_module_info sVGATextConsole = {
157 {
158 "console/vga_text/v1",
159 0,
160 text_std_ops
161 },
162 get_size,
163 move_cursor,
164 put_glyph,
165 fill_glyph,
166 blit,
167 clear,
168 };
169
170 module_info *modules[] = {
171 (module_info *)&sVGATextConsole,
172 NULL
173 };
174