Commit 660de33686226402a064e3fbab9cc6dfed06b087
1 parent
69135b5c
PIIX ELCR register support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@820 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
48 additions
and
11 deletions
hw/i8259.c
... | ... | @@ -43,6 +43,8 @@ typedef struct PicState { |
43 | 43 | uint8_t rotate_on_auto_eoi; |
44 | 44 | uint8_t special_fully_nested_mode; |
45 | 45 | uint8_t init4; /* true if 4 byte init */ |
46 | + uint8_t elcr; /* PIIX edge/trigger selection*/ | |
47 | + uint8_t elcr_mask; | |
46 | 48 | } PicState; |
47 | 49 | |
48 | 50 | /* 0 is master pic, 1 is slave pic */ |
... | ... | @@ -54,12 +56,24 @@ static inline void pic_set_irq1(PicState *s, int irq, int level) |
54 | 56 | { |
55 | 57 | int mask; |
56 | 58 | mask = 1 << irq; |
57 | - if (level) { | |
58 | - if ((s->last_irr & mask) == 0) | |
59 | + if (s->elcr & mask) { | |
60 | + /* level triggered */ | |
61 | + if (level) { | |
59 | 62 | s->irr |= mask; |
60 | - s->last_irr |= mask; | |
63 | + s->last_irr |= mask; | |
64 | + } else { | |
65 | + s->irr &= ~mask; | |
66 | + s->last_irr &= ~mask; | |
67 | + } | |
61 | 68 | } else { |
62 | - s->last_irr &= ~mask; | |
69 | + /* edge triggered */ | |
70 | + if (level) { | |
71 | + if ((s->last_irr & mask) == 0) | |
72 | + s->irr |= mask; | |
73 | + s->last_irr |= mask; | |
74 | + } else { | |
75 | + s->last_irr &= ~mask; | |
76 | + } | |
63 | 77 | } |
64 | 78 | } |
65 | 79 | |
... | ... | @@ -205,7 +219,7 @@ int cpu_get_pic_interrupt(CPUState *env) |
205 | 219 | static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val) |
206 | 220 | { |
207 | 221 | PicState *s = opaque; |
208 | - int priority, cmd, irq; | |
222 | + int priority, cmd, irq, tmp; | |
209 | 223 | |
210 | 224 | #ifdef DEBUG_PIC |
211 | 225 | printf("pic_write: addr=0x%02x val=0x%02x\n", addr, val); |
... | ... | @@ -214,7 +228,10 @@ static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val) |
214 | 228 | if (addr == 0) { |
215 | 229 | if (val & 0x10) { |
216 | 230 | /* init */ |
231 | + tmp = s->elcr_mask; | |
217 | 232 | memset(s, 0, sizeof(PicState)); |
233 | + s->elcr_mask = tmp; | |
234 | + | |
218 | 235 | s->init_state = 1; |
219 | 236 | s->init4 = val & 1; |
220 | 237 | if (val & 0x02) |
... | ... | @@ -356,6 +373,18 @@ uint32_t pic_intack_read(CPUState *env) |
356 | 373 | return ret; |
357 | 374 | } |
358 | 375 | |
376 | +static void elcr_ioport_write(void *opaque, uint32_t addr, uint32_t val) | |
377 | +{ | |
378 | + PicState *s = opaque; | |
379 | + s->elcr = val & s->elcr_mask; | |
380 | +} | |
381 | + | |
382 | +static uint32_t elcr_ioport_read(void *opaque, uint32_t addr1) | |
383 | +{ | |
384 | + PicState *s = opaque; | |
385 | + return s->elcr; | |
386 | +} | |
387 | + | |
359 | 388 | static void pic_save(QEMUFile *f, void *opaque) |
360 | 389 | { |
361 | 390 | PicState *s = opaque; |
... | ... | @@ -374,6 +403,7 @@ static void pic_save(QEMUFile *f, void *opaque) |
374 | 403 | qemu_put_8s(f, &s->rotate_on_auto_eoi); |
375 | 404 | qemu_put_8s(f, &s->special_fully_nested_mode); |
376 | 405 | qemu_put_8s(f, &s->init4); |
406 | + qemu_put_8s(f, &s->elcr); | |
377 | 407 | } |
378 | 408 | |
379 | 409 | static int pic_load(QEMUFile *f, void *opaque, int version_id) |
... | ... | @@ -397,15 +427,19 @@ static int pic_load(QEMUFile *f, void *opaque, int version_id) |
397 | 427 | qemu_get_8s(f, &s->rotate_on_auto_eoi); |
398 | 428 | qemu_get_8s(f, &s->special_fully_nested_mode); |
399 | 429 | qemu_get_8s(f, &s->init4); |
430 | + qemu_get_8s(f, &s->elcr); | |
400 | 431 | return 0; |
401 | 432 | } |
402 | 433 | |
403 | 434 | /* XXX: add generic master/slave system */ |
404 | -static void pic_init1(int io_addr, PicState *s) | |
435 | +static void pic_init1(int io_addr, int elcr_addr, PicState *s) | |
405 | 436 | { |
406 | 437 | register_ioport_write(io_addr, 2, 1, pic_ioport_write, s); |
407 | 438 | register_ioport_read(io_addr, 2, 1, pic_ioport_read, s); |
408 | - | |
439 | + if (elcr_addr >= 0) { | |
440 | + register_ioport_write(elcr_addr, 1, 1, elcr_ioport_write, s); | |
441 | + register_ioport_read(elcr_addr, 1, 1, elcr_ioport_read, s); | |
442 | + } | |
409 | 443 | register_savevm("i8259", io_addr, 1, pic_save, pic_load, s); |
410 | 444 | } |
411 | 445 | |
... | ... | @@ -416,15 +450,18 @@ void pic_info(void) |
416 | 450 | |
417 | 451 | for(i=0;i<2;i++) { |
418 | 452 | s = &pics[i]; |
419 | - term_printf("pic%d: irr=%02x imr=%02x isr=%02x hprio=%d irq_base=%02x rr_sel=%d\n", | |
420 | - i, s->irr, s->imr, s->isr, s->priority_add, s->irq_base, s->read_reg_select); | |
453 | + term_printf("pic%d: irr=%02x imr=%02x isr=%02x hprio=%d irq_base=%02x rr_sel=%d elcr=%02x\n", | |
454 | + i, s->irr, s->imr, s->isr, s->priority_add, | |
455 | + s->irq_base, s->read_reg_select, s->elcr); | |
421 | 456 | } |
422 | 457 | } |
423 | 458 | |
424 | 459 | |
425 | 460 | void pic_init(void) |
426 | 461 | { |
427 | - pic_init1(0x20, &pics[0]); | |
428 | - pic_init1(0xa0, &pics[1]); | |
462 | + pic_init1(0x20, 0x4d0, &pics[0]); | |
463 | + pic_init1(0xa0, 0x4d1, &pics[1]); | |
464 | + pics[0].elcr_mask = 0xf8; | |
465 | + pics[1].elcr_mask = 0xde; | |
429 | 466 | } |
430 | 467 | ... | ... |