⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 console.c

📁 jos lab3代码
💻 C
字号:
/* See COPYRIGHT for copyright information. */#include <inc/x86.h>#include <inc/memlayout.h>#include <inc/kbdreg.h>#include <inc/string.h>#include <inc/assert.h>#include <kern/console.h>void cons_intr(int (*proc)(void));/***** Serial I/O code *****/#define COM1		0x3F8#define COM_RX		0	// In:	Receive buffer (DLAB=0)#define COM_DLL		0	// Out: Divisor Latch Low (DLAB=1)#define COM_DLM		1	// Out: Divisor Latch High (DLAB=1)#define COM_IER		1	// Out: Interrupt Enable Register#define   COM_IER_RDI	0x01	//   Enable receiver data interrupt#define COM_IIR		2	// In:	Interrupt ID Register#define COM_FCR		2	// Out: FIFO Control Register#define COM_LCR		3	// Out: Line Control Register#define	  COM_LCR_DLAB	0x80	//   Divisor latch access bit#define	  COM_LCR_WLEN8	0x03	//   Wordlength: 8 bits#define COM_MCR		4	// Out: Modem Control Register#define	  COM_MCR_RTS	0x02	// RTS complement#define	  COM_MCR_DTR	0x01	// DTR complement#define	  COM_MCR_OUT2	0x08	// Out2 complement#define COM_LSR		5	// In:	Line Status Register#define   COM_LSR_DATA	0x01	//   Data availablestatic bool serial_exists;intserial_proc_data(void){	if (!(inb(COM1+COM_LSR) & COM_LSR_DATA))		return -1;	return inb(COM1+COM_RX);}voidserial_intr(void){	if (serial_exists)		cons_intr(serial_proc_data);}voidserial_init(void){	// Turn off the FIFO	outb(COM1+COM_FCR, 0);		// Set speed; requires DLAB latch	outb(COM1+COM_LCR, COM_LCR_DLAB);	outb(COM1+COM_DLL, (uint8_t) (115200 / 9600));	outb(COM1+COM_DLM, 0);	// 8 data bits, 1 stop bit, parity off; turn off DLAB latch	outb(COM1+COM_LCR, COM_LCR_WLEN8 & ~COM_LCR_DLAB);	// No modem controls	outb(COM1+COM_MCR, 0);	// Enable rcv interrupts	outb(COM1+COM_IER, COM_IER_RDI);	// Clear any preexisting overrun indications and interrupts	// Serial port doesn't exist if COM_LSR returns 0xFF	serial_exists = (inb(COM1+COM_LSR) != 0xFF);	(void) inb(COM1+COM_IIR);	(void) inb(COM1+COM_RX);}/***** Parallel port output code *****/// For information on PC parallel port programming, see the class References// page.// Stupid I/O delay routine necessitated by historical PC design flawsstatic voiddelay(void){	inb(0x84);	inb(0x84);	inb(0x84);	inb(0x84);}static voidlpt_putc(int c){	int i;	for (i = 0; !(inb(0x378+1) & 0x80) && i < 12800; i++)		delay();	outb(0x378+0, c);	outb(0x378+2, 0x08|0x04|0x01);	outb(0x378+2, 0x08);}/***** Text-mode CGA/VGA display output *****/static unsigned addr_6845;static uint16_t *crt_buf;static uint16_t crt_pos;voidcga_init(void){	volatile uint16_t *cp;	uint16_t was;	unsigned pos;	cp = (uint16_t*) (KERNBASE + CGA_BUF);	was = *cp;	*cp = (uint16_t) 0xA55A;	if (*cp != 0xA55A) {		cp = (uint16_t*) (KERNBASE + MONO_BUF);		addr_6845 = MONO_BASE;	} else {		*cp = was;		addr_6845 = CGA_BASE;	}		/* Extract cursor location */	outb(addr_6845, 14);	pos = inb(addr_6845 + 1) << 8;	outb(addr_6845, 15);	pos |= inb(addr_6845 + 1);	crt_buf = (uint16_t*) cp;	crt_pos = pos;}voidcga_putc(int c){	// if no attribute given, then use black on white	if (!(c & ~0xFF))		c |= 0x0700;	switch (c & 0xff) {	case '\b':		if (crt_pos > 0) {			crt_pos--;			crt_buf[crt_pos] = (c & ~0xff) | ' ';		}		break;	case '\n':		crt_pos += CRT_COLS;		/* fallthru */	case '\r':		crt_pos -= (crt_pos % CRT_COLS);		break;	case '\t':		cons_putc(' ');		cons_putc(' ');		cons_putc(' ');		cons_putc(' ');		cons_putc(' ');		break;	default:		crt_buf[crt_pos++] = c;		/* write the character */		break;	}	// What is the purpose of this?	if (crt_pos >= CRT_SIZE) {		int i;		memmove(crt_buf, crt_buf + CRT_COLS, (CRT_SIZE - CRT_COLS) * sizeof(uint16_t));		for (i = CRT_SIZE - CRT_COLS; i < CRT_SIZE; i++)			crt_buf[i] = 0x0700 | ' ';		crt_pos -= CRT_COLS;	}	/* move that little blinky thing */	outb(addr_6845, 14);	outb(addr_6845 + 1, crt_pos >> 8);	outb(addr_6845, 15);	outb(addr_6845 + 1, crt_pos);}/***** Keyboard input code *****/#define NO		0#define SHIFT		(1<<0)#define CTL		(1<<1)#define ALT		(1<<2)#define CAPSLOCK	(1<<3)#define NUMLOCK		(1<<4)#define SCROLLLOCK	(1<<5)#define E0ESC		(1<<6)static uint8_t shiftcode[256] = {	[0x1D] CTL,	[0x2A] SHIFT,	[0x36] SHIFT,	[0x38] ALT,	[0x9D] CTL,	[0xB8] ALT};static uint8_t togglecode[256] = {	[0x3A] CAPSLOCK,	[0x45] NUMLOCK,	[0x46] SCROLLLOCK};static uint8_t normalmap[256] ={	NO,   0x1B, '1',  '2',  '3',  '4',  '5',  '6',	// 0x00	'7',  '8',  '9',  '0',  '-',  '=',  '\b', '\t',	'q',  'w',  'e',  'r',  't',  'y',  'u',  'i',	// 0x10	'o',  'p',  '[',  ']',  '\n', NO,   'a',  's',	'd',  'f',  'g',  'h',  'j',  'k',  'l',  ';',	// 0x20	'\'', '`',  NO,   '\\', 'z',  'x',  'c',  'v',	'b',  'n',  'm',  ',',  '.',  '/',  NO,   '*',	// 0x30	NO,   ' ',  NO,   NO,   NO,   NO,   NO,   NO,	NO,   NO,   NO,   NO,   NO,   NO,   NO,   '7',	// 0x40	'8',  '9',  '-',  '4',  '5',  '6',  '+',  '1',	'2',  '3',  '0',  '.',  NO,   NO,   NO,   NO,	// 0x50	[0xC7] KEY_HOME,	[0x9C] '\n' /*KP_Enter*/,	[0xB5] '/' /*KP_Div*/,	[0xC8] KEY_UP,	[0xC9] KEY_PGUP,	[0xCB] KEY_LF,	[0xCD] KEY_RT,		[0xCF] KEY_END,	[0xD0] KEY_DN,		[0xD1] KEY_PGDN,	[0xD2] KEY_INS,		[0xD3] KEY_DEL};static uint8_t shiftmap[256] = {	NO,   033,  '!',  '@',  '#',  '$',  '%',  '^',	// 0x00	'&',  '*',  '(',  ')',  '_',  '+',  '\b', '\t',	'Q',  'W',  'E',  'R',  'T',  'Y',  'U',  'I',	// 0x10	'O',  'P',  '{',  '}',  '\n', NO,   'A',  'S',	'D',  'F',  'G',  'H',  'J',  'K',  'L',  ':',	// 0x20	'"',  '~',  NO,   '|',  'Z',  'X',  'C',  'V',	'B',  'N',  'M',  '<',  '>',  '?',  NO,   '*',	// 0x30	NO,   ' ',  NO,   NO,   NO,   NO,   NO,   NO,	NO,   NO,   NO,   NO,   NO,   NO,   NO,   '7',	// 0x40	'8',  '9',  '-',  '4',  '5',  '6',  '+',  '1',	'2',  '3',  '0',  '.',  NO,   NO,   NO,   NO,	// 0x50	[0xC7] KEY_HOME,	[0x9C] '\n' /*KP_Enter*/,	[0xB5] '/' /*KP_Div*/,	[0xC8] KEY_UP,	[0xC9] KEY_PGUP,	[0xCB] KEY_LF,	[0xCD] KEY_RT,		[0xCF] KEY_END,	[0xD0] KEY_DN,		[0xD1] KEY_PGDN,	[0xD2] KEY_INS,		[0xD3] KEY_DEL};#define C(x) (x - '@')static uint8_t ctlmap[256] = {	NO,      NO,      NO,      NO,      NO,      NO,      NO,      NO, 	NO,      NO,      NO,      NO,      NO,      NO,      NO,      NO, 	C('Q'),  C('W'),  C('E'),  C('R'),  C('T'),  C('Y'),  C('U'),  C('I'),	C('O'),  C('P'),  NO,      NO,      '\r',    NO,      C('A'),  C('S'),	C('D'),  C('F'),  C('G'),  C('H'),  C('J'),  C('K'),  C('L'),  NO, 	NO,      NO,      NO,      C('\\'), C('Z'),  C('X'),  C('C'),  C('V'),	C('B'),  C('N'),  C('M'),  NO,      NO,      C('/'),  NO,      NO,	[0x97] KEY_HOME,	[0xB5] C('/'),		[0xC8] KEY_UP,	[0xC9] KEY_PGUP,	[0xCB] KEY_LF,	[0xCD] KEY_RT,		[0xCF] KEY_END,	[0xD0] KEY_DN,		[0xD1] KEY_PGDN,	[0xD2] KEY_INS,		[0xD3] KEY_DEL};static uint8_t *charcode[4] = {	normalmap,	shiftmap,	ctlmap,	ctlmap};/* * Get data from the keyboard.  If we finish a character, return it.  Else 0. * Return -1 if no data. */static intkbd_proc_data(void){	int c;	uint8_t data;	static uint32_t shift;	if ((inb(KBSTATP) & KBS_DIB) == 0)		return -1;	data = inb(KBDATAP);	if (data == 0xE0) {		// E0 escape character		shift |= E0ESC;		return 0;	} else if (data & 0x80) {		// Key released		data = (shift & E0ESC ? data : data & 0x7F);		shift &= ~(shiftcode[data] | E0ESC);		return 0;	} else if (shift & E0ESC) {		// Last character was an E0 escape; or with 0x80		data |= 0x80;		shift &= ~E0ESC;	}	shift |= shiftcode[data];	shift ^= togglecode[data];	c = charcode[shift & (CTL | SHIFT)][data];	if (shift & CAPSLOCK) {		if ('a' <= c && c <= 'z')			c += 'A' - 'a';		else if ('A' <= c && c <= 'Z')			c += 'a' - 'A';	}	// Process special keys	// Ctrl-Alt-Del: reboot	if (!(~shift & (CTL | ALT)) && c == KEY_DEL) {		cprintf("Rebooting!\n");		outb(0x92, 0x3); // courtesy of Chris Frost	}	return c;}voidkbd_intr(void){	cons_intr(kbd_proc_data);}voidkbd_init(void){}/***** General device-independent console code *****/// Here we manage the console input buffer,// where we stash characters received from the keyboard or serial port// whenever the corresponding interrupt occurs.#define CONSBUFSIZE 512static struct {	uint8_t buf[CONSBUFSIZE];	uint32_t rpos;	uint32_t wpos;} cons;// called by device interrupt routines to feed input characters// into the circular console input buffer.voidcons_intr(int (*proc)(void)){	int c;	while ((c = (*proc)()) != -1) {		if (c == 0)			continue;		cons.buf[cons.wpos++] = c;		if (cons.wpos == CONSBUFSIZE)			cons.wpos = 0;	}}// return the next input character from the console, or 0 if none waitingintcons_getc(void){	int c;	// poll for any pending input characters,	// so that this function works even when interrupts are disabled	// (e.g., when called from the kernel monitor).	serial_intr();	kbd_intr();	// grab the next character from the input buffer.	if (cons.rpos != cons.wpos) {		c = cons.buf[cons.rpos++];		if (cons.rpos == CONSBUFSIZE)			cons.rpos = 0;		return c;	}	return 0;}// output a character to the consolevoidcons_putc(int c){	lpt_putc(c);	cga_putc(c);}// initialize the console devicesvoidcons_init(void){	cga_init();	kbd_init();	serial_init();	if (!serial_exists)		cprintf("Serial port does not exist!\n");}// `High'-level console I/O.  Used by readline and cprintf.voidcputchar(int c){	cons_putc(c);}intgetchar(void){	int c;	while ((c = cons_getc()) == 0)		/* do nothing */;	return c;}intiscons(int fdnum){	// used by readline	return 1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -