Esempio n. 1
0
/*
 * Called when the OS reads from port 0x60 (PS/2 data)
 */
static u32 kbd_read_data(void)
{
	u32 ret;
	int i;

	if (state.kcount != 0) {
		/* Keyboard data gets read first */
		ret = state.kq[state.kread++ % QUEUE_SIZE];
		state.kcount--;
		kvm__irq_line(state.kvm, KBD_IRQ, 0);
		kbd_update_irq();
	} else if (state.mcount > 0) {
		/* Followed by the mouse */
		ret = state.mq[state.mread++ % QUEUE_SIZE];
		state.mcount--;
		kvm__irq_line(state.kvm, AUX_IRQ, 0);
		kbd_update_irq();
	} else {
		i = state.kread - 1;
		if (i < 0)
			i = QUEUE_SIZE;
		ret = state.kq[i];
	}
	return ret;
}
Esempio n. 2
0
static void kbd_write_data(void *opaque, hwaddr addr,
                           uint64_t val, unsigned size)
{
    KBDState *s = opaque;

    DPRINTF("kbd: write data=0x%02" PRIx64 "\n", val);

    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:
        outport_write(s, val);
        break;
    case KBD_CCMD_WRITE_MOUSE:
        ps2_write_mouse(s->mouse, val);
        break;
    default:
        break;
    }
    s->write_cmd = 0;
}
Esempio n. 3
0
/*
 * Add a byte to the keyboard queue, then set IRQs
 */
void kbd_queue(u8 c)
{
	if (state.kcount >= QUEUE_SIZE)
		return;

	state.kq[state.kwrite++ % QUEUE_SIZE] = c;

	state.kcount++;
	kbd_update_irq();
}
Esempio n. 4
0
/*
 * Add a byte to the mouse queue, then set IRQs
 */
void mouse_queue(u8 c)
{
	if (state.mcount >= QUEUE_SIZE)
		return;

	state.mq[state.mwrite++ % QUEUE_SIZE] = c;

	state.mcount++;
	kbd_update_irq();
}
Esempio n. 5
0
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);
}
Esempio n. 6
0
static 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;
}
Esempio n. 7
0
static uint32_t kbd_read_data(void *opaque, uint32_t addr)
{
    KBDState *s = (KBDState*)opaque;
    uint32_t val;
    NOREF(addr);

    /* Return the current DBB contents. */
    val = s->dbbout;

    /* Reading the DBB deasserts IRQs... */
    if (s->status & KBD_STAT_MOUSE_OBF)
        PDMDevHlpISASetIrq(s->CTX_SUFF(pDevIns), 12, 0);
    else
        PDMDevHlpISASetIrq(s->CTX_SUFF(pDevIns), 1, 0);
    /* ...and clears the OBF bits. */
    s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);

    /* Check if more data is available. */
    kbd_update_irq(s);
#ifdef DEBUG_KBD
    Log(("kbd: read data=0x%02x\n", val));
#endif
    return val;
}
Esempio n. 8
0
/*
 * Called when the OS writes to port 0x60 (data port)
 * Things written here are generally arguments to commands previously
 * written to port 0x64 and stored in state.write_cmd
 */
static void kbd_write_data(u32 val)
{
	switch (state.write_cmd) {
	case I8042_CMD_CTL_WCTR:
		state.mode = val;
		kbd_update_irq();
		break;
	case I8042_CMD_AUX_LOOP:
		mouse_queue(val);
		mouse_queue(RESPONSE_ACK);
		break;
	case I8042_CMD_AUX_SEND:
		/* The OS wants to send a command to the mouse */
		mouse_queue(RESPONSE_ACK);
		switch (val) {
		case 0xe6:
			/* set scaling = 1:1 */
			state.mstatus &= ~AUX_SCALING_FLAG;
			break;
		case 0xe8:
			/* set resolution */
			state.mres = val;
			break;
		case 0xe9:
			/* Report mouse status/config */
			mouse_queue(state.mstatus);
			mouse_queue(state.mres);
			mouse_queue(state.msample);
			break;
		case 0xf2:
			/* send ID */
			mouse_queue(0); /* normal mouse */
			break;
		case 0xf3:
			/* set sample rate */
			state.msample = val;
			break;
		case 0xf4:
			/* enable reporting */
			state.mstatus |= AUX_ENABLE_REPORTING;
			break;
		case 0xf5:
			state.mstatus &= ~AUX_ENABLE_REPORTING;
			break;
		case 0xf6:
			/* set defaults, just fall through to reset */
		case 0xff:
			/* reset */
			state.mstatus = 0x0;
			state.mres = AUX_DEFAULT_RESOLUTION;
			state.msample = AUX_DEFAULT_SAMPLE;
			break;
		default:
			break;
	}
	break;
	case 0:
		/* Just send the ID */
		kbd_queue(RESPONSE_ACK);
		kbd_queue(0xab);
		kbd_queue(0x41);
		kbd_update_irq();
		break;
	default:
		/* Yeah whatever */
		break;
	}
	state.write_cmd = 0;
}
Esempio n. 9
0
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;
    }
}
Esempio n. 10
0
static void kbd_write_command(void *opaque, hwaddr addr,
                              uint64_t val, unsigned size)
{
    KBDState *s = opaque;

    DPRINTF("kbd: write cmd=0x%02" PRIx64 "\n", val);

    /* Bits 3-0 of the output port P2 of the keyboard controller may be pulsed
     * low for approximately 6 micro seconds. Bits 3-0 of the KBD_CCMD_PULSE
     * command specify the output port bits to be pulsed.
     * 0: Bit should be pulsed. 1: Bit should not be modified.
     * The only useful version of this command is pulsing bit 0,
     * which does a CPU reset.
     */
    if((val & KBD_CCMD_PULSE_BITS_3_0) == KBD_CCMD_PULSE_BITS_3_0) {
        if(!(val & 1))
            val = KBD_CCMD_RESET;
        else
            val = KBD_CCMD_NO_OP;
    }

    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, 0x80, 0);
        break;
    case KBD_CCMD_READ_OUTPORT:
        kbd_queue(s, s->outport, 0);
        break;
    case KBD_CCMD_ENABLE_A20:
        qemu_irq_raise(s->a20_out);
        s->outport |= KBD_OUT_A20;
        break;
    case KBD_CCMD_DISABLE_A20:
        qemu_irq_lower(s->a20_out);
        s->outport &= ~KBD_OUT_A20;
        break;
    case KBD_CCMD_RESET:
        qemu_system_reset_request();
        break;
    case KBD_CCMD_NO_OP:
        /* ignore that */
        break;
    default:
        fprintf(stderr, "qemu: unsupported keyboard cmd=0x%02x\n", (int)val);
        break;
    }
}
Esempio n. 11
0
static int kbd_write_command(void *opaque, uint32_t addr, uint32_t val)
{
    int rc = VINF_SUCCESS;
    KBDState *s = (KBDState*)opaque;
    NOREF(addr);

#ifdef DEBUG_KBD
    Log(("kbd: write cmd=0x%02x\n", val));
#endif
    switch(val) {
    case KBD_CCMD_READ_MODE:
        kbc_dbb_out(s, s->mode);
        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;
        /* Check for queued input. */
        kbd_update_irq(s);
        break;
    case KBD_CCMD_TEST_MOUSE:
        kbc_dbb_out(s, 0x00);
        break;
    case KBD_CCMD_SELF_TEST:
        /* Enable the A20 line - that is the power-on state(!). */
# ifndef IN_RING3
        if (!PDMDevHlpA20IsEnabled(s->CTX_SUFF(pDevIns)))
        {
            rc = VINF_IOM_R3_IOPORT_WRITE;
            break;
        }
# else /* IN_RING3 */
        PDMDevHlpA20Set(s->CTX_SUFF(pDevIns), true);
# endif /* IN_RING3 */
        s->status |= KBD_STAT_SELFTEST;
        s->mode |= KBD_MODE_DISABLE_KBD;
        kbc_dbb_out(s, 0x55);
        break;
    case KBD_CCMD_KBD_TEST:
        kbc_dbb_out(s, 0x00);
        break;
    case KBD_CCMD_KBD_DISABLE:
        s->mode |= KBD_MODE_DISABLE_KBD;
        break;
    case KBD_CCMD_KBD_ENABLE:
        s->mode &= ~KBD_MODE_DISABLE_KBD;
        /* Check for queued input. */
        kbd_update_irq(s);
        break;
    case KBD_CCMD_READ_INPORT:
        kbc_dbb_out(s, 0xBF);
        break;
    case KBD_CCMD_READ_OUTPORT:
        /* XXX: check that */
#ifdef TARGET_I386
        val = 0x01 | (PDMDevHlpA20IsEnabled(s->CTX_SUFF(pDevIns)) << 1);
#else
        val = 0x01;
#endif
        if (s->status & KBD_STAT_OBF)
            val |= 0x10;
        if (s->status & KBD_STAT_MOUSE_OBF)
            val |= 0x20;
        kbc_dbb_out(s, val);
        break;
#ifdef TARGET_I386
    case KBD_CCMD_ENABLE_A20:
# ifndef IN_RING3
        if (!PDMDevHlpA20IsEnabled(s->CTX_SUFF(pDevIns)))
            rc = VINF_IOM_R3_IOPORT_WRITE;
# else /* IN_RING3 */
        PDMDevHlpA20Set(s->CTX_SUFF(pDevIns), true);
# endif /* IN_RING3 */
        break;
    case KBD_CCMD_DISABLE_A20:
# ifndef IN_RING3
        if (PDMDevHlpA20IsEnabled(s->CTX_SUFF(pDevIns)))
            rc = VINF_IOM_R3_IOPORT_WRITE;
# else /* IN_RING3 */
        PDMDevHlpA20Set(s->CTX_SUFF(pDevIns), false);
# endif /* !IN_RING3 */
        break;
#endif
    case KBD_CCMD_READ_TSTINP:
        /* Keyboard clock line is zero IFF keyboard is disabled */
        val = (s->mode & KBD_MODE_DISABLE_KBD) ? 0 : 1;
        kbc_dbb_out(s, val);
        break;
    case KBD_CCMD_RESET:
    case KBD_CCMD_RESET_ALT:
#ifndef IN_RING3
        rc = VINF_IOM_R3_IOPORT_WRITE;
#else /* IN_RING3 */
        LogRel(("Reset initiated by keyboard controller\n"));
        rc = PDMDevHlpVMReset(s->CTX_SUFF(pDevIns), PDMVMRESET_F_KBD);
#endif /* !IN_RING3 */
        break;
    case 0xff:
        /* ignore that - I don't know what is its use */
        break;
    /* Make OS/2 happy. */
    /* The 8042 RAM is readable using commands 0x20 thru 0x3f, and writable
       by 0x60 thru 0x7f. Now days only the first byte, the mode, is used.
       We'll ignore the writes (0x61..7f) and return 0 for all the reads
       just to make some OS/2 debug stuff a bit happier. */
    case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
    case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
    case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
    case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
        kbc_dbb_out(s, 0);
        Log(("kbd: reading non-standard RAM addr %#x\n", val & 0x1f));
        break;
    default:
        Log(("kbd: unsupported keyboard cmd=0x%02x\n", val));
        break;
    }
    return rc;
}
Esempio n. 12
0
void KBCUpdateInterrupts(void *pKbc)
{
    KBDState    *s = (KBDState *)pKbc;
    kbd_update_irq(s);
}