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 */ 42typedef 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 */ 81static short vga_idx_reg; /* location of VGA index register */ 82static short vga_io_reg; /* location of VGA data register */ 83static short vga_cols = 80; /* number of columns */ 84static short vga_rows = 25; /* number of rows */ 85static char vga_attr; /* current character attribute */ 86static char vga_attr_rev; /* current reverse attribute */ 87static char vga_cursor_start; /* cached cursor start scan line */ 88static unsigned char *vram_start; /* VM start of VGA frame buffer */ 89 90/* 91 * Functions in kdasm.s. 92 */ 93extern void kd_slmwd(unsigned char * pos, int count, unsigned short val); 94extern void kd_slmscu(unsigned char * from, unsigned char * to, int count); 95extern void kd_slmscd(unsigned char * from, unsigned char * to, int count); 96 97/* 98 * move_up 99 * 100 * Block move up for VGA. 101 */ 102static void 103move_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 */ 116static void 117move_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 */ 130static void 131clear_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 */ 146static void 147set_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 */ 165static void 166set_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 */ 178static void 179display_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 */ 193static void 194vga_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 */ 217void 218tc_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 */ 241void 242tc_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 */ 262enum { 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 */ 286void 287tc_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 */ 321void 322tc_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 */ 333void 334tc_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 */ 345void 346tc_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 */ 377void 378tc_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 */ 393void 394tc_enable(__unused boolean_t enable) 395{ 396 397} 398 399/* 400 * tc_initialize 401 * 402 * Must be called before any other exported functions. 403 */ 404void 405tc_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} 414