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