Commit ed5fd2cce48520e4c0d4eec016743017df93e43a
1 parent
bee32909
timer for READ_ID (win98 floppy fix) - simpler irq handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@787 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
44 additions
and
36 deletions
hw/fdc.c
| ... | ... | @@ -125,17 +125,17 @@ static int fd_seek (fdrive_t *drv, uint8_t head, uint8_t track, uint8_t sect, |
| 125 | 125 | |
| 126 | 126 | if (track > drv->max_track || |
| 127 | 127 | (head != 0 && (drv->flags & FDISK_DBL_SIDES) == 0)) { |
| 128 | - FLOPPY_ERROR("try to read %d %02x %02x (max=%d %d %02x %02x)\n", | |
| 129 | - head, track, sect, 1, | |
| 130 | - (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1, | |
| 131 | - drv->max_track, drv->last_sect); | |
| 128 | + FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n", | |
| 129 | + head, track, sect, 1, | |
| 130 | + (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1, | |
| 131 | + drv->max_track, drv->last_sect); | |
| 132 | 132 | return 2; |
| 133 | 133 | } |
| 134 | 134 | if (sect > drv->last_sect) { |
| 135 | - FLOPPY_ERROR("try to read %d %02x %02x (max=%d %d %02x %02x)\n", | |
| 136 | - head, track, sect, 1, | |
| 137 | - (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1, | |
| 138 | - drv->max_track, drv->last_sect); | |
| 135 | + FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n", | |
| 136 | + head, track, sect, 1, | |
| 137 | + (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1, | |
| 138 | + drv->max_track, drv->last_sect); | |
| 139 | 139 | return 3; |
| 140 | 140 | } |
| 141 | 141 | sector = _fd_sector(head, track, sect, drv->last_sect); |
| ... | ... | @@ -240,8 +240,8 @@ static void fd_revalidate (fdrive_t *drv) |
| 240 | 240 | ro = bdrv_is_read_only(drv->bs); |
| 241 | 241 | bdrv_get_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect); |
| 242 | 242 | if (nb_heads != 0 && max_track != 0 && last_sect != 0) { |
| 243 | - printf("User defined disk (%d %d %d)", | |
| 244 | - nb_heads - 1, max_track, last_sect); | |
| 243 | + FLOPPY_DPRINTF("User defined disk (%d %d %d)", | |
| 244 | + nb_heads - 1, max_track, last_sect); | |
| 245 | 245 | } else { |
| 246 | 246 | bdrv_get_geometry(drv->bs, &nb_sectors); |
| 247 | 247 | match = -1; |
| ... | ... | @@ -273,8 +273,8 @@ static void fd_revalidate (fdrive_t *drv) |
| 273 | 273 | max_track = parse->max_track; |
| 274 | 274 | last_sect = parse->last_sect; |
| 275 | 275 | drv->drive = parse->drive; |
| 276 | - printf("%s floppy disk (%d h %d t %d s) %s\n", parse->str, | |
| 277 | - nb_heads, max_track, last_sect, ro ? "ro" : "rw"); | |
| 276 | + FLOPPY_DPRINTF("%s floppy disk (%d h %d t %d s) %s\n", parse->str, | |
| 277 | + nb_heads, max_track, last_sect, ro ? "ro" : "rw"); | |
| 278 | 278 | } |
| 279 | 279 | if (nb_heads == 1) { |
| 280 | 280 | drv->flags &= ~FDISK_DBL_SIDES; |
| ... | ... | @@ -285,7 +285,7 @@ static void fd_revalidate (fdrive_t *drv) |
| 285 | 285 | drv->last_sect = last_sect; |
| 286 | 286 | drv->ro = ro; |
| 287 | 287 | } else { |
| 288 | - printf("No disk in drive\n"); | |
| 288 | + FLOPPY_DPRINTF("No disk in drive\n"); | |
| 289 | 289 | drv->last_sect = 0; |
| 290 | 290 | drv->max_track = 0; |
| 291 | 291 | drv->flags &= ~FDISK_DBL_SIDES; |
| ... | ... | @@ -318,6 +318,7 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq); |
| 318 | 318 | static void fdctrl_reset_fifo (fdctrl_t *fdctrl); |
| 319 | 319 | static int fdctrl_transfer_handler (void *opaque, target_ulong addr, int size); |
| 320 | 320 | static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status); |
| 321 | +static void fdctrl_result_timer(void *opaque); | |
| 321 | 322 | |
| 322 | 323 | static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl); |
| 323 | 324 | static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl); |
| ... | ... | @@ -331,10 +332,10 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value); |
| 331 | 332 | static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl); |
| 332 | 333 | |
| 333 | 334 | enum { |
| 334 | - FD_CTRL_ACTIVE = 0x01, | |
| 335 | + FD_CTRL_ACTIVE = 0x01, /* XXX: suppress that */ | |
| 335 | 336 | FD_CTRL_RESET = 0x02, |
| 336 | - FD_CTRL_SLEEP = 0x04, | |
| 337 | - FD_CTRL_BUSY = 0x08, | |
| 337 | + FD_CTRL_SLEEP = 0x04, /* XXX: suppress that */ | |
| 338 | + FD_CTRL_BUSY = 0x08, /* dma transfer in progress */ | |
| 338 | 339 | FD_CTRL_INTR = 0x10, |
| 339 | 340 | }; |
| 340 | 341 | |
| ... | ... | @@ -372,6 +373,7 @@ struct fdctrl_t { |
| 372 | 373 | int dma_chann; |
| 373 | 374 | uint32_t io_base; |
| 374 | 375 | /* Controler state */ |
| 376 | + QEMUTimer *result_timer; | |
| 375 | 377 | uint8_t state; |
| 376 | 378 | uint8_t dma_en; |
| 377 | 379 | uint8_t cur_drv; |
| ... | ... | @@ -425,6 +427,7 @@ static uint32_t fdctrl_read (void *opaque, uint32_t reg) |
| 425 | 427 | retval = (uint32_t)(-1); |
| 426 | 428 | break; |
| 427 | 429 | } |
| 430 | + FLOPPY_DPRINTF("read reg%d: 0x%02x\n", reg & 7, retval); | |
| 428 | 431 | |
| 429 | 432 | return retval; |
| 430 | 433 | } |
| ... | ... | @@ -433,6 +436,8 @@ static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value) |
| 433 | 436 | { |
| 434 | 437 | fdctrl_t *fdctrl = opaque; |
| 435 | 438 | |
| 439 | + FLOPPY_DPRINTF("write reg%d: 0x%02x\n", reg & 7, value); | |
| 440 | + | |
| 436 | 441 | switch (reg & 0x07) { |
| 437 | 442 | case 0x02: |
| 438 | 443 | fdctrl_write_dor(fdctrl, value); |
| ... | ... | @@ -476,6 +481,9 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped, |
| 476 | 481 | fdctrl = qemu_mallocz(sizeof(fdctrl_t)); |
| 477 | 482 | if (!fdctrl) |
| 478 | 483 | return NULL; |
| 484 | + fdctrl->result_timer = qemu_new_timer(vm_clock, | |
| 485 | + fdctrl_result_timer, fdctrl); | |
| 486 | + | |
| 479 | 487 | fdctrl->version = 0x90; /* Intel 82078 controler */ |
| 480 | 488 | fdctrl->irq_lvl = irq_lvl; |
| 481 | 489 | fdctrl->dma_chann = dma_chann; |
| ... | ... | @@ -524,10 +532,9 @@ int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num) |
| 524 | 532 | /* Change IRQ state */ |
| 525 | 533 | static void fdctrl_reset_irq (fdctrl_t *fdctrl) |
| 526 | 534 | { |
| 527 | - if (fdctrl->state & FD_CTRL_INTR) { | |
| 528 | - pic_set_irq(fdctrl->irq_lvl, 0); | |
| 529 | - fdctrl->state &= ~(FD_CTRL_INTR | FD_CTRL_SLEEP | FD_CTRL_BUSY); | |
| 530 | - } | |
| 535 | + FLOPPY_DPRINTF("Reset interrupt\n"); | |
| 536 | + pic_set_irq(fdctrl->irq_lvl, 0); | |
| 537 | + fdctrl->state &= ~FD_CTRL_INTR; | |
| 531 | 538 | } |
| 532 | 539 | |
| 533 | 540 | static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status) |
| ... | ... | @@ -558,7 +565,7 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq) |
| 558 | 565 | fd_reset(&fdctrl->drives[i]); |
| 559 | 566 | fdctrl_reset_fifo(fdctrl); |
| 560 | 567 | if (do_irq) |
| 561 | - fdctrl_raise_irq(fdctrl, 0x20); | |
| 568 | + fdctrl_raise_irq(fdctrl, 0xc0); | |
| 562 | 569 | } |
| 563 | 570 | |
| 564 | 571 | static inline fdrive_t *drv0 (fdctrl_t *fdctrl) |
| ... | ... | @@ -579,9 +586,7 @@ static fdrive_t *get_cur_drv (fdctrl_t *fdctrl) |
| 579 | 586 | /* Status B register : 0x01 (read-only) */ |
| 580 | 587 | static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl) |
| 581 | 588 | { |
| 582 | - fdctrl_reset_irq(fdctrl); | |
| 583 | 589 | FLOPPY_DPRINTF("status register: 0x00\n"); |
| 584 | - | |
| 585 | 590 | return 0; |
| 586 | 591 | } |
| 587 | 592 | |
| ... | ... | @@ -608,7 +613,6 @@ static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl) |
| 608 | 613 | |
| 609 | 614 | static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value) |
| 610 | 615 | { |
| 611 | - fdctrl_reset_irq(fdctrl); | |
| 612 | 616 | /* Reset mode */ |
| 613 | 617 | if (fdctrl->state & FD_CTRL_RESET) { |
| 614 | 618 | if (!(value & 0x04)) { |
| ... | ... | @@ -653,7 +657,6 @@ static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl) |
| 653 | 657 | { |
| 654 | 658 | uint32_t retval = 0; |
| 655 | 659 | |
| 656 | - fdctrl_reset_irq(fdctrl); | |
| 657 | 660 | /* Disk boot selection indicator */ |
| 658 | 661 | retval |= fdctrl->bootsel << 2; |
| 659 | 662 | /* Tape indicators: never allowed */ |
| ... | ... | @@ -664,7 +667,6 @@ static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl) |
| 664 | 667 | |
| 665 | 668 | static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value) |
| 666 | 669 | { |
| 667 | - fdctrl_reset_irq(fdctrl); | |
| 668 | 670 | /* Reset mode */ |
| 669 | 671 | if (fdctrl->state & FD_CTRL_RESET) { |
| 670 | 672 | FLOPPY_DPRINTF("Floppy controler in RESET state !\n"); |
| ... | ... | @@ -681,7 +683,6 @@ static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl) |
| 681 | 683 | { |
| 682 | 684 | uint32_t retval = 0; |
| 683 | 685 | |
| 684 | - fdctrl_reset_irq(fdctrl); | |
| 685 | 686 | fdctrl->state &= ~(FD_CTRL_SLEEP | FD_CTRL_RESET); |
| 686 | 687 | if (!(fdctrl->state & FD_CTRL_BUSY)) { |
| 687 | 688 | /* Data transfer allowed */ |
| ... | ... | @@ -703,7 +704,6 @@ static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl) |
| 703 | 704 | /* Data select rate register : 0x04 (write) */ |
| 704 | 705 | static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value) |
| 705 | 706 | { |
| 706 | - fdctrl_reset_irq(fdctrl); | |
| 707 | 707 | /* Reset mode */ |
| 708 | 708 | if (fdctrl->state & FD_CTRL_RESET) { |
| 709 | 709 | FLOPPY_DPRINTF("Floppy controler in RESET state !\n"); |
| ... | ... | @@ -728,7 +728,6 @@ static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl) |
| 728 | 728 | { |
| 729 | 729 | uint32_t retval = 0; |
| 730 | 730 | |
| 731 | - fdctrl_reset_irq(fdctrl); | |
| 732 | 731 | if (drv0(fdctrl)->drflags & FDRIVE_REVALIDATE || |
| 733 | 732 | drv1(fdctrl)->drflags & FDRIVE_REVALIDATE) |
| 734 | 733 | retval |= 0x80; |
| ... | ... | @@ -795,8 +794,10 @@ static void fdctrl_stop_transfer (fdctrl_t *fdctrl, uint8_t status0, |
| 795 | 794 | fdctrl->fifo[5] = cur_drv->sect; |
| 796 | 795 | fdctrl->fifo[6] = FD_SECTOR_SC; |
| 797 | 796 | fdctrl->data_dir = FD_DIR_READ; |
| 798 | - if (fdctrl->state & FD_CTRL_BUSY) | |
| 797 | + if (fdctrl->state & FD_CTRL_BUSY) { | |
| 799 | 798 | DMA_release_DREQ(fdctrl->dma_chann); |
| 799 | + fdctrl->state &= ~FD_CTRL_BUSY; | |
| 800 | + } | |
| 800 | 801 | fdctrl_set_fifo(fdctrl, 7, 1); |
| 801 | 802 | } |
| 802 | 803 | |
| ... | ... | @@ -916,7 +917,6 @@ static int fdctrl_transfer_handler (void *opaque, target_ulong addr, int size) |
| 916 | 917 | uint8_t status0 = 0x00, status1 = 0x00, status2 = 0x00; |
| 917 | 918 | |
| 918 | 919 | fdctrl = opaque; |
| 919 | - fdctrl_reset_irq(fdctrl); | |
| 920 | 920 | if (!(fdctrl->state & FD_CTRL_BUSY)) { |
| 921 | 921 | FLOPPY_DPRINTF("Not in DMA transfer mode !\n"); |
| 922 | 922 | return 0; |
| ... | ... | @@ -1049,7 +1049,6 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl) |
| 1049 | 1049 | uint32_t retval = 0; |
| 1050 | 1050 | int pos, len; |
| 1051 | 1051 | |
| 1052 | - fdctrl_reset_irq(fdctrl); | |
| 1053 | 1052 | cur_drv = get_cur_drv(fdctrl); |
| 1054 | 1053 | fdctrl->state &= ~FD_CTRL_SLEEP; |
| 1055 | 1054 | if (FD_STATE(fdctrl->data_state) == FD_STATE_CMD) { |
| ... | ... | @@ -1073,10 +1072,12 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl) |
| 1073 | 1072 | /* Switch from transfert mode to status mode |
| 1074 | 1073 | * then from status mode to command mode |
| 1075 | 1074 | */ |
| 1076 | - if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) | |
| 1075 | + if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) { | |
| 1077 | 1076 | fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00); |
| 1078 | - else | |
| 1077 | + } else { | |
| 1079 | 1078 | fdctrl_reset_fifo(fdctrl); |
| 1079 | + fdctrl_reset_irq(fdctrl); | |
| 1080 | + } | |
| 1080 | 1081 | } |
| 1081 | 1082 | FLOPPY_DPRINTF("data register: 0x%02x\n", retval); |
| 1082 | 1083 | |
| ... | ... | @@ -1152,7 +1153,6 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) |
| 1152 | 1153 | { |
| 1153 | 1154 | fdrive_t *cur_drv; |
| 1154 | 1155 | |
| 1155 | - fdctrl_reset_irq(fdctrl); | |
| 1156 | 1156 | cur_drv = get_cur_drv(fdctrl); |
| 1157 | 1157 | /* Reset mode */ |
| 1158 | 1158 | if (fdctrl->state & FD_CTRL_RESET) { |
| ... | ... | @@ -1583,7 +1583,9 @@ enqueue: |
| 1583 | 1583 | case 0x4A: |
| 1584 | 1584 | /* READ_ID */ |
| 1585 | 1585 | FLOPPY_DPRINTF("treat READ_ID command\n"); |
| 1586 | - fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); | |
| 1586 | + /* XXX: should set main status register to busy */ | |
| 1587 | + qemu_mod_timer(fdctrl->result_timer, | |
| 1588 | + qemu_get_clock(vm_clock) + (ticks_per_sec / 50)); | |
| 1587 | 1589 | break; |
| 1588 | 1590 | case 0x4C: |
| 1589 | 1591 | /* RESTORE */ |
| ... | ... | @@ -1688,3 +1690,9 @@ enqueue: |
| 1688 | 1690 | } |
| 1689 | 1691 | } |
| 1690 | 1692 | } |
| 1693 | + | |
| 1694 | +static void fdctrl_result_timer(void *opaque) | |
| 1695 | +{ | |
| 1696 | + fdctrl_t *fdctrl = opaque; | |
| 1697 | + fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); | |
| 1698 | +} | ... | ... |