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