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

📄 kbd.c

📁 开源的BIOS启动软件
💻 C
字号:
#include <bios/types.h>#include <bios/time.h>#include <bios/pci.h>#include <bios/stdio.h>#include <bios/stdioint.h>#include <bios/timer.h>#define inb(r)		pci_io_read_byte((r))#define outb(v,r)	pci_io_write_byte((v),(r))/* * Keyboard Controller Registers */#define KBD_STATUS_REG	0x64	/* Status register (R) */#define KBD_CNTL_REG	0x64	/* Controller command register (W) */#define KBD_DATA_REG	0x60	/* Keyboard data register (R/W) *//* * Keyboard Controller Commands */#define KBD_CCMD_READ_MODE	0x20#define KBD_CCMD_WRITE_MODE	0x60#define KBD_CCMD_GET_VERSION	0xa1#define KBD_CCMD_MOUSE_DISABLE	0xa7#define KBD_CCMD_MOUSE_ENABLE	0xa8#define KBD_CCMD_TEST_MOUSE	0xa9#define KBD_CCMD_SELF_TEST	0xaa#define KBD_CCMD_KBD_TEST	0xab#define KBD_CCMD_KBD_DISABLE	0xad#define KBD_CCMD_KBD_ENABLE	0xae#define KBD_CCMD_WRITE_AUX_OBUF	0xd3#define KBD_CCMD_WRITE_MOUSE	0xd4/* * Keyboard Commands */#define KBD_CMD_SET_LEDS	0xed#define KBD_CMD_SET_RATE	0xf3#define KBD_CMD_ENABLE		0xf4#define KBD_CMD_DISABLE		0xf5#define KBD_CMD_RESET		0xff/* * Keyboard Replies */#define KBD_REPLY_POR		0xaa#define KBD_REPLY_ACK		0xfa#define KBD_REPLY_RESEND	0xfe/* * Status Register Bits */#define KBD_STAT_OBF		0x01#define KBD_STAT_IBF		0x02#define KBD_STAT_SELFTEST	0x04#define KBD_STAT_CMD		0x08#define KBD_STAT_UNLOCKED	0x10#define KBD_STAT_MOUSE_OBF	0x20#define KBD_STAT_GTO		0x40#define KBD_STAT_PERR		0x80/* * Controller mode register bits */#define KBD_MODE_KBD_INT	0x01#define KBD_MODE_MOUSE_INT	0x02#define KBD_MODE_SYS		0x04#define KBD_MODE_NO_KEYLOCK	0x08#define KBD_MODE_DISABLE_KBD	0x10#define KBD_MODE_DISABLE_MOUSE	0x20#define KBD_MODE_KCC		0x40#define KBD_MODE_RFU		0x80#define KBD_NO_DATA	(-1)#define KBD_BAD_DATA	(-2)static volatile unsigned char reply_expected;static volatile unsigned char acknowledge;static volatile unsigned char resend;static volatile unsigned char read_ch;static const char kbd_table[] = {/*00*/	0x00, 0x1b, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,/*08*/	0x37, 0x38, 0x39, 0x30, 0x2d, 0x3d, 0x7f, 0x09,/*10*/	0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69,/*18*/	0x6f, 0x70, 0x5b, 0x5d, 0x0a, 0x00, 0x61, 0x73,/*20*/	0x64, 0x66, 0x67, 0x68, 0x6a, 0x6b, 0x6c, 0x3b,/*28*/	0x27, 0x60, 0x00, 0x5c, 0x7a, 0x78, 0x63, 0x76,/*30*/	0x62, 0x6e, 0x6d, 0x2c, 0x2e, 0x2f, 0x00, 0x00,/*38*/	0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,/*40*/	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,/*48*/	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,/*50*/	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00,/*58*/	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,/*60*/	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,/*68*/	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,/*70*/	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,/*78*/	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};static void handle_scancode(int scancode, int up){	if (up)		return;	read_ch = kbd_table[scancode & 0x7f];}static int do_acknowledge(unsigned char scancode){	if (reply_expected) {		switch (scancode) {		case KBD_REPLY_ACK:			acknowledge = 1;			reply_expected = 0;			return 0;		case KBD_REPLY_RESEND:			resend = 1;			reply_expected = 0;			return 0;		default:			break;		}	}	return 1;}static unsigned char handle_kbd_event(void){	unsigned char status = inb(KBD_STATUS_REG);	int work = 1000;	while (status & KBD_STAT_OBF && work--) {		unsigned char scancode;		scancode = inb(KBD_DATA_REG);		if (do_acknowledge(scancode))			handle_scancode(scancode, !(scancode & 0x80));		status = inb(KBD_STATUS_REG);	}	return status;}static void kb_wait(void){	int timeout = 10;	do {		unsigned char status = handle_kbd_event();		if (!(status & KBD_STAT_IBF))			return;		wait_cs(1);	} while (--timeout);	printf("Keyboard timed out\n");}static int kbd_read_input(void){	int retval = KBD_NO_DATA;	unsigned char status;	status = inb(KBD_STATUS_REG);	if (status & KBD_STAT_OBF) {		unsigned char data = inb(KBD_DATA_REG);		retval = data;		if (status & (KBD_STAT_GTO | KBD_STAT_PERR))			retval = KBD_BAD_DATA;	}	return retval;}static void kbd_clear_input(void){	int maxread = 100;	/* Random number */	do {		if (kbd_read_input() == KBD_NO_DATA)			break;	} while (--maxread);}static int kbd_wait_for_input(void){	long timeout = 100;	do {		int retval = kbd_read_input();		if (retval >= 0)			return retval;		wait_cs(1);	} while (--timeout);	return -1;}static void kbd_write(int address, int data){	kb_wait();	outb(data, address);}static int init_kbd_hw(void){	int status;	/*	 * Test the keyboard interface.	 * This seems to be the only way to get it going.	 * If the test is successful a x55 is placed in the input buffer.	 */	kbd_write(KBD_CNTL_REG, KBD_CCMD_SELF_TEST);	if (kbd_wait_for_input() != 0x55) {		printf("Keyboard failed self test\n");		return 1;	}	/*	 * Perform a keyboard interface test.  This causes the controller	 * to test the keyboard clock and data lines.  The results of the	 * test are placed in the input buffer.	 */	kbd_write(KBD_CNTL_REG, KBD_CCMD_KBD_TEST);	if (kbd_wait_for_input() != 0x00) {		printf("Keyboard interface failed self test");		return 1;	}	/*	 * Enable the keyboard by allowing the keyboard clock to run.	 */	kbd_write(KBD_CNTL_REG, KBD_CCMD_KBD_ENABLE);	/*	 * Reset keyboard. If the read times out	 * then the assumption is that no keyboard is	 * plugged into the machine.	 * This defaults the keyboard to scan-code set 2.	 *	 * Set up to try again if the keyboard asks for RESEND.	 */	do {		kbd_write(KBD_DATA_REG, KBD_CMD_RESET);		status = kbd_wait_for_input();		if (status == KBD_REPLY_ACK)			break;		if (status != KBD_REPLY_RESEND) {			printf("Keyboard reset failed, no ACK: %02X\n", status);			return 1;		}	} while (1);	if (kbd_wait_for_input() != KBD_REPLY_POR) {		printf("Keyboard reset failed, no POR\n");		return 1;	}	/*	 * Set keyboard controller mode. During this, the keyboard should be	 * in the disabled state.	 *	 * Set up to try again if the keyboard asks for RESEND.	 */	do {		kbd_write(KBD_DATA_REG, KBD_CMD_DISABLE);		status = kbd_wait_for_input();		if (status == KBD_REPLY_ACK)			break;		if (status != KBD_REPLY_RESEND) {			printf("Disable keyboard failed, no ACK: %02X\n", status);			return 1;		}	} while (1);	kbd_write(KBD_CNTL_REG, KBD_CCMD_WRITE_MODE);	kbd_write(KBD_DATA_REG, KBD_MODE_KBD_INT|KBD_MODE_SYS|KBD_MODE_DISABLE_MOUSE|KBD_MODE_KCC);	/* ibm powerpc portables need this to use scan-code set 1 -- Cort */	kbd_write(KBD_CNTL_REG, KBD_CCMD_READ_MODE);	if (!(kbd_wait_for_input() & KBD_MODE_KCC)) {		/*		 * If the controller does not support conversion,		 * Set the keyboard to scan-code set 1.		 */		kbd_write(KBD_DATA_REG, 0xF0);		kbd_wait_for_input();		kbd_write(KBD_DATA_REG, 0x01);		kbd_wait_for_input();	}	kbd_write(KBD_DATA_REG, KBD_CMD_ENABLE);	if (kbd_wait_for_input() != KBD_REPLY_ACK) {		printf("Enable keyboard: no ACK\n");		return 1;	}	/*	 * Finally, set the typematic rate to maximum.	 */	kbd_write(KBD_DATA_REG, KBD_CMD_SET_RATE);	if (kbd_wait_for_input() != KBD_REPLY_ACK)		printf("Set rate: no ACK\n");	else {		kbd_write(KBD_DATA_REG, 0x00);		if (kbd_wait_for_input() != KBD_REPLY_ACK)			printf("Set rate: no ACK\n");	}	return 0;}int kbd_read(char *buffer, int nr){	int used = 0;	do {		handle_kbd_event();		if (read_ch) {			buffer[used++] = read_ch;			read_ch = 0;			nr -= 1;		} else if (timers[KEY_TIMER].status)			break;	} while (nr);	return used;}void kbd_init(void){	/* flush any pending input */	kbd_clear_input();	if (!init_kbd_hw())		stdfn.read = kbd_read;}

⌨️ 快捷键说明

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