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
30static uint16 *sOrigin;
31static isa_module_info *sISA;
32
33
34static int
35text_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
58static int
59text_uninit(void)
60{
61	put_module(B_ISA_MODULE_NAME);
62
63	// ToDo: unmap video memory (someday)
64	return 0;
65}
66
67
68static status_t
69get_size(int32 *width, int32 *height)
70{
71	*width = COLUMNS;
72	*height = LINES;
73	return 0;
74}
75
76
77static void
78move_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
94static void
95put_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
103static void
104fill_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
118static void
119blit(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
130static void
131clear(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
141static status_t
142text_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
156static 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
170module_info *modules[] = {
171	(module_info *)&sVGATextConsole,
172	NULL
173};
174