diff options
Diffstat (limited to 'kernel/old/cio.c')
-rw-r--r-- | kernel/old/cio.c | 796 |
1 files changed, 0 insertions, 796 deletions
diff --git a/kernel/old/cio.c b/kernel/old/cio.c deleted file mode 100644 index cfff543..0000000 --- a/kernel/old/cio.c +++ /dev/null @@ -1,796 +0,0 @@ -/* -** SCCS ID: @(#)cio.c 2.10 1/22/25 -** -** @file cio.c -** -** @author Warren R. Carithers -** -** Based on: c_io.c 1.13 (Ken Reek, Jon Coles, Warren R. Carithers) -** -** Console I/O routines -** -** This module implements a simple set of input and output routines -** for the console screen and keyboard on the machines in the DSL. -** Refer to the header file comments for complete details. -** -** Naming conventions: -** -** Externally-visible functions have names beginning with the -** characters "cio_". -** -*/ - -#include <cio.h> -#include <lib.h> -#include <support.h> -#include <x86/arch.h> -#include <x86/pic.h> -#include <x86/ops.h> - -/* -** Bit masks for the lower five and eight bits of a value -*/ -#define BMASK5 0x1f -#define BMASK8 0xff - -/* -** Video parameters -*/ -#define SCREEN_MIN_X 0 -#define SCREEN_MIN_Y 0 -#define SCREEN_X_SIZE 80 -#define SCREEN_Y_SIZE 25 -#define SCREEN_MAX_X ( SCREEN_X_SIZE - 1 ) -#define SCREEN_MAX_Y ( SCREEN_Y_SIZE - 1 ) - -/* -** Video state -*/ -static unsigned int scroll_min_x, scroll_min_y; -static unsigned int scroll_max_x, scroll_max_y; -static unsigned int curr_x, curr_y; -static unsigned int min_x, min_y; -static unsigned int max_x, max_y; - -// pointer to input notification function -static void (*notify)(int); - -#ifdef SA_DEBUG -#include <stdio.h> -#define cio_putchar putchar -#define cio_puts(x) fputs( x, stdout ) -#endif - - -/* -** VGA definitions. -*/ - -// calculate the memory address of a specific character position -// within VGA memory -#define VIDEO_ADDR(x,y) ( unsigned short * ) \ - ( VID_BASE_ADDR + 2 * ( (y) * SCREEN_X_SIZE + (x) ) ) - -// port addresses -#define VGA_CTRL_IX_ADDR 0x3d4 -# define VGA_CTRL_CUR_HIGH 0x0e // cursor location, high byte -# define VGA_CTRL_CUR_LOW 0x0f // cursor location, low byte -#define VGA_CTRL_IX_DATA 0x3d5 - -// attribute bits -#define VGA_ATT_BBI 0x80 // blink, or background intensity -#define VGA_ATT_BGC 0x70 // background color -#define VGA_ATT_FICS 0x80 // foreground intensity or char font select -#define VGA_ATT_FGC 0x70 // foreground color - -// color selections -#define VGA_BG_BLACK 0x0000 // background colors -#define VGA_BG_BLUE 0x1000 -#define VGA_BG_GREEN 0x2000 -#define VGA_BG_CYAN 0x3000 -#define VGA_BG_RED 0x4000 -#define VGA_BG_MAGENTA 0x5000 -#define VGA_BG_BROWN 0x6000 -#define VGA_BG_WHITE 0x7000 - -#define VGA_FG_BLACK 0x0000 // foreground colors -#define VGA_FG_BLUE 0x0100 -#define VGA_FG_GREEN 0x0200 -#define VGA_FG_CYAN 0x0300 -#define VGA_FG_RED 0x0400 -#define VGA_FG_MAGENTA 0x0500 -#define VGA_FG_BROWN 0x0600 -#define VGA_FG_WHITE 0x0700 - -// color combinations -#define VGA_WHITE_ON_BLACK (VGA_FG_WHITE | VGA_BG_BLACK) -#define VGA_BLACK_ON_WHITE (VGA_FG_BLACK | VGA_BG_WHITE) - -/* -** Internal support routines. -*/ - -/* -** setcursor: set the cursor location (screen coordinates) -*/ -static void setcursor( void ) { - unsigned addr; - unsigned int y = curr_y; - - if( y > scroll_max_y ) { - y = scroll_max_y; - } - - addr = (unsigned)( y * SCREEN_X_SIZE + curr_x ); - - outb( VGA_CTRL_IX_ADDR, VGA_CTRL_CUR_HIGH ); - outb( VGA_CTRL_IX_DATA, ( addr >> 8 ) & BMASK8 ); - outb( VGA_CTRL_IX_ADDR, VGA_CTRL_CUR_LOW ); - outb( VGA_CTRL_IX_DATA, addr & BMASK8 ); -} - -/* -** putchar_at: physical output to the video memory -*/ -static void putchar_at( unsigned int x, unsigned int y, unsigned int c ) { - /* - ** If x or y is too big or small, don't do any output. - */ - if( x <= max_x && y <= max_y ) { - unsigned short *addr = VIDEO_ADDR( x, y ); - - /* - ** The character may have attributes associated with it; if - ** so, use those, otherwise use white on black. - */ - c &= 0xffff; // keep only the lower bytes - if( c > BMASK8 ) { - *addr = (unsigned short)c; - } else { - *addr = (unsigned short)c | VGA_WHITE_ON_BLACK; - } - } -} - -/* -** Globally-visible support routines. -*/ - -/* -** Set the scrolling region -*/ -void cio_setscroll( unsigned int s_min_x, unsigned int s_min_y, - unsigned int s_max_x, unsigned int s_max_y ) { - scroll_min_x = bound( min_x, s_min_x, max_x ); - scroll_min_y = bound( min_y, s_min_y, max_y ); - scroll_max_x = bound( scroll_min_x, s_max_x, max_x ); - scroll_max_y = bound( scroll_min_y, s_max_y, max_y ); - curr_x = scroll_min_x; - curr_y = scroll_min_y; - setcursor(); -} - -/* -** Cursor movement in the scroll region -*/ -void cio_moveto( unsigned int x, unsigned int y ) { - curr_x = bound( scroll_min_x, x + scroll_min_x, scroll_max_x ); - curr_y = bound( scroll_min_y, y + scroll_min_y, scroll_max_y ); - setcursor(); -} - -/* -** The putchar family -*/ -void cio_putchar_at( unsigned int x, unsigned int y, unsigned int c ) { - if( ( c & 0x7f ) == '\n' ) { - unsigned int limit; - - /* - ** If we're in the scroll region, don't let this loop - ** leave it. If we're not in the scroll region, don't - ** let this loop enter it. - */ - if( x > scroll_max_x ) { - limit = max_x; - } - else if( x >= scroll_min_x ) { - limit = scroll_max_x; - } - else { - limit = scroll_min_x - 1; - } - while( x <= limit ) { - putchar_at( x, y, ' ' ); - x += 1; - } - } - else { - putchar_at( x, y, c ); - } -} - -#ifndef SA_DEBUG -void cio_putchar( unsigned int c ) { - /* - ** If we're off the bottom of the screen, scroll the window. - */ - if( curr_y > scroll_max_y ) { - cio_scroll( curr_y - scroll_max_y ); - curr_y = scroll_max_y; - } - - switch( c & BMASK8 ) { - case '\n': - /* - ** Erase to the end of the line, then move to new line - ** (actual scroll is delayed until next output appears). - */ - while( curr_x <= scroll_max_x ) { - putchar_at( curr_x, curr_y, ' ' ); - curr_x += 1; - } - curr_x = scroll_min_x; - curr_y += 1; - break; - - case '\r': - curr_x = scroll_min_x; - break; - - default: - putchar_at( curr_x, curr_y, c ); - curr_x += 1; - if( curr_x > scroll_max_x ) { - curr_x = scroll_min_x; - curr_y += 1; - } - break; - } - setcursor(); -} -#endif - -/* -** The puts family -*/ -void cio_puts_at( unsigned int x, unsigned int y, const char *str ) { - unsigned int ch; - - while( (ch = *str++) != '\0' && x <= max_x ) { - cio_putchar_at( x, y, ch ); - x += 1; - } -} - -#ifndef SA_DEBUG -void cio_puts( const char *str ) { - unsigned int ch; - - while( (ch = *str++) != '\0' ) { - cio_putchar( ch ); - } -} -#endif - -/* -** Write a "sized" buffer (like cio_puts(), but no NUL) -*/ -void cio_write( const char *buf, int length ) { - for( int i = 0; i < length; ++i ) { - cio_putchar( buf[i] ); - } -} - -void cio_clearscroll( void ) { - unsigned int nchars = scroll_max_x - scroll_min_x + 1; - unsigned int l; - unsigned int c; - - for( l = scroll_min_y; l <= scroll_max_y; l += 1 ) { - unsigned short *to = VIDEO_ADDR( scroll_min_x, l ); - - for( c = 0; c < nchars; c += 1 ) { - *to++ = ' ' | 0x0700; - } - } -} - -void cio_clearscreen( void ) { - unsigned short *to = VIDEO_ADDR( min_x, min_y ); - unsigned int nchars = ( max_y - min_y + 1 ) * ( max_x - min_x + 1 ); - - while( nchars > 0 ) { - *to++ = ' ' | 0x0700; - nchars -= 1; - } -} - - -void cio_scroll( unsigned int lines ) { - unsigned short *from; - unsigned short *to; - int nchars = scroll_max_x - scroll_min_x + 1; - int line, c; - - /* - ** If # of lines is the whole scrolling region or more, just clear. - */ - if( lines > scroll_max_y - scroll_min_y ) { - cio_clearscroll(); - curr_x = scroll_min_x; - curr_y = scroll_min_y; - setcursor(); - return; - } - - /* - ** Must copy it line by line. - */ - for( line = scroll_min_y; line <= scroll_max_y - lines; line += 1 ) { - from = VIDEO_ADDR( scroll_min_x, line + lines ); - to = VIDEO_ADDR( scroll_min_x, line ); - for( c = 0; c < nchars; c += 1 ) { - *to++ = *from++; - } - } - - for( ; line <= scroll_max_y; line += 1 ) { - to = VIDEO_ADDR( scroll_min_x, line ); - for( c = 0; c < nchars; c += 1 ) { - *to++ = ' ' | 0x0700; - } - } -} - -static int mypad( int x, int y, int extra, int padchar ) { - while( extra > 0 ) { - if( x != -1 || y != -1 ) { - cio_putchar_at( x, y, padchar ); - x += 1; - } - else { - cio_putchar( padchar ); - } - extra -= 1; - } - return x; -} - -static int mypadstr( int x, int y, char *str, int len, int width, - int leftadjust, int padchar ) { - int extra; - - if( len < 0 ) { - len = strlen( str ); - } - extra = width - len; - if( extra > 0 && !leftadjust ) { - x = mypad( x, y, extra, padchar ); - } - if( x != -1 || y != -1 ) { - cio_puts_at( x, y, str ); - x += len; - } - else { - cio_puts( str ); - } - if( extra > 0 && leftadjust ) { - x = mypad( x, y, extra, padchar ); - } - return x; -} - -static void do_printf( int x, int y, char **f ) { - char *fmt = *f; - int *ap; - char buf[ 12 ]; - char ch; - char *str; - int leftadjust; - int width; - int len; - int padchar; - - /* - ** Get characters from the format string and process them - */ - - ap = (int *)( f + 1 ); - - while( (ch = *fmt++) != '\0' ) { - - /* - ** Is it the start of a format code? - */ - - if( ch == '%' ) { - - /* - ** Yes, get the padding and width options (if there). - ** Alignment must come at the beginning, then fill, - ** then width. - */ - - leftadjust = 0; - padchar = ' '; - width = 0; - - ch = *fmt++; - - if( ch == '-' ) { - leftadjust = 1; - ch = *fmt++; - } - - if( ch == '0' ) { - padchar = '0'; - ch = *fmt++; - } - - while( ch >= '0' && ch <= '9' ) { - width *= 10; - width += ch - '0'; - ch = *fmt++; - } - - /* - ** What data type do we have? - */ - switch( ch ) { - - case 'c': - // ch = *( (int *)ap )++; - ch = *ap++; - buf[ 0 ] = ch; - buf[ 1 ] = '\0'; - x = mypadstr( x, y, buf, 1, width, leftadjust, padchar ); - break; - - case 'd': - // len = cvtdec( buf, *( (int *)ap )++ ); - len = cvtdec( buf, *ap++ ); - x = mypadstr( x, y, buf, len, width, leftadjust, padchar ); - break; - - case 's': - // str = *( (char **)ap )++; - str = (char *) (*ap++); - x = mypadstr( x, y, str, -1, width, leftadjust, padchar ); - break; - - case 'x': - // len = cvthex( buf, *( (int *)ap )++ ); - len = cvthex( buf, *ap++ ); - x = mypadstr( x, y, buf, len, width, leftadjust, padchar ); - break; - - case 'o': - // len = cvtoct( buf, *( (int *)ap )++ ); - len = cvtoct( buf, *ap++ ); - x = mypadstr( x, y, buf, len, width, leftadjust, padchar ); - break; - - case 'u': - len = cvtuns( buf, *ap++ ); - x = mypadstr( x, y, buf, len, width, leftadjust, padchar ); - break; - - } - } else { - - /* - ** No - just print it normally. - */ - - if( x != -1 || y != -1 ) { - cio_putchar_at( x, y, ch ); - switch( ch ) { - case '\n': - y += 1; - /* FALL THRU */ - - case '\r': - x = scroll_min_x; - break; - - default: - x += 1; - } - } - else { - cio_putchar( ch ); - } - } - } -} - -void cio_printf_at( unsigned int x, unsigned int y, char *fmt, ... ) { - do_printf( x, y, &fmt ); -} - -void cio_printf( char *fmt, ... ) { - do_printf( -1, -1, &fmt ); -} - -/* -** These are the "standard" IBM AT "Set 1" keycodes. -*/ - -static unsigned char scan_code[ 2 ][ 128 ] = { - { // unshifted characters -/* 00-07 */ '\377', '\033', '1', '2', '3', '4', '5', '6', -/* 08-0f */ '7', '8', '9', '0', '-', '=', '\b', '\t', -/* 10-17 */ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', -/* 18-1f */ 'o', 'p', '[', ']', '\n', '\377', 'a', 's', -/* 20-27 */ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', -/* 28-2f */ '\'', '`', '\377', '\\', 'z', 'x', 'c', 'v', -/* 30-37 */ 'b', 'n', 'm', ',', '.', '/', '\377', '*', -/* 38-3f */ '\377', ' ', '\377', '\377', '\377', '\377', '\377', '\377', -/* 40-47 */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '7', -/* 48-4f */ '8', '9', '-', '4', '5', '6', '+', '1', -/* 50-57 */ '2', '3', '0', '.', '\377', '\377', '\377', '\377', -/* 58-5f */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', -/* 60-67 */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', -/* 68-6f */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', -/* 70-77 */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', -/* 78-7f */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377' - }, - - { // shifted characters -/* 00-07 */ '\377', '\033', '!', '@', '#', '$', '%', '^', -/* 08-0f */ '&', '*', '(', ')', '_', '+', '\b', '\t', -/* 10-17 */ 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', -/* 18-1f */ 'O', 'P', '{', '}', '\n', '\377', 'A', 'S', -/* 20-27 */ 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', -/* 28-2f */ '"', '~', '\377', '|', 'Z', 'X', 'C', 'V', -/* 30-37 */ 'B', 'N', 'M', '<', '>', '?', '\377', '*', -/* 38-3f */ '\377', ' ', '\377', '\377', '\377', '\377', '\377', '\377', -/* 40-47 */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '7', -/* 48-4f */ '8', '9', '-', '4', '5', '6', '+', '1', -/* 50-57 */ '2', '3', '0', '.', '\377', '\377', '\377', '\377', -/* 58-5f */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', -/* 60-67 */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', -/* 68-6f */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', -/* 70-77 */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', -/* 78-7f */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377' - } -}; - -/* -** Scan code masks -*/ - -// 'release' bit -#define REL_BIT 0x80 -#define CODE_BITS 0x7f - -#define IS_PRESS(c) (((c) & REL_BIT) == 0) -#define IS_RELEASE(c) (((c) & REL_BIT) != 0) - -/* -** Scan codes for some special characters -*/ - -// escape code - followed by another code byte -#define SCAN_ESC 0xe0 - -// shift keys: press, release -#define L_SHIFT_DN 0x2a -#define R_SHIFT_DN 0x36 -#define L_SHIFT_UP 0xaa -#define R_SHIFT_UP 0xb6 - -// control keys -#define L_CTRL_DN 0x1d -#define L_CTRL_UP 0x9d - -/* -** I/O communication constants -*/ -#define KBD_DATA 0x60 -#define KBD_STATUS 0x64 -#define READY 0x1 - -/* -** Circular buffer for input characters. Characters are inserted at -** next_space, and are removed at next_char. Buffer is empty if -** these are equal. -*/ -#define C_BUFSIZE 200 - -static char input_buffer[ C_BUFSIZE ]; -static volatile char *next_char = input_buffer; -static volatile char *next_space = input_buffer; - -static volatile char *increment( volatile char *pointer ) { - if( ++pointer >= input_buffer + C_BUFSIZE ) { - pointer = input_buffer; - } - return pointer; -} - -static int input_scan_code( int code ) { - static int shift = 0; - static int ctrl_mask = BMASK8; - int rval = -1; - - /* - ** Do the shift processing - */ - code &= BMASK8; - switch( code ) { - case L_SHIFT_DN: - case R_SHIFT_DN: - shift = 1; - break; - - case L_SHIFT_UP: - case R_SHIFT_UP: - shift = 0; - break; - - case L_CTRL_DN: - ctrl_mask = BMASK5; - break; - - case L_CTRL_UP: - ctrl_mask = BMASK8; - break; - - default: - /* - ** Process ordinary characters only on the press (to handle - ** autorepeat). Ignore undefined scan codes. - */ - if( IS_PRESS(code) ) { - code = scan_code[ shift ][ (int)code ]; - if( code != '\377' ) { - volatile char *next = increment( next_space ); - - /* - ** Store character only if there's room - */ - rval = code & ctrl_mask; - if( next != next_char ) { - *next_space = code & ctrl_mask; - next_space = next; - } - } - } - } - return( rval ); -} - -static void keyboard_isr( int vector, int code ) { - - int data = inb( KBD_DATA ); - int val = input_scan_code( data ); - - // if there is a notification function, call it - if( val != -1 && notify ) - notify( val ); - - outb( PIC1_CMD, PIC_EOI ); -} - -int cio_getchar( void ) { - char c; - int interrupts_enabled = r_eflags() & EFL_IF; - - while( next_char == next_space ) { - if( !interrupts_enabled ) { - /* - ** Must read the next keystroke ourselves. - */ - while( ( inb( KBD_STATUS ) & READY ) == 0 ) { - ; - } - (void) input_scan_code( inb( KBD_DATA ) ); - } - } - - c = *next_char & BMASK8; - next_char = increment( next_char ); - if( c != EOT ) { - cio_putchar( c ); - } - return c; -} - -int cio_gets( char *buffer, unsigned int size ) { - char ch; - int count = 0; - - while( size > 1 ) { - ch = cio_getchar(); - if( ch == EOT ) { - break; - } - *buffer++ = ch; - count += 1; - size -= 1; - if( ch == '\n' ) { - break; - } - } - *buffer = '\0'; - return count; -} - -int cio_input_queue( void ) { - int n_chars = next_space - next_char; - - if( n_chars < 0 ) { - n_chars += C_BUFSIZE; - } - return n_chars; -} - -/* -** Initialization routines -*/ -void cio_init( void (*fcn)(int) ) { - /* - ** Screen dimensions - */ - min_x = SCREEN_MIN_X; - min_y = SCREEN_MIN_Y; - max_x = SCREEN_MAX_X; - max_y = SCREEN_MAX_Y; - - /* - ** Scrolling region - */ - scroll_min_x = SCREEN_MIN_X; - scroll_min_y = SCREEN_MIN_Y; - scroll_max_x = SCREEN_MAX_X; - scroll_max_y = SCREEN_MAX_Y; - - /* - ** Initial cursor location - */ - curr_y = min_y; - curr_x = min_x; - setcursor(); - - /* - ** Notification function (or NULL) - */ - notify = fcn; - - /* - ** Set up the interrupt handler for the keyboard - */ - install_isr( VEC_KBD, keyboard_isr ); -} - -#ifdef SA_DEBUG -int main() { - cio_printf( "%d\n", 123 ); - cio_printf( "%d\n", -123 ); - cio_printf( "%d\n", 0x7fffffff ); - cio_printf( "%d\n", 0x80000001 ); - cio_printf( "%d\n", 0x80000000 ); - cio_printf( "x%14dy\n", 0x80000000 ); - cio_printf( "x%-14dy\n", 0x80000000 ); - cio_printf( "x%014dy\n", 0x80000000 ); - cio_printf( "x%-014dy\n", 0x80000000 ); - cio_printf( "%s\n", "xyz" ); - cio_printf( "|%10s|\n", "xyz" ); - cio_printf( "|%-10s|\n", "xyz" ); - cio_printf( "%c\n", 'x' ); - cio_printf( "|%4c|\n", 'y' ); - cio_printf( "|%-4c|\n", 'y' ); - cio_printf( "|%04c|\n", 'y' ); - cio_printf( "|%-04c|\n", 'y' ); - cio_printf( "|%3d|\n", 5 ); - cio_printf( "|%3d|\n", 54321 ); - cio_printf( "%x\n", 0x123abc ); - cio_printf( "|%04x|\n", 20 ); - cio_printf( "|%012x|\n", 0xfedcba98 ); - cio_printf( "|%-012x|\n", 0x76543210 ); -} - -int curr_x, curr_y, max_x, max_y; -#endif |