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