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,6 +43,8 @@ typedef struct PicState { | ||
| 43 | uint8_t rotate_on_auto_eoi; | 43 | uint8_t rotate_on_auto_eoi; |
| 44 | uint8_t special_fully_nested_mode; | 44 | uint8_t special_fully_nested_mode; |
| 45 | uint8_t init4; /* true if 4 byte init */ | 45 | uint8_t init4; /* true if 4 byte init */ |
| 46 | + uint8_t elcr; /* PIIX edge/trigger selection*/ | ||
| 47 | + uint8_t elcr_mask; | ||
| 46 | } PicState; | 48 | } PicState; |
| 47 | 49 | ||
| 48 | /* 0 is master pic, 1 is slave pic */ | 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,12 +56,24 @@ static inline void pic_set_irq1(PicState *s, int irq, int level) | ||
| 54 | { | 56 | { |
| 55 | int mask; | 57 | int mask; |
| 56 | mask = 1 << irq; | 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 | s->irr |= mask; | 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 | } else { | 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,7 +219,7 @@ int cpu_get_pic_interrupt(CPUState *env) | ||
| 205 | static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val) | 219 | static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val) |
| 206 | { | 220 | { |
| 207 | PicState *s = opaque; | 221 | PicState *s = opaque; |
| 208 | - int priority, cmd, irq; | 222 | + int priority, cmd, irq, tmp; |
| 209 | 223 | ||
| 210 | #ifdef DEBUG_PIC | 224 | #ifdef DEBUG_PIC |
| 211 | printf("pic_write: addr=0x%02x val=0x%02x\n", addr, val); | 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,7 +228,10 @@ static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val) | ||
| 214 | if (addr == 0) { | 228 | if (addr == 0) { |
| 215 | if (val & 0x10) { | 229 | if (val & 0x10) { |
| 216 | /* init */ | 230 | /* init */ |
| 231 | + tmp = s->elcr_mask; | ||
| 217 | memset(s, 0, sizeof(PicState)); | 232 | memset(s, 0, sizeof(PicState)); |
| 233 | + s->elcr_mask = tmp; | ||
| 234 | + | ||
| 218 | s->init_state = 1; | 235 | s->init_state = 1; |
| 219 | s->init4 = val & 1; | 236 | s->init4 = val & 1; |
| 220 | if (val & 0x02) | 237 | if (val & 0x02) |
| @@ -356,6 +373,18 @@ uint32_t pic_intack_read(CPUState *env) | @@ -356,6 +373,18 @@ uint32_t pic_intack_read(CPUState *env) | ||
| 356 | return ret; | 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 | static void pic_save(QEMUFile *f, void *opaque) | 388 | static void pic_save(QEMUFile *f, void *opaque) |
| 360 | { | 389 | { |
| 361 | PicState *s = opaque; | 390 | PicState *s = opaque; |
| @@ -374,6 +403,7 @@ static void pic_save(QEMUFile *f, void *opaque) | @@ -374,6 +403,7 @@ static void pic_save(QEMUFile *f, void *opaque) | ||
| 374 | qemu_put_8s(f, &s->rotate_on_auto_eoi); | 403 | qemu_put_8s(f, &s->rotate_on_auto_eoi); |
| 375 | qemu_put_8s(f, &s->special_fully_nested_mode); | 404 | qemu_put_8s(f, &s->special_fully_nested_mode); |
| 376 | qemu_put_8s(f, &s->init4); | 405 | qemu_put_8s(f, &s->init4); |
| 406 | + qemu_put_8s(f, &s->elcr); | ||
| 377 | } | 407 | } |
| 378 | 408 | ||
| 379 | static int pic_load(QEMUFile *f, void *opaque, int version_id) | 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,15 +427,19 @@ static int pic_load(QEMUFile *f, void *opaque, int version_id) | ||
| 397 | qemu_get_8s(f, &s->rotate_on_auto_eoi); | 427 | qemu_get_8s(f, &s->rotate_on_auto_eoi); |
| 398 | qemu_get_8s(f, &s->special_fully_nested_mode); | 428 | qemu_get_8s(f, &s->special_fully_nested_mode); |
| 399 | qemu_get_8s(f, &s->init4); | 429 | qemu_get_8s(f, &s->init4); |
| 430 | + qemu_get_8s(f, &s->elcr); | ||
| 400 | return 0; | 431 | return 0; |
| 401 | } | 432 | } |
| 402 | 433 | ||
| 403 | /* XXX: add generic master/slave system */ | 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 | register_ioport_write(io_addr, 2, 1, pic_ioport_write, s); | 437 | register_ioport_write(io_addr, 2, 1, pic_ioport_write, s); |
| 407 | register_ioport_read(io_addr, 2, 1, pic_ioport_read, s); | 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 | register_savevm("i8259", io_addr, 1, pic_save, pic_load, s); | 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,15 +450,18 @@ void pic_info(void) | ||
| 416 | 450 | ||
| 417 | for(i=0;i<2;i++) { | 451 | for(i=0;i<2;i++) { |
| 418 | s = &pics[i]; | 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 | void pic_init(void) | 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 |