mirror of https://gitee.com/openkylin/qemu.git
keyboard irq generation fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@778 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
0294ffb9c8
commit
6f51f6b593
33
hw/pckbd.c
33
hw/pckbd.c
|
@ -111,12 +111,13 @@
|
||||||
#define KBD_QUEUE_SIZE 256
|
#define KBD_QUEUE_SIZE 256
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
uint8_t aux[KBD_QUEUE_SIZE];
|
||||||
uint8_t data[KBD_QUEUE_SIZE];
|
uint8_t data[KBD_QUEUE_SIZE];
|
||||||
int rptr, wptr, count;
|
int rptr, wptr, count;
|
||||||
} KBDQueue;
|
} KBDQueue;
|
||||||
|
|
||||||
typedef struct KBDState {
|
typedef struct KBDState {
|
||||||
KBDQueue queues[2];
|
KBDQueue queue;
|
||||||
uint8_t write_cmd; /* if non zero, write data to port 60 is expected */
|
uint8_t write_cmd; /* if non zero, write data to port 60 is expected */
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
uint8_t mode;
|
uint8_t mode;
|
||||||
|
@ -145,15 +146,15 @@ int reset_requested;
|
||||||
incorrect, but it avoids having to simulate exact delays */
|
incorrect, but it avoids having to simulate exact delays */
|
||||||
static void kbd_update_irq(KBDState *s)
|
static void kbd_update_irq(KBDState *s)
|
||||||
{
|
{
|
||||||
|
KBDQueue *q = &s->queue;
|
||||||
int irq12_level, irq1_level;
|
int irq12_level, irq1_level;
|
||||||
|
|
||||||
irq1_level = 0;
|
irq1_level = 0;
|
||||||
irq12_level = 0;
|
irq12_level = 0;
|
||||||
s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);
|
s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);
|
||||||
if (s->queues[0].count != 0 ||
|
if (q->count != 0) {
|
||||||
s->queues[1].count != 0) {
|
|
||||||
s->status |= KBD_STAT_OBF;
|
s->status |= KBD_STAT_OBF;
|
||||||
if (s->queues[1].count != 0) {
|
if (q->aux[q->rptr]) {
|
||||||
s->status |= KBD_STAT_MOUSE_OBF;
|
s->status |= KBD_STAT_MOUSE_OBF;
|
||||||
if (s->mode & KBD_MODE_MOUSE_INT)
|
if (s->mode & KBD_MODE_MOUSE_INT)
|
||||||
irq12_level = 1;
|
irq12_level = 1;
|
||||||
|
@ -169,7 +170,7 @@ static void kbd_update_irq(KBDState *s)
|
||||||
|
|
||||||
static void kbd_queue(KBDState *s, int b, int aux)
|
static void kbd_queue(KBDState *s, int b, int aux)
|
||||||
{
|
{
|
||||||
KBDQueue *q = &s->queues[aux];
|
KBDQueue *q = &s->queue;
|
||||||
|
|
||||||
#if defined(DEBUG_MOUSE) || defined(DEBUG_KBD)
|
#if defined(DEBUG_MOUSE) || defined(DEBUG_KBD)
|
||||||
if (aux)
|
if (aux)
|
||||||
|
@ -181,6 +182,7 @@ static void kbd_queue(KBDState *s, int b, int aux)
|
||||||
#endif
|
#endif
|
||||||
if (q->count >= KBD_QUEUE_SIZE)
|
if (q->count >= KBD_QUEUE_SIZE)
|
||||||
return;
|
return;
|
||||||
|
q->aux[q->wptr] = aux;
|
||||||
q->data[q->wptr] = b;
|
q->data[q->wptr] = b;
|
||||||
if (++q->wptr == KBD_QUEUE_SIZE)
|
if (++q->wptr == KBD_QUEUE_SIZE)
|
||||||
q->wptr = 0;
|
q->wptr = 0;
|
||||||
|
@ -288,30 +290,28 @@ static uint32_t kbd_read_data(void *opaque, uint32_t addr)
|
||||||
{
|
{
|
||||||
KBDState *s = opaque;
|
KBDState *s = opaque;
|
||||||
KBDQueue *q;
|
KBDQueue *q;
|
||||||
int val, index;
|
int val, index, aux;
|
||||||
|
|
||||||
q = &s->queues[1]; /* first check AUX data */
|
q = &s->queue;
|
||||||
if (q->count == 0)
|
|
||||||
q = &s->queues[0]; /* then check KBD data */
|
|
||||||
if (q->count == 0) {
|
if (q->count == 0) {
|
||||||
/* NOTE: if no data left, we return the last keyboard one
|
/* NOTE: if no data left, we return the last keyboard one
|
||||||
(needed for EMM386) */
|
(needed for EMM386) */
|
||||||
/* XXX: need a timer to do things correctly */
|
/* XXX: need a timer to do things correctly */
|
||||||
q = &s->queues[0];
|
|
||||||
index = q->rptr - 1;
|
index = q->rptr - 1;
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
index = KBD_QUEUE_SIZE - 1;
|
index = KBD_QUEUE_SIZE - 1;
|
||||||
val = q->data[index];
|
val = q->data[index];
|
||||||
} else {
|
} else {
|
||||||
|
aux = q->aux[q->rptr];
|
||||||
val = q->data[q->rptr];
|
val = q->data[q->rptr];
|
||||||
if (++q->rptr == KBD_QUEUE_SIZE)
|
if (++q->rptr == KBD_QUEUE_SIZE)
|
||||||
q->rptr = 0;
|
q->rptr = 0;
|
||||||
q->count--;
|
q->count--;
|
||||||
/* reading deasserts IRQ */
|
/* reading deasserts IRQ */
|
||||||
if (q == &s->queues[0])
|
if (aux)
|
||||||
pic_set_irq(1, 0);
|
|
||||||
else
|
|
||||||
pic_set_irq(12, 0);
|
pic_set_irq(12, 0);
|
||||||
|
else
|
||||||
|
pic_set_irq(1, 0);
|
||||||
}
|
}
|
||||||
/* reassert IRQs if data left */
|
/* reassert IRQs if data left */
|
||||||
kbd_update_irq(s);
|
kbd_update_irq(s);
|
||||||
|
@ -452,7 +452,7 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
|
||||||
s->mouse_buttons = buttons_state;
|
s->mouse_buttons = buttons_state;
|
||||||
|
|
||||||
if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
|
if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
|
||||||
(s->queues[1].count < (KBD_QUEUE_SIZE - 16))) {
|
(s->queue.count < (KBD_QUEUE_SIZE - 16))) {
|
||||||
for(;;) {
|
for(;;) {
|
||||||
/* if not remote, send event. Multiple events are sent if
|
/* if not remote, send event. Multiple events are sent if
|
||||||
too big deltas */
|
too big deltas */
|
||||||
|
@ -632,19 +632,16 @@ void kbd_write_data(void *opaque, uint32_t addr, uint32_t val)
|
||||||
void kbd_reset(KBDState *s)
|
void kbd_reset(KBDState *s)
|
||||||
{
|
{
|
||||||
KBDQueue *q;
|
KBDQueue *q;
|
||||||
int i;
|
|
||||||
|
|
||||||
s->kbd_write_cmd = -1;
|
s->kbd_write_cmd = -1;
|
||||||
s->mouse_write_cmd = -1;
|
s->mouse_write_cmd = -1;
|
||||||
s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT;
|
s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT;
|
||||||
s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED;
|
s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED;
|
||||||
for(i = 0; i < 2; i++) {
|
q = &s->queue;
|
||||||
q = &s->queues[i];
|
|
||||||
q->rptr = 0;
|
q->rptr = 0;
|
||||||
q->wptr = 0;
|
q->wptr = 0;
|
||||||
q->count = 0;
|
q->count = 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void kbd_init(void)
|
void kbd_init(void)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue