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

📄 pckbd.c

📁 qemu虚拟机代码
💻 C
字号:
/* * QEMU PC keyboard emulation *  * Copyright (c) 2003 Fabrice Bellard *  * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */#include "vl.h"/* debug PC keyboard *///#define DEBUG_KBD/* debug PC keyboard : only mouse *///#define DEBUG_MOUSE/*	Keyboard Controller Commands */#define KBD_CCMD_READ_MODE	0x20	/* Read mode bits */#define KBD_CCMD_WRITE_MODE	0x60	/* Write mode bits */#define KBD_CCMD_GET_VERSION	0xA1	/* Get controller version */#define KBD_CCMD_MOUSE_DISABLE	0xA7	/* Disable mouse interface */#define KBD_CCMD_MOUSE_ENABLE	0xA8	/* Enable mouse interface */#define KBD_CCMD_TEST_MOUSE	0xA9	/* Mouse interface test */#define KBD_CCMD_SELF_TEST	0xAA	/* Controller self test */#define KBD_CCMD_KBD_TEST	0xAB	/* Keyboard interface test */#define KBD_CCMD_KBD_DISABLE	0xAD	/* Keyboard interface disable */#define KBD_CCMD_KBD_ENABLE	0xAE	/* Keyboard interface enable */#define KBD_CCMD_READ_INPORT    0xC0    /* read input port */#define KBD_CCMD_READ_OUTPORT	0xD0    /* read output port */#define KBD_CCMD_WRITE_OUTPORT	0xD1    /* write output port */#define KBD_CCMD_WRITE_OBUF	0xD2#define KBD_CCMD_WRITE_AUX_OBUF	0xD3    /* Write to output buffer as if					   initiated by the auxiliary device */#define KBD_CCMD_WRITE_MOUSE	0xD4	/* Write the following byte to the mouse */#define KBD_CCMD_DISABLE_A20    0xDD    /* HP vectra only ? */#define KBD_CCMD_ENABLE_A20     0xDF    /* HP vectra only ? */#define KBD_CCMD_RESET	        0xFE/* Keyboard Commands */#define KBD_CMD_SET_LEDS	0xED	/* Set keyboard leds */#define KBD_CMD_ECHO     	0xEE#define KBD_CMD_GET_ID 	        0xF2	/* get keyboard ID */#define KBD_CMD_SET_RATE	0xF3	/* Set typematic rate */#define KBD_CMD_ENABLE		0xF4	/* Enable scanning */#define KBD_CMD_RESET_DISABLE	0xF5	/* reset and disable scanning */#define KBD_CMD_RESET_ENABLE   	0xF6    /* reset and enable scanning */#define KBD_CMD_RESET		0xFF	/* Reset *//* Keyboard Replies */#define KBD_REPLY_POR		0xAA	/* Power on reset */#define KBD_REPLY_ACK		0xFA	/* Command ACK */#define KBD_REPLY_RESEND	0xFE	/* Command NACK, send the cmd again *//* Status Register Bits */#define KBD_STAT_OBF 		0x01	/* Keyboard output buffer full */#define KBD_STAT_IBF 		0x02	/* Keyboard input buffer full */#define KBD_STAT_SELFTEST	0x04	/* Self test successful */#define KBD_STAT_CMD		0x08	/* Last write was a command write (0=data) */#define KBD_STAT_UNLOCKED	0x10	/* Zero if keyboard locked */#define KBD_STAT_MOUSE_OBF	0x20	/* Mouse output buffer full */#define KBD_STAT_GTO 		0x40	/* General receive/xmit timeout */#define KBD_STAT_PERR 		0x80	/* Parity error *//* Controller Mode Register Bits */#define KBD_MODE_KBD_INT	0x01	/* Keyboard data generate IRQ1 */#define KBD_MODE_MOUSE_INT	0x02	/* Mouse data generate IRQ12 */#define KBD_MODE_SYS 		0x04	/* The system flag (?) */#define KBD_MODE_NO_KEYLOCK	0x08	/* The keylock doesn't affect the keyboard if set */#define KBD_MODE_DISABLE_KBD	0x10	/* Disable keyboard interface */#define KBD_MODE_DISABLE_MOUSE	0x20	/* Disable mouse interface */#define KBD_MODE_KCC 		0x40	/* Scan code conversion to PC format */#define KBD_MODE_RFU		0x80/* Mouse Commands */#define AUX_SET_SCALE11		0xE6	/* Set 1:1 scaling */#define AUX_SET_SCALE21		0xE7	/* Set 2:1 scaling */#define AUX_SET_RES		0xE8	/* Set resolution */#define AUX_GET_SCALE		0xE9	/* Get scaling factor */#define AUX_SET_STREAM		0xEA	/* Set stream mode */#define AUX_POLL		0xEB	/* Poll */#define AUX_RESET_WRAP		0xEC	/* Reset wrap mode */#define AUX_SET_WRAP		0xEE	/* Set wrap mode */#define AUX_SET_REMOTE		0xF0	/* Set remote mode */#define AUX_GET_TYPE		0xF2	/* Get type */#define AUX_SET_SAMPLE		0xF3	/* Set sample rate */#define AUX_ENABLE_DEV		0xF4	/* Enable aux device */#define AUX_DISABLE_DEV		0xF5	/* Disable aux device */#define AUX_SET_DEFAULT		0xF6#define AUX_RESET		0xFF	/* Reset aux device */#define AUX_ACK			0xFA	/* Command byte ACK. */#define MOUSE_STATUS_REMOTE     0x40#define MOUSE_STATUS_ENABLED    0x20#define MOUSE_STATUS_SCALE21    0x10#define KBD_QUEUE_SIZE 256#define KBD_PENDING_KBD         1#define KBD_PENDING_AUX         2typedef struct KBDState {    uint8_t write_cmd; /* if non zero, write data to port 60 is expected */    uint8_t status;    uint8_t mode;    /* Bitmask of devices with data available.  */    uint8_t pending;    void *kbd;    void *mouse;} KBDState;KBDState kbd_state;/* update irq and KBD_STAT_[MOUSE_]OBF *//* XXX: not generating the irqs if KBD_MODE_DISABLE_KBD is set may be   incorrect, but it avoids having to simulate exact delays */static void kbd_update_irq(KBDState *s){    int irq12_level, irq1_level;    irq1_level = 0;        irq12_level = 0;        s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);    if (s->pending) {        s->status |= KBD_STAT_OBF;        /* kdb data takes priority over aux data.  */        if (s->pending == KBD_PENDING_AUX) {            s->status |= KBD_STAT_MOUSE_OBF;            if (s->mode & KBD_MODE_MOUSE_INT)                irq12_level = 1;        } else {            if ((s->mode & KBD_MODE_KBD_INT) &&                 !(s->mode & KBD_MODE_DISABLE_KBD))                irq1_level = 1;        }    }    pic_set_irq(1, irq1_level);    pic_set_irq(12, irq12_level);}static void kbd_update_kbd_irq(void *opaque, int level){    KBDState *s = (KBDState *)opaque;    if (level)        s->pending |= KBD_PENDING_KBD;    else        s->pending &= ~KBD_PENDING_KBD;    kbd_update_irq(s);}static void kbd_update_aux_irq(void *opaque, int level){    KBDState *s = (KBDState *)opaque;    if (level)        s->pending |= KBD_PENDING_AUX;    else        s->pending &= ~KBD_PENDING_AUX;    kbd_update_irq(s);}static uint32_t kbd_read_status(void *opaque, uint32_t addr){    KBDState *s = opaque;    int val;    val = s->status;#if defined(DEBUG_KBD)    printf("kbd: read status=0x%02x\n", val);#endif    return val;}static void kbd_queue(KBDState *s, int b, int aux){    if (aux)        ps2_queue(s->mouse, b);    else        ps2_queue(s->kbd, b);}static void kbd_write_command(void *opaque, uint32_t addr, uint32_t val){    KBDState *s = opaque;#ifdef DEBUG_KBD    printf("kbd: write cmd=0x%02x\n", val);#endif    switch(val) {    case KBD_CCMD_READ_MODE:        kbd_queue(s, s->mode, 0);        break;    case KBD_CCMD_WRITE_MODE:    case KBD_CCMD_WRITE_OBUF:    case KBD_CCMD_WRITE_AUX_OBUF:    case KBD_CCMD_WRITE_MOUSE:    case KBD_CCMD_WRITE_OUTPORT:        s->write_cmd = val;        break;    case KBD_CCMD_MOUSE_DISABLE:        s->mode |= KBD_MODE_DISABLE_MOUSE;        break;    case KBD_CCMD_MOUSE_ENABLE:        s->mode &= ~KBD_MODE_DISABLE_MOUSE;        break;    case KBD_CCMD_TEST_MOUSE:        kbd_queue(s, 0x00, 0);        break;    case KBD_CCMD_SELF_TEST:        s->status |= KBD_STAT_SELFTEST;        kbd_queue(s, 0x55, 0);        break;    case KBD_CCMD_KBD_TEST:        kbd_queue(s, 0x00, 0);        break;    case KBD_CCMD_KBD_DISABLE:        s->mode |= KBD_MODE_DISABLE_KBD;        kbd_update_irq(s);        break;    case KBD_CCMD_KBD_ENABLE:        s->mode &= ~KBD_MODE_DISABLE_KBD;        kbd_update_irq(s);        break;    case KBD_CCMD_READ_INPORT:        kbd_queue(s, 0x00, 0);        break;    case KBD_CCMD_READ_OUTPORT:        /* XXX: check that */#ifdef TARGET_I386        val = 0x01 | (ioport_get_a20() << 1);#else        val = 0x01;#endif        if (s->status & KBD_STAT_OBF)            val |= 0x10;        if (s->status & KBD_STAT_MOUSE_OBF)            val |= 0x20;        kbd_queue(s, val, 0);        break;#ifdef TARGET_I386    case KBD_CCMD_ENABLE_A20:        ioport_set_a20(1);        break;    case KBD_CCMD_DISABLE_A20:        ioport_set_a20(0);        break;#endif    case KBD_CCMD_RESET:        qemu_system_reset_request();        break;    case 0xff:        /* ignore that - I don't know what is its use */        break;    default:        fprintf(stderr, "qemu: unsupported keyboard cmd=0x%02x\n", val);        break;    }}static uint32_t kbd_read_data(void *opaque, uint32_t addr){    KBDState *s = opaque;    if (s->pending == KBD_PENDING_AUX)        return ps2_read_data(s->mouse);    return ps2_read_data(s->kbd);}void kbd_write_data(void *opaque, uint32_t addr, uint32_t val){    KBDState *s = opaque;#ifdef DEBUG_KBD    printf("kbd: write data=0x%02x\n", val);#endif    switch(s->write_cmd) {    case 0:        ps2_write_keyboard(s->kbd, val);        break;    case KBD_CCMD_WRITE_MODE:        s->mode = val;        ps2_keyboard_set_translation(s->kbd, (s->mode & KBD_MODE_KCC) != 0);        /* ??? */        kbd_update_irq(s);        break;    case KBD_CCMD_WRITE_OBUF:        kbd_queue(s, val, 0);        break;    case KBD_CCMD_WRITE_AUX_OBUF:        kbd_queue(s, val, 1);        break;    case KBD_CCMD_WRITE_OUTPORT:#ifdef TARGET_I386        ioport_set_a20((val >> 1) & 1);#endif        if (!(val & 1)) {            qemu_system_reset_request();        }        break;    case KBD_CCMD_WRITE_MOUSE:        ps2_write_mouse(s->mouse, val);        break;    default:        break;    }    s->write_cmd = 0;}static void kbd_reset(void *opaque){    KBDState *s = opaque;    s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT;    s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED;}static void kbd_save(QEMUFile* f, void* opaque){    KBDState *s = (KBDState*)opaque;        qemu_put_8s(f, &s->write_cmd);    qemu_put_8s(f, &s->status);    qemu_put_8s(f, &s->mode);    qemu_put_8s(f, &s->pending);}static int kbd_load(QEMUFile* f, void* opaque, int version_id){    KBDState *s = (KBDState*)opaque;        if (version_id != 3)        return -EINVAL;    qemu_get_8s(f, &s->write_cmd);    qemu_get_8s(f, &s->status);    qemu_get_8s(f, &s->mode);    qemu_get_8s(f, &s->pending);    return 0;}void kbd_init(void){    KBDState *s = &kbd_state;        kbd_reset(s);    register_savevm("pckbd", 0, 3, kbd_save, kbd_load, s);    register_ioport_read(0x60, 1, 1, kbd_read_data, s);    register_ioport_write(0x60, 1, 1, kbd_write_data, s);    register_ioport_read(0x64, 1, 1, kbd_read_status, s);    register_ioport_write(0x64, 1, 1, kbd_write_command, s);    s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s);    s->mouse = ps2_mouse_init(kbd_update_aux_irq, s);    qemu_register_reset(kbd_reset, s);}

⌨️ 快捷键说明

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