/* * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * text_console.c * * VGA text console support. */ #include #include #include "text_console.h" /* * Macros and typedefs. */ typedef short csrpos_t; /* cursor position, ONE_SPACE bytes per char */ #define ONE_SPACE 2 /* bytes per character */ #define ONE_LINE (vga_cols * ONE_SPACE) /* number of bytes in line */ #define ONE_PAGE (vga_rows * ONE_LINE) /* number of bytes in page */ #define SPACE_CHAR 0x20 #define VGA_FB_START 0x0b8000 #define VGA_FB_SIZE 0x8000 #define VGA_IDX_REG 0x3d4 #define VGA_IO_REG 0x3d5 /* * Commands sent to graphics adapter. */ #define VGA_C_START 0x0a /* cursor start position, on/off bit */ #define VGA_C_LOW 0x0f /* return low byte of cursor addr */ #define VGA_C_HIGH 0x0e /* high byte */ /* * Attributes for character sent to display. */ #define VGA_ATTR_NORMAL 0x07 #define VGA_ATTR_REVERSE 0x70 /* * Cursor Start Register bit fields. */ #define VGA_CURSOR_CS 0x1F #define VGA_CURSOR_ON 0x20 /* * Convert from XY coordinate to a location in display memory. */ #define XY_TO_CSRPOS(x, y) (((y) * vga_cols + (x)) * ONE_SPACE) /* * Globals. */ static short vga_idx_reg = 0; /* location of VGA index register */ static short vga_io_reg = 0; /* location of VGA data register */ static short vga_cols = 80; /* number of columns */ static short vga_rows = 25; /* number of rows */ static char vga_attr = 0; /* current character attribute */ static char vga_attr_rev = 0; /* current reverse attribute */ static char vga_cursor_start = 0; /* cached cursor start scan line */ static char * vram_start = 0; /* VM start of VGA frame buffer */ /* * Functions in kdasm.s. */ extern void kd_slmwd(unsigned char * pos, int count, unsigned short val); extern void kd_slmscu(unsigned char * from, unsigned char * to, int count); extern void kd_slmscd(unsigned char * from, unsigned char * to, int count); /* * move_up * * Block move up for VGA. */ static void move_up( csrpos_t from, csrpos_t to, int count) { if (vram_start == 0) return; kd_slmscu( vram_start + from, vram_start + to, count ); } /* * move_down * * Block move down for VGA. */ static void move_down( csrpos_t from, csrpos_t to, int count ) { if (vram_start == 0) return; kd_slmscd( vram_start + from, vram_start + to, count ); } /* * clear_block * * Fast clear for VGA. */ static void clear_block( csrpos_t start, int size, char attr) { if (vram_start == 0) return; kd_slmwd( vram_start + start, size, ((unsigned short) attr << 8) + SPACE_CHAR); } /* * set_cursor_position * * This function sets the hardware cursor position * on the screen. */ static void set_cursor_position( csrpos_t newpos ) { short curpos; /* position, not scaled for attribute byte */ curpos = newpos / ONE_SPACE; outb(vga_idx_reg, VGA_C_HIGH); outb(vga_io_reg, (unsigned char)(curpos >> 8)); outb(vga_idx_reg, VGA_C_LOW); outb(vga_io_reg, (unsigned char)(curpos & 0xff)); } /* * set_cursor_enable * * Allow the cursor to be turned on or off. */ static void set_cursor_enable( boolean_t enable ) { outb(vga_idx_reg, VGA_C_START); outb(vga_io_reg, vga_cursor_start | (enable == TRUE ? VGA_CURSOR_ON : 0)); } /* * display_char * * Display attributed character for VGA (mode 3). */ static void display_char( csrpos_t pos, /* where to put it */ char ch, /* the character */ char attr ) /* its attribute */ { if (vram_start == 0) return; *(vram_start + pos) = ch; *(vram_start + pos + 1) = attr; } /* * vga_init * * Initialize the VGA text console. */ static void vga_init(int cols, int rows, unsigned char * addr) { vram_start = addr; vga_idx_reg = VGA_IDX_REG; vga_io_reg = VGA_IO_REG; vga_rows = rows; vga_cols = cols; vga_attr = VGA_ATTR_NORMAL; vga_attr_rev = VGA_ATTR_REVERSE; /* cache cursor start position */ outb(vga_idx_reg, VGA_C_START); vga_cursor_start = inb(vga_io_reg) & VGA_CURSOR_CS; /* defaults to a hidden hw cursor */ set_cursor_enable( FALSE ); } /* * tc_scroll_up * * Scroll the screen up 'n' character lines. */ void tc_scroll_up( int lines, __unused int top, __unused int bottom ) { csrpos_t to; csrpos_t from; int size; /* scroll up */ to = 0; from = ONE_LINE * lines; size = ( ONE_PAGE - ( ONE_LINE * lines ) ) / ONE_SPACE; move_up(from, to, size); /* clear bottom line */ to = ( ( vga_rows - lines) * ONE_LINE ); size = ( ONE_LINE * lines ) / ONE_SPACE; clear_block(to, size, vga_attr); } /* * tc_scroll_down * * Scrolls the screen down 'n' character lines. */ void tc_scroll_down( int lines, __unused int top, __unused int bottom ) { csrpos_t to; csrpos_t from; int size; /* move down */ to = ONE_PAGE - ONE_SPACE; from = ONE_PAGE - ( ONE_LINE * lines ) - ONE_SPACE; size = ( ONE_PAGE - ( ONE_LINE * lines ) ) / ONE_SPACE; move_down(from, to, size); /* clear top line */ to = 0; size = ( ONE_LINE * lines ) / ONE_SPACE; clear_block(to, size, vga_attr); } /* Default colors for 16-color palette */ enum { kVGAColorBlack = 0, kVGAColorBlue, kVGAColorGreen, kVGAColorCyan, kVGAColorRed, kVGAColorMagenta, kVGAColorBrown, kVGAColorWhite, kVGAColorGray, kVGAColorLightBlue, kVGAColorLightGreen, kVGAColorLightCyan, kVGAColorLightRed, kVGAColorLightMagenta, kVGAColorLightBrown, kVGAColorBrightWhite }; /* * tc_update_color * * Update the foreground / background color. */ void tc_update_color( int color, int fore ) { unsigned char mask_on, mask_off; switch ( color ) { case 1: mask_on = kVGAColorRed; break; case 3: mask_on = kVGAColorLightBrown; break; case 4: mask_on = kVGAColorBlue; break; case 6: mask_on = kVGAColorCyan; break; default: mask_on = color; break; } if ( fore ) { mask_off = 0x0f; } else { mask_off = 0xf0; mask_on <<= 4; } vga_attr = (vga_attr & ~mask_off) | mask_on; vga_attr_rev = ( ((vga_attr << 4) & 0xf0) | ((vga_attr >> 4) & 0x0f) ); } /* * tc_show_cursor * * Show the hardware cursor. */ void tc_show_cursor( int x, int y ) { set_cursor_position( XY_TO_CSRPOS(x, y) ); set_cursor_enable( TRUE ); } /* * tc_hide_cursor * * Hide the hardware cursor. */ void tc_hide_cursor( __unused int x, __unused int y ) { set_cursor_enable( FALSE ); } /* * tc_clear_screen * * Clear the entire screen, or a portion of the screen * relative to the current cursor position. */ void tc_clear_screen(int x, int y, __unused int top, __unused int bottom, int operation) { csrpos_t start; int count; switch ( operation ) { case 0: /* To end of screen */ start = XY_TO_CSRPOS(x, y); count = ONE_PAGE - start; break; case 1: /* To start of screen */ start = 0; count = XY_TO_CSRPOS(x, y) + ONE_SPACE; break; default: case 2: /* Whole screen */ start = 0; count = ONE_PAGE; break; } clear_block(start, count, vga_attr); } /* * tc_paint_char * * Display a character on screen with the given coordinates, * and attributes. */ void tc_paint_char(int x, int y, unsigned char ch, int attrs, __unused unsigned char ch_previous, __unused int attrs_previous) { char my_attr = vga_attr; if ( attrs & 4 ) my_attr = vga_attr_rev; display_char( XY_TO_CSRPOS(x, y), ch, vga_attr ); } /* * tc_enable * * Enable / disable the console. */ void tc_enable(__unused boolean_t enable) { } /* * tc_initialize * * Must be called before any other exported functions. */ void tc_initialize(struct vc_info * vinfo_p) { vinfo_p->v_rows = vinfo_p->v_height; vinfo_p->v_columns = vinfo_p->v_width; vga_init( vinfo_p->v_columns, vinfo_p->v_rows, (unsigned char *) vinfo_p->v_baseaddr); }