]> git.saurik.com Git - apple/xnu.git/blob - osfmk/console/i386/text_console.c
xnu-1228.tar.gz
[apple/xnu.git] / osfmk / console / i386 / text_console.c
1 /*
2 * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 /*
30 * text_console.c
31 *
32 * VGA text console support.
33 */
34
35 #include <architecture/i386/pio.h>
36 #include <console/video_console.h>
37 #include "text_console.h"
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 */
57 #define VGA_C_START 0x0a /* cursor start position, on/off bit */
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
67 /*
68 * Cursor Start Register bit fields.
69 */
70 #define VGA_CURSOR_CS 0x1F
71 #define VGA_CURSOR_ON 0x20
72
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 */
81 static short vga_idx_reg; /* location of VGA index register */
82 static short vga_io_reg; /* 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; /* current character attribute */
86 static char vga_attr_rev; /* current reverse attribute */
87 static char vga_cursor_start; /* cached cursor start scan line */
88 static unsigned char *vram_start; /* VM start of VGA frame buffer */
89
90 /*
91 * Functions in kdasm.s.
92 */
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);
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 {
107 if (vram_start == 0) return;
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 {
121 if (vram_start == 0) return;
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 {
135 if (vram_start == 0) return;
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);
154 outb(vga_io_reg, (unsigned char)(curpos >> 8));
155
156 outb(vga_idx_reg, VGA_C_LOW);
157 outb(vga_io_reg, (unsigned char)(curpos & 0xff));
158 }
159
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
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 {
183 if (vram_start == 0) return;
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
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 );
210 }
211
212 /*
213 * tc_scroll_up
214 *
215 * Scroll the screen up 'n' character lines.
216 */
217 void
218 tc_scroll_up(int lines, __unused unsigned int top, __unused unsigned int bottom)
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 /*
237 * tc_scroll_down
238 *
239 * Scrolls the screen down 'n' character lines.
240 */
241 void
242 tc_scroll_down(int lines, __unused unsigned int top,
243 __unused unsigned int bottom)
244 {
245 csrpos_t to;
246 csrpos_t from;
247 int size;
248
249 /* move down */
250 to = ONE_PAGE - ONE_SPACE;
251 from = ONE_PAGE - ( ONE_LINE * lines ) - ONE_SPACE;
252 size = ( ONE_PAGE - ( ONE_LINE * lines ) ) / ONE_SPACE;
253 move_down(from, to, size);
254
255 /* clear top line */
256 to = 0;
257 size = ( ONE_LINE * lines ) / ONE_SPACE;
258 clear_block(to, size, vga_attr);
259 }
260
261 /* Default colors for 16-color palette */
262 enum {
263 kVGAColorBlack = 0,
264 kVGAColorBlue,
265 kVGAColorGreen,
266 kVGAColorCyan,
267 kVGAColorRed,
268 kVGAColorMagenta,
269 kVGAColorBrown,
270 kVGAColorWhite,
271 kVGAColorGray,
272 kVGAColorLightBlue,
273 kVGAColorLightGreen,
274 kVGAColorLightCyan,
275 kVGAColorLightRed,
276 kVGAColorLightMagenta,
277 kVGAColorLightBrown,
278 kVGAColorBrightWhite
279 };
280
281 /*
282 * tc_update_color
283 *
284 * Update the foreground / background color.
285 */
286 void
287 tc_update_color( int color, int fore )
288 {
289 unsigned char mask_on, mask_off;
290
291 switch ( color )
292 {
293 case 1: mask_on = kVGAColorRed; break;
294 case 3: mask_on = kVGAColorLightBrown; break;
295 case 4: mask_on = kVGAColorBlue; break;
296 case 6: mask_on = kVGAColorCyan; break;
297 default: mask_on = color; break;
298 }
299
300 if ( fore )
301 {
302 mask_off = 0x0f;
303 }
304 else
305 {
306 mask_off = 0xf0;
307 mask_on <<= 4;
308 }
309
310 vga_attr = (vga_attr & ~mask_off) | mask_on;
311
312 vga_attr_rev = ( ((vga_attr << 4) & 0xf0) |
313 ((vga_attr >> 4) & 0x0f) );
314 }
315
316 /*
317 * tc_show_cursor
318 *
319 * Show the hardware cursor.
320 */
321 void
322 tc_show_cursor(unsigned int x, unsigned int y)
323 {
324 set_cursor_position( XY_TO_CSRPOS(x, y) );
325 set_cursor_enable( TRUE );
326 }
327
328 /*
329 * tc_hide_cursor
330 *
331 * Hide the hardware cursor.
332 */
333 void
334 tc_hide_cursor(__unused unsigned int x, __unused unsigned int y)
335 {
336 set_cursor_enable( FALSE );
337 }
338
339 /*
340 * tc_clear_screen
341 *
342 * Clear the entire screen, or a portion of the screen
343 * relative to the current cursor position.
344 */
345 void
346 tc_clear_screen(unsigned int x, unsigned int y, __unused unsigned int top,
347 __unused unsigned int bottom, int operation)
348 {
349 csrpos_t start;
350 int count;
351
352 switch ( operation )
353 {
354 case 0: /* To end of screen */
355 start = XY_TO_CSRPOS(x, y);
356 count = ONE_PAGE - start;
357 break;
358 case 1: /* To start of screen */
359 start = 0;
360 count = XY_TO_CSRPOS(x, y) + ONE_SPACE;
361 break;
362 default:
363 case 2: /* Whole screen */
364 start = 0;
365 count = ONE_PAGE;
366 break;
367 }
368 clear_block(start, count, vga_attr);
369 }
370
371 /*
372 * tc_paint_char
373 *
374 * Display a character on screen with the given coordinates,
375 * and attributes.
376 */
377 void
378 tc_paint_char(unsigned int x, unsigned int y, unsigned char ch, int attrs,
379 __unused unsigned char ch_previous, __unused int attrs_previous)
380 {
381 char my_attr = vga_attr;
382
383 if ( attrs & 4 ) my_attr = vga_attr_rev;
384
385 display_char( XY_TO_CSRPOS(x, y), ch, vga_attr );
386 }
387
388 /*
389 * tc_enable
390 *
391 * Enable / disable the console.
392 */
393 void
394 tc_enable(__unused boolean_t enable)
395 {
396
397 }
398
399 /*
400 * tc_initialize
401 *
402 * Must be called before any other exported functions.
403 */
404 void
405 tc_initialize(struct vc_info * vinfo_p)
406 {
407 vinfo_p->v_rows = vinfo_p->v_height;
408 vinfo_p->v_columns = vinfo_p->v_width;
409
410 vga_init( vinfo_p->v_columns,
411 vinfo_p->v_rows,
412 (unsigned char *) vinfo_p->v_baseaddr);
413 }