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