]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
8f6c56a5 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
1c79356b | 5 | * |
8f6c56a5 A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
14 | * | |
15 | * Please obtain a copy of the License at | |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
23 | * Please see the License for the specific language governing rights and | |
8ad349bb | 24 | * limitations under the License. |
8f6c56a5 A |
25 | * |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | |
1c79356b A |
27 | */ |
28 | ||
29 | /* | |
30 | * text_console.c | |
31 | * | |
32 | * VGA text console support. | |
33 | */ | |
34 | ||
4452a7af | 35 | #include <architecture/i386/pio.h> |
55e303ae | 36 | #include <console/video_console.h> |
91447636 | 37 | #include "text_console.h" |
1c79356b A |
38 | |
39 | /* | |
40 | * Macros and typedefs. | |
41 | */ | |
42 | typedef short csrpos_t; /* cursor position, ONE_SPACE bytes per char */ | |
43 | ||
44 | #define ONE_SPACE 2 /* bytes per character */ | |
45 | #define ONE_LINE (vga_cols * ONE_SPACE) /* number of bytes in line */ | |
46 | #define ONE_PAGE (vga_rows * ONE_LINE) /* number of bytes in page */ | |
47 | #define SPACE_CHAR 0x20 | |
48 | ||
49 | #define VGA_FB_START 0x0b8000 | |
50 | #define VGA_FB_SIZE 0x8000 | |
51 | #define VGA_IDX_REG 0x3d4 | |
52 | #define VGA_IO_REG 0x3d5 | |
53 | ||
54 | /* | |
55 | * Commands sent to graphics adapter. | |
56 | */ | |
91447636 | 57 | #define VGA_C_START 0x0a /* cursor start position, on/off bit */ |
1c79356b A |
58 | #define VGA_C_LOW 0x0f /* return low byte of cursor addr */ |
59 | #define VGA_C_HIGH 0x0e /* high byte */ | |
60 | ||
61 | /* | |
62 | * Attributes for character sent to display. | |
63 | */ | |
64 | #define VGA_ATTR_NORMAL 0x07 | |
65 | #define VGA_ATTR_REVERSE 0x70 | |
66 | ||
91447636 A |
67 | /* |
68 | * Cursor Start Register bit fields. | |
69 | */ | |
70 | #define VGA_CURSOR_CS 0x1F | |
71 | #define VGA_CURSOR_ON 0x20 | |
72 | ||
1c79356b A |
73 | /* |
74 | * Convert from XY coordinate to a location in display memory. | |
75 | */ | |
76 | #define XY_TO_CSRPOS(x, y) (((y) * vga_cols + (x)) * ONE_SPACE) | |
77 | ||
78 | /* | |
79 | * Globals. | |
80 | */ | |
91447636 A |
81 | static short vga_idx_reg = 0; /* location of VGA index register */ |
82 | static short vga_io_reg = 0; /* location of VGA data register */ | |
83 | static short vga_cols = 80; /* number of columns */ | |
84 | static short vga_rows = 25; /* number of rows */ | |
85 | static char vga_attr = 0; /* current character attribute */ | |
86 | static char vga_attr_rev = 0; /* current reverse attribute */ | |
87 | static char vga_cursor_start = 0; /* cached cursor start scan line */ | |
88 | static char * vram_start = 0; /* VM start of VGA frame buffer */ | |
1c79356b A |
89 | |
90 | /* | |
91 | * Functions in kdasm.s. | |
92 | */ | |
55e303ae A |
93 | extern void kd_slmwd(unsigned char * pos, int count, unsigned short val); |
94 | extern void kd_slmscu(unsigned char * from, unsigned char * to, int count); | |
95 | extern void kd_slmscd(unsigned char * from, unsigned char * to, int count); | |
1c79356b A |
96 | |
97 | /* | |
98 | * move_up | |
99 | * | |
100 | * Block move up for VGA. | |
101 | */ | |
102 | static void | |
103 | move_up( csrpos_t from, | |
104 | csrpos_t to, | |
105 | int count) | |
106 | { | |
4452a7af | 107 | if (vram_start == 0) return; |
1c79356b A |
108 | kd_slmscu( vram_start + from, vram_start + to, count ); |
109 | } | |
110 | ||
111 | /* | |
112 | * move_down | |
113 | * | |
114 | * Block move down for VGA. | |
115 | */ | |
116 | static void | |
117 | move_down( csrpos_t from, | |
118 | csrpos_t to, | |
119 | int count ) | |
120 | { | |
4452a7af | 121 | if (vram_start == 0) return; |
1c79356b A |
122 | kd_slmscd( vram_start + from, vram_start + to, count ); |
123 | } | |
124 | ||
125 | /* | |
126 | * clear_block | |
127 | * | |
128 | * Fast clear for VGA. | |
129 | */ | |
130 | static void | |
131 | clear_block( csrpos_t start, | |
132 | int size, | |
133 | char attr) | |
134 | { | |
4452a7af | 135 | if (vram_start == 0) return; |
1c79356b A |
136 | kd_slmwd( vram_start + start, size, |
137 | ((unsigned short) attr << 8) + SPACE_CHAR); | |
138 | } | |
139 | ||
140 | /* | |
141 | * set_cursor_position | |
142 | * | |
143 | * This function sets the hardware cursor position | |
144 | * on the screen. | |
145 | */ | |
146 | static void | |
147 | set_cursor_position( csrpos_t newpos ) | |
148 | { | |
149 | short curpos; /* position, not scaled for attribute byte */ | |
150 | ||
151 | curpos = newpos / ONE_SPACE; | |
152 | ||
153 | outb(vga_idx_reg, VGA_C_HIGH); | |
55e303ae | 154 | outb(vga_io_reg, (unsigned char)(curpos >> 8)); |
1c79356b A |
155 | |
156 | outb(vga_idx_reg, VGA_C_LOW); | |
55e303ae | 157 | outb(vga_io_reg, (unsigned char)(curpos & 0xff)); |
1c79356b A |
158 | } |
159 | ||
91447636 A |
160 | /* |
161 | * set_cursor_enable | |
162 | * | |
163 | * Allow the cursor to be turned on or off. | |
164 | */ | |
165 | static void | |
166 | set_cursor_enable( boolean_t enable ) | |
167 | { | |
168 | outb(vga_idx_reg, VGA_C_START); | |
169 | outb(vga_io_reg, vga_cursor_start | | |
170 | (enable == TRUE ? VGA_CURSOR_ON : 0)); | |
171 | } | |
172 | ||
1c79356b A |
173 | /* |
174 | * display_char | |
175 | * | |
176 | * Display attributed character for VGA (mode 3). | |
177 | */ | |
178 | static void | |
179 | display_char( csrpos_t pos, /* where to put it */ | |
180 | char ch, /* the character */ | |
181 | char attr ) /* its attribute */ | |
182 | { | |
4452a7af | 183 | if (vram_start == 0) return; |
1c79356b A |
184 | *(vram_start + pos) = ch; |
185 | *(vram_start + pos + 1) = attr; | |
186 | } | |
187 | ||
188 | /* | |
189 | * vga_init | |
190 | * | |
191 | * Initialize the VGA text console. | |
192 | */ | |
193 | static void | |
194 | vga_init(int cols, int rows, unsigned char * addr) | |
195 | { | |
196 | vram_start = addr; | |
197 | vga_idx_reg = VGA_IDX_REG; | |
198 | vga_io_reg = VGA_IO_REG; | |
199 | vga_rows = rows; | |
200 | vga_cols = cols; | |
201 | vga_attr = VGA_ATTR_NORMAL; | |
202 | vga_attr_rev = VGA_ATTR_REVERSE; | |
203 | ||
91447636 A |
204 | /* cache cursor start position */ |
205 | outb(vga_idx_reg, VGA_C_START); | |
206 | vga_cursor_start = inb(vga_io_reg) & VGA_CURSOR_CS; | |
207 | ||
208 | /* defaults to a hidden hw cursor */ | |
209 | set_cursor_enable( FALSE ); | |
1c79356b A |
210 | } |
211 | ||
212 | /* | |
55e303ae | 213 | * tc_scroll_up |
1c79356b A |
214 | * |
215 | * Scroll the screen up 'n' character lines. | |
216 | */ | |
217 | void | |
91447636 | 218 | tc_scroll_up( int lines, __unused int top, __unused int bottom ) |
1c79356b A |
219 | { |
220 | csrpos_t to; | |
221 | csrpos_t from; | |
222 | int size; | |
223 | ||
224 | /* scroll up */ | |
225 | to = 0; | |
226 | from = ONE_LINE * lines; | |
227 | size = ( ONE_PAGE - ( ONE_LINE * lines ) ) / ONE_SPACE; | |
228 | move_up(from, to, size); | |
229 | ||
230 | /* clear bottom line */ | |
231 | to = ( ( vga_rows - lines) * ONE_LINE ); | |
232 | size = ( ONE_LINE * lines ) / ONE_SPACE; | |
233 | clear_block(to, size, vga_attr); | |
234 | } | |
235 | ||
236 | /* | |
55e303ae | 237 | * tc_scroll_down |
1c79356b A |
238 | * |
239 | * Scrolls the screen down 'n' character lines. | |
240 | */ | |
241 | void | |
91447636 | 242 | tc_scroll_down( int lines, __unused int top, __unused int bottom ) |
1c79356b A |
243 | { |
244 | csrpos_t to; | |
245 | csrpos_t from; | |
246 | int size; | |
247 | ||
248 | /* move down */ | |
249 | to = ONE_PAGE - ONE_SPACE; | |
250 | from = ONE_PAGE - ( ONE_LINE * lines ) - ONE_SPACE; | |
251 | size = ( ONE_PAGE - ( ONE_LINE * lines ) ) / ONE_SPACE; | |
252 | move_down(from, to, size); | |
253 | ||
254 | /* clear top line */ | |
255 | to = 0; | |
256 | size = ( ONE_LINE * lines ) / ONE_SPACE; | |
257 | clear_block(to, size, vga_attr); | |
258 | } | |
259 | ||
260 | /* Default colors for 16-color palette */ | |
261 | enum { | |
262 | kVGAColorBlack = 0, | |
263 | kVGAColorBlue, | |
264 | kVGAColorGreen, | |
265 | kVGAColorCyan, | |
266 | kVGAColorRed, | |
267 | kVGAColorMagenta, | |
268 | kVGAColorBrown, | |
269 | kVGAColorWhite, | |
270 | kVGAColorGray, | |
271 | kVGAColorLightBlue, | |
272 | kVGAColorLightGreen, | |
273 | kVGAColorLightCyan, | |
274 | kVGAColorLightRed, | |
275 | kVGAColorLightMagenta, | |
276 | kVGAColorLightBrown, | |
277 | kVGAColorBrightWhite | |
278 | }; | |
279 | ||
280 | /* | |
281 | * tc_update_color | |
282 | * | |
283 | * Update the foreground / background color. | |
284 | */ | |
285 | void | |
286 | tc_update_color( int color, int fore ) | |
287 | { | |
288 | unsigned char mask_on, mask_off; | |
289 | ||
290 | switch ( color ) | |
291 | { | |
292 | case 1: mask_on = kVGAColorRed; break; | |
293 | case 3: mask_on = kVGAColorLightBrown; break; | |
294 | case 4: mask_on = kVGAColorBlue; break; | |
295 | case 6: mask_on = kVGAColorCyan; break; | |
296 | default: mask_on = color; break; | |
297 | } | |
298 | ||
299 | if ( fore ) | |
300 | { | |
301 | mask_off = 0x0f; | |
302 | } | |
303 | else | |
304 | { | |
305 | mask_off = 0xf0; | |
306 | mask_on <<= 4; | |
307 | } | |
308 | ||
309 | vga_attr = (vga_attr & ~mask_off) | mask_on; | |
310 | ||
311 | vga_attr_rev = ( ((vga_attr << 4) & 0xf0) | | |
312 | ((vga_attr >> 4) & 0x0f) ); | |
313 | } | |
314 | ||
315 | /* | |
316 | * tc_show_cursor | |
317 | * | |
318 | * Show the hardware cursor. | |
319 | */ | |
320 | void | |
321 | tc_show_cursor( int x, int y ) | |
322 | { | |
323 | set_cursor_position( XY_TO_CSRPOS(x, y) ); | |
91447636 | 324 | set_cursor_enable( TRUE ); |
1c79356b A |
325 | } |
326 | ||
327 | /* | |
328 | * tc_hide_cursor | |
329 | * | |
330 | * Hide the hardware cursor. | |
331 | */ | |
332 | void | |
91447636 | 333 | tc_hide_cursor( __unused int x, __unused int y ) |
1c79356b | 334 | { |
91447636 | 335 | set_cursor_enable( FALSE ); |
1c79356b A |
336 | } |
337 | ||
338 | /* | |
339 | * tc_clear_screen | |
340 | * | |
341 | * Clear the entire screen, or a portion of the screen | |
342 | * relative to the current cursor position. | |
343 | */ | |
344 | void | |
91447636 A |
345 | tc_clear_screen(int x, int y, __unused int top, __unused int bottom, |
346 | int operation) | |
1c79356b A |
347 | { |
348 | csrpos_t start; | |
349 | int count; | |
350 | ||
351 | switch ( operation ) | |
352 | { | |
353 | case 0: /* To end of screen */ | |
354 | start = XY_TO_CSRPOS(x, y); | |
355 | count = ONE_PAGE - start; | |
356 | break; | |
357 | case 1: /* To start of screen */ | |
358 | start = 0; | |
359 | count = XY_TO_CSRPOS(x, y) + ONE_SPACE; | |
360 | break; | |
361 | default: | |
362 | case 2: /* Whole screen */ | |
363 | start = 0; | |
364 | count = ONE_PAGE; | |
365 | break; | |
366 | } | |
367 | clear_block(start, count, vga_attr); | |
368 | } | |
369 | ||
370 | /* | |
55e303ae | 371 | * tc_paint_char |
1c79356b A |
372 | * |
373 | * Display a character on screen with the given coordinates, | |
374 | * and attributes. | |
375 | */ | |
376 | void | |
91447636 A |
377 | tc_paint_char(int x, int y, unsigned char ch, int attrs, |
378 | __unused unsigned char ch_previous, __unused int attrs_previous) | |
1c79356b A |
379 | { |
380 | char my_attr = vga_attr; | |
381 | ||
382 | if ( attrs & 4 ) my_attr = vga_attr_rev; | |
383 | ||
384 | display_char( XY_TO_CSRPOS(x, y), ch, vga_attr ); | |
385 | } | |
386 | ||
55e303ae A |
387 | /* |
388 | * tc_enable | |
389 | * | |
390 | * Enable / disable the console. | |
391 | */ | |
392 | void | |
91447636 | 393 | tc_enable(__unused boolean_t enable) |
55e303ae A |
394 | { |
395 | ||
396 | } | |
397 | ||
1c79356b A |
398 | /* |
399 | * tc_initialize | |
400 | * | |
401 | * Must be called before any other exported functions. | |
402 | */ | |
403 | void | |
404 | tc_initialize(struct vc_info * vinfo_p) | |
405 | { | |
406 | vinfo_p->v_rows = vinfo_p->v_height; | |
407 | vinfo_p->v_columns = vinfo_p->v_width; | |
408 | ||
409 | vga_init( vinfo_p->v_columns, | |
410 | vinfo_p->v_rows, | |
411 | (unsigned char *) vinfo_p->v_baseaddr); | |
412 | } |