/* $Header: /ker/i386/RCS/die.c,v 2.3 93/10/29 00:56:42 nigel Exp Locker: nigel $ */ /* * die.c -- Get information out from a very young kernel which probably * can't do printf()'s. * * $Log: die.c,v $ * Revision 2.3 93/10/29 00:56:42 nigel * R98 (aka 4.2 Beta) prior to removing System Global memory * * Revision 2.2 93/08/19 03:40:00 nigel * Nigel's R83 * */ #if KLAATU #define SERIAL_CONSOLE 1 #define INS8250 0x3f8 /* klaatu */ #endif #if GORT #define SERIAL_CONSOLE 1 #define INS8250 0x290 /* gort */ #endif #ifndef INS8250 #define INS8250 0x3f8 #endif #define _KERNEL 1 #include <kernel/reg.h> #include <sys/mmu.h> #include <ctype.h> #define COLOR ((char *) (0x0000B0000 + ctob(SBASE-PBASE))) #define MONO ((char *) (0x0000B8000 + ctob(SBASE-PBASE))) #define PAGING (0x80000000) /* Paging bit in cr0, set if paging is on. */ static int chirp_off; /* * void _chirp(char c, off); * Put character 'c' directly in video memory at offset 'off'; * * This routine must not use any static variables, since the .data * segment is not necessarily available yet. */ void _chirp(c, off) char c; int off; { #if SERIAL_CONSOLE __putchar(c); #else if (!paging()) { *(COLOR + off) = c; *(MONO + off) = c; } else { *((char *) (ctob(VIDEOa) + off)) = c; *((char *) (ctob(VIDEOb) + off)) = c; } #endif } /* * void chirp(char c); * Put character 'c' directly in the first character of video memory; * * This routine must not use any static variables, since the .data * segment is not necessarily available yet. */ void chirp(c) char c; { _chirp(c, 158); } /* * void strchirp(char *str); * Put string 'str' directly in the next character of video memory; * Note that calls to chirp and dchirp do not effect what mchirp considers * to be the next character. * * This routine uses a ds variable, so it must not be used until the .data * segment is available (this currently happens in the middle of mchinit). */ void strchirp(str) char *str; { char c; while ((c = * str ++) != 0) { _chirp (c, chirp_off); chirp_off += 2; } } /* * void mchirp(char c); * Put character 'c' directly in the next character of video memory; * If c == 0 reset the "next" character to be the first character. * Note that calls to chirp and dchirp do not effect what mchirp considers * to be the next character. * * This routine uses a static variable, so it must not be used until the .data * segment is available (this currently happens in the middle of mchinit). */ void mchirp(c) char c; { if ('\0' != c) { _chirp(c, chirp_off); chirp_off += 2; /* Don't go past 80 x 25 screen */ if (chirp_off > 4000) /* Don't go past 80 x 25 screen */ chirp_off = 0; } else chirp_off = 0; } /* * void dchirp(char c, charpos); * Put character 'c' directly in the 'charpos' character of video memory; * * This routine must not use any static variables, since the .data * segment is not necessarily available yet. */ void dchirp(c, charpos) char c; int charpos; { _chirp(c, charpos<<1); } /* * void die(char c); * Put character 'c' directly in video memory, and then halt. */ void die(c) char c; { _chirp(c, 0); for (;;) { halt(); } } #define LINESIZE 80 /* * puts() -- put a NUL terminated string. * Takes one argument--a pointer to a NUL terminated character string. */ void puts(s) register char *s; { while (*s != '\0') { mchirp(*s++); } } #define BS '\010' #define DEL '\0' /* This is really what getchar() returns! */ #define NAK '\025' #define BITS_PER_INT16 16 /* Number of bits in an int16. */ #define DIGITS_PER_INT16 4 /* Maximum hex digits in a 16 bit number. */ #define DIGITS_PER_INT8 2 /* Maximum hex digits in an 8 bit number. */ #if SERIAL_CONSOLE #define OUTCH(c) __putchar(c) #else #define OUTCH(c) mchirp(c) #endif void hexprint(n, hexdigits) int n, hexdigits; { int shift; char digit, outch; for (shift = 4*(hexdigits-1); shift >= 0; shift -= 4) { digit = (n >> shift) & 0xF; if (digit > 9) outch = 'A'+digit-10; else outch = '0'+digit; OUTCH(outch); } OUTCH(' '); } /* * Print a 32/16/8 bit integers in hexadecimal. */ void print32(num) int num; {hexprint(num,8);} void print16(num) int num; {hexprint(num,4);} void print8(num) int num; {hexprint(num,2);} void outch(c) int c; { OUTCH(c); } #define ASCII 1 #define XONXOFF 1 #define BAUD 9600 /* * file: i8251.c * * This version of putchar works with the serial lines. * Various configurations are possible through conditional * defines: * * BAUD default 9600 * specifies the baudrate, can be as high as 38400 * * CONSOLE default COM1: * is the base address of the uart * * ASCII default BINARY * if set, maps '\n' into CR, LF and reduces input * to 7-bit * * XONXOFF default not enabled * allows user to control output * */ #define THR (INS8250+0) #define IER (INS8250+1) #define IIR (INS8250+2) #define LCR (INS8250+3) #define MCR (INS8250+4) #define LSR (INS8250+5) #define MSR (INS8250+6) #define RBR THR #define DLL THR #define DLM IER #define DR 0x01 #define THRE 0x20 void __cinit() { #if SERIAL_CONSOLE register rate; #if BAUD rate = 115200L / BAUD; #else rate = 1; #endif outb(LCR, 0x00); outb(IER, 0x00); outb(LCR, 0x80); outb(DLL, rate); outb(DLM, rate>>8); outb(LCR, 0x03); outb(MCR, 0x03); __putchar('\007'); __putchar('g'); #endif } #define CTLQ 0021 #define CTLS 0023 int __getchar() { register int c; while( (inb(LSR) & DR) == 0 ) ; c = inb( RBR ); #if ASCII c &= 0x7F; #endif return( c ); } int __putchar( c ) register char c; { register int f; #if ASCII if (c == '\n') putchar( '\r' ); #endif while( ((f=inb(LSR)) & THRE) == 0 ) ; #if XONXOFF if( (f & DR) != 0 ) { f = inb( RBR ) & 0x7F; if (f == CTLS) { do { while( (inb(LSR) & DR) == 0) ; f = inb( RBR ) & 0x7F; } while (f != CTLQ); } } #endif outb( THR, c ); return( c ); }