Commit 6f51f6b593e0a0065f83bcebb6f9e4aa05a4c8b3
1 parent
0294ffb9
keyboard irq generation fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@778 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
18 additions
and
21 deletions
hw/pckbd.c
| ... | ... | @@ -111,12 +111,13 @@ |
| 111 | 111 | #define KBD_QUEUE_SIZE 256 |
| 112 | 112 | |
| 113 | 113 | typedef struct { |
| 114 | + uint8_t aux[KBD_QUEUE_SIZE]; | |
| 114 | 115 | uint8_t data[KBD_QUEUE_SIZE]; |
| 115 | 116 | int rptr, wptr, count; |
| 116 | 117 | } KBDQueue; |
| 117 | 118 | |
| 118 | 119 | typedef struct KBDState { |
| 119 | - KBDQueue queues[2]; | |
| 120 | + KBDQueue queue; | |
| 120 | 121 | uint8_t write_cmd; /* if non zero, write data to port 60 is expected */ |
| 121 | 122 | uint8_t status; |
| 122 | 123 | uint8_t mode; |
| ... | ... | @@ -145,15 +146,15 @@ int reset_requested; |
| 145 | 146 | incorrect, but it avoids having to simulate exact delays */ |
| 146 | 147 | static void kbd_update_irq(KBDState *s) |
| 147 | 148 | { |
| 149 | + KBDQueue *q = &s->queue; | |
| 148 | 150 | int irq12_level, irq1_level; |
| 149 | 151 | |
| 150 | 152 | irq1_level = 0; |
| 151 | 153 | irq12_level = 0; |
| 152 | 154 | s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF); |
| 153 | - if (s->queues[0].count != 0 || | |
| 154 | - s->queues[1].count != 0) { | |
| 155 | + if (q->count != 0) { | |
| 155 | 156 | s->status |= KBD_STAT_OBF; |
| 156 | - if (s->queues[1].count != 0) { | |
| 157 | + if (q->aux[q->rptr]) { | |
| 157 | 158 | s->status |= KBD_STAT_MOUSE_OBF; |
| 158 | 159 | if (s->mode & KBD_MODE_MOUSE_INT) |
| 159 | 160 | irq12_level = 1; |
| ... | ... | @@ -169,7 +170,7 @@ static void kbd_update_irq(KBDState *s) |
| 169 | 170 | |
| 170 | 171 | static void kbd_queue(KBDState *s, int b, int aux) |
| 171 | 172 | { |
| 172 | - KBDQueue *q = &s->queues[aux]; | |
| 173 | + KBDQueue *q = &s->queue; | |
| 173 | 174 | |
| 174 | 175 | #if defined(DEBUG_MOUSE) || defined(DEBUG_KBD) |
| 175 | 176 | if (aux) |
| ... | ... | @@ -181,6 +182,7 @@ static void kbd_queue(KBDState *s, int b, int aux) |
| 181 | 182 | #endif |
| 182 | 183 | if (q->count >= KBD_QUEUE_SIZE) |
| 183 | 184 | return; |
| 185 | + q->aux[q->wptr] = aux; | |
| 184 | 186 | q->data[q->wptr] = b; |
| 185 | 187 | if (++q->wptr == KBD_QUEUE_SIZE) |
| 186 | 188 | q->wptr = 0; |
| ... | ... | @@ -288,30 +290,28 @@ static uint32_t kbd_read_data(void *opaque, uint32_t addr) |
| 288 | 290 | { |
| 289 | 291 | KBDState *s = opaque; |
| 290 | 292 | KBDQueue *q; |
| 291 | - int val, index; | |
| 293 | + int val, index, aux; | |
| 292 | 294 | |
| 293 | - q = &s->queues[1]; /* first check AUX data */ | |
| 294 | - if (q->count == 0) | |
| 295 | - q = &s->queues[0]; /* then check KBD data */ | |
| 295 | + q = &s->queue; | |
| 296 | 296 | if (q->count == 0) { |
| 297 | 297 | /* NOTE: if no data left, we return the last keyboard one |
| 298 | 298 | (needed for EMM386) */ |
| 299 | 299 | /* XXX: need a timer to do things correctly */ |
| 300 | - q = &s->queues[0]; | |
| 301 | 300 | index = q->rptr - 1; |
| 302 | 301 | if (index < 0) |
| 303 | 302 | index = KBD_QUEUE_SIZE - 1; |
| 304 | 303 | val = q->data[index]; |
| 305 | 304 | } else { |
| 305 | + aux = q->aux[q->rptr]; | |
| 306 | 306 | val = q->data[q->rptr]; |
| 307 | 307 | if (++q->rptr == KBD_QUEUE_SIZE) |
| 308 | 308 | q->rptr = 0; |
| 309 | 309 | q->count--; |
| 310 | 310 | /* reading deasserts IRQ */ |
| 311 | - if (q == &s->queues[0]) | |
| 312 | - pic_set_irq(1, 0); | |
| 313 | - else | |
| 311 | + if (aux) | |
| 314 | 312 | pic_set_irq(12, 0); |
| 313 | + else | |
| 314 | + pic_set_irq(1, 0); | |
| 315 | 315 | } |
| 316 | 316 | /* reassert IRQs if data left */ |
| 317 | 317 | kbd_update_irq(s); |
| ... | ... | @@ -452,7 +452,7 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state) |
| 452 | 452 | s->mouse_buttons = buttons_state; |
| 453 | 453 | |
| 454 | 454 | if (!(s->mouse_status & MOUSE_STATUS_REMOTE) && |
| 455 | - (s->queues[1].count < (KBD_QUEUE_SIZE - 16))) { | |
| 455 | + (s->queue.count < (KBD_QUEUE_SIZE - 16))) { | |
| 456 | 456 | for(;;) { |
| 457 | 457 | /* if not remote, send event. Multiple events are sent if |
| 458 | 458 | too big deltas */ |
| ... | ... | @@ -632,18 +632,15 @@ void kbd_write_data(void *opaque, uint32_t addr, uint32_t val) |
| 632 | 632 | void kbd_reset(KBDState *s) |
| 633 | 633 | { |
| 634 | 634 | KBDQueue *q; |
| 635 | - int i; | |
| 636 | 635 | |
| 637 | 636 | s->kbd_write_cmd = -1; |
| 638 | 637 | s->mouse_write_cmd = -1; |
| 639 | 638 | s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT; |
| 640 | 639 | s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED; |
| 641 | - for(i = 0; i < 2; i++) { | |
| 642 | - q = &s->queues[i]; | |
| 643 | - q->rptr = 0; | |
| 644 | - q->wptr = 0; | |
| 645 | - q->count = 0; | |
| 646 | - } | |
| 640 | + q = &s->queue; | |
| 641 | + q->rptr = 0; | |
| 642 | + q->wptr = 0; | |
| 643 | + q->count = 0; | |
| 647 | 644 | } |
| 648 | 645 | |
| 649 | 646 | void kbd_init(void) | ... | ... |