xref: /haiku/src/add-ons/kernel/console/vga_text/vga_text.c (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
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
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
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
69 get_size(int32 *width, int32 *height)
70 {
71 	*width = COLUMNS;
72 	*height = LINES;
73 	return 0;
74 }
75 
76 
77 static void
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
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
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
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
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
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