Commit 77370520924697c6deb6964a7328f7fceaaecc17
1 parent
b9b3d225
FDC fix 7/10 (Hervé Poussineau):
- Removes useless fields in fdrive_t structure. - Adds a message when bdrv_read/bdrv_write calls fail. - Rename int_status to status0. - Replace some constants by value names. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4287 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
74 additions
and
69 deletions
hw/fdc.c
| @@ -82,9 +82,6 @@ typedef struct fdrive_t { | @@ -82,9 +82,6 @@ typedef struct fdrive_t { | ||
| 82 | uint8_t head; | 82 | uint8_t head; |
| 83 | uint8_t track; | 83 | uint8_t track; |
| 84 | uint8_t sect; | 84 | uint8_t sect; |
| 85 | - /* Last operation status */ | ||
| 86 | - uint8_t dir; /* Direction */ | ||
| 87 | - uint8_t rw; /* Read/write */ | ||
| 88 | /* Media */ | 85 | /* Media */ |
| 89 | fdisk_flags_t flags; | 86 | fdisk_flags_t flags; |
| 90 | uint8_t last_sect; /* Nb sector per track */ | 87 | uint8_t last_sect; /* Nb sector per track */ |
| @@ -116,6 +113,13 @@ static int fd_sector (fdrive_t *drv) | @@ -116,6 +113,13 @@ static int fd_sector (fdrive_t *drv) | ||
| 116 | return _fd_sector(drv->head, drv->track, drv->sect, drv->last_sect); | 113 | return _fd_sector(drv->head, drv->track, drv->sect, drv->last_sect); |
| 117 | } | 114 | } |
| 118 | 115 | ||
| 116 | +/* Seek to a new position: | ||
| 117 | + * returns 0 if already on right track | ||
| 118 | + * returns 1 if track changed | ||
| 119 | + * returns 2 if track is invalid | ||
| 120 | + * returns 3 if sector is invalid | ||
| 121 | + * returns 4 if seek is disabled | ||
| 122 | + */ | ||
| 119 | static int fd_seek (fdrive_t *drv, uint8_t head, uint8_t track, uint8_t sect, | 123 | static int fd_seek (fdrive_t *drv, uint8_t head, uint8_t track, uint8_t sect, |
| 120 | int enable_seek) | 124 | int enable_seek) |
| 121 | { | 125 | { |
| @@ -164,8 +168,6 @@ static void fd_recalibrate (fdrive_t *drv) | @@ -164,8 +168,6 @@ static void fd_recalibrate (fdrive_t *drv) | ||
| 164 | drv->head = 0; | 168 | drv->head = 0; |
| 165 | drv->track = 0; | 169 | drv->track = 0; |
| 166 | drv->sect = 1; | 170 | drv->sect = 1; |
| 167 | - drv->dir = 1; | ||
| 168 | - drv->rw = 0; | ||
| 169 | } | 171 | } |
| 170 | 172 | ||
| 171 | /* Recognize floppy formats */ | 173 | /* Recognize floppy formats */ |
| @@ -297,7 +299,7 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq); | @@ -297,7 +299,7 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq); | ||
| 297 | static void fdctrl_reset_fifo (fdctrl_t *fdctrl); | 299 | static void fdctrl_reset_fifo (fdctrl_t *fdctrl); |
| 298 | static int fdctrl_transfer_handler (void *opaque, int nchan, | 300 | static int fdctrl_transfer_handler (void *opaque, int nchan, |
| 299 | int dma_pos, int dma_len); | 301 | int dma_pos, int dma_len); |
| 300 | -static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status); | 302 | +static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status0); |
| 301 | 303 | ||
| 302 | static uint32_t fdctrl_read_statusA (fdctrl_t *fdctrl); | 304 | static uint32_t fdctrl_read_statusA (fdctrl_t *fdctrl); |
| 303 | static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl); | 305 | static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl); |
| @@ -386,6 +388,15 @@ enum { | @@ -386,6 +388,15 @@ enum { | ||
| 386 | }; | 388 | }; |
| 387 | 389 | ||
| 388 | enum { | 390 | enum { |
| 391 | + FD_SR1_EC = 0x80, /* End of cylinder */ | ||
| 392 | +}; | ||
| 393 | + | ||
| 394 | +enum { | ||
| 395 | + FD_SR2_SNS = 0x04, /* Scan not satisfied */ | ||
| 396 | + FD_SR2_SEH = 0x08, /* Scan equal hit */ | ||
| 397 | +}; | ||
| 398 | + | ||
| 399 | +enum { | ||
| 389 | FD_SRA_DIR = 0x01, | 400 | FD_SRA_DIR = 0x01, |
| 390 | FD_SRA_nWP = 0x02, | 401 | FD_SRA_nWP = 0x02, |
| 391 | FD_SRA_nINDX = 0x04, | 402 | FD_SRA_nINDX = 0x04, |
| @@ -445,7 +456,6 @@ enum { | @@ -445,7 +456,6 @@ enum { | ||
| 445 | #define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT) | 456 | #define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT) |
| 446 | 457 | ||
| 447 | struct fdctrl_t { | 458 | struct fdctrl_t { |
| 448 | - fdctrl_t *fdctrl; | ||
| 449 | /* Controller's identification */ | 459 | /* Controller's identification */ |
| 450 | uint8_t version; | 460 | uint8_t version; |
| 451 | /* HW */ | 461 | /* HW */ |
| @@ -459,17 +469,17 @@ struct fdctrl_t { | @@ -459,17 +469,17 @@ struct fdctrl_t { | ||
| 459 | uint8_t dor; | 469 | uint8_t dor; |
| 460 | uint8_t dsr; | 470 | uint8_t dsr; |
| 461 | uint8_t msr; | 471 | uint8_t msr; |
| 462 | - uint8_t state; | ||
| 463 | - uint8_t dma_en; | ||
| 464 | uint8_t cur_drv; | 472 | uint8_t cur_drv; |
| 465 | uint8_t bootsel; | 473 | uint8_t bootsel; |
| 474 | + uint8_t status0; | ||
| 475 | + uint8_t status1; | ||
| 476 | + uint8_t status2; | ||
| 466 | /* Command FIFO */ | 477 | /* Command FIFO */ |
| 467 | uint8_t *fifo; | 478 | uint8_t *fifo; |
| 468 | uint32_t data_pos; | 479 | uint32_t data_pos; |
| 469 | uint32_t data_len; | 480 | uint32_t data_len; |
| 470 | uint8_t data_state; | 481 | uint8_t data_state; |
| 471 | uint8_t data_dir; | 482 | uint8_t data_dir; |
| 472 | - uint8_t int_status; | ||
| 473 | uint8_t eot; /* last wanted sector */ | 483 | uint8_t eot; /* last wanted sector */ |
| 474 | /* States kept only to be returned back */ | 484 | /* States kept only to be returned back */ |
| 475 | /* Timers state */ | 485 | /* Timers state */ |
| @@ -587,8 +597,6 @@ static void fd_save (QEMUFile *f, fdrive_t *fd) | @@ -587,8 +597,6 @@ static void fd_save (QEMUFile *f, fdrive_t *fd) | ||
| 587 | qemu_put_8s(f, &fd->head); | 597 | qemu_put_8s(f, &fd->head); |
| 588 | qemu_put_8s(f, &fd->track); | 598 | qemu_put_8s(f, &fd->track); |
| 589 | qemu_put_8s(f, &fd->sect); | 599 | qemu_put_8s(f, &fd->sect); |
| 590 | - qemu_put_8s(f, &fd->dir); | ||
| 591 | - qemu_put_8s(f, &fd->rw); | ||
| 592 | } | 600 | } |
| 593 | 601 | ||
| 594 | static void fdc_save (QEMUFile *f, void *opaque) | 602 | static void fdc_save (QEMUFile *f, void *opaque) |
| @@ -598,17 +606,21 @@ static void fdc_save (QEMUFile *f, void *opaque) | @@ -598,17 +606,21 @@ static void fdc_save (QEMUFile *f, void *opaque) | ||
| 598 | /* Controller state */ | 606 | /* Controller state */ |
| 599 | qemu_put_8s(f, &s->sra); | 607 | qemu_put_8s(f, &s->sra); |
| 600 | qemu_put_8s(f, &s->srb); | 608 | qemu_put_8s(f, &s->srb); |
| 601 | - qemu_put_8s(f, &s->state); | ||
| 602 | - qemu_put_8s(f, &s->dma_en); | 609 | + qemu_put_8s(f, &s->dsr); |
| 610 | + qemu_put_8s(f, &s->msr); | ||
| 611 | + qemu_put_8s(f, &s->status0); | ||
| 612 | + qemu_put_8s(f, &s->status1); | ||
| 613 | + qemu_put_8s(f, &s->status2); | ||
| 603 | qemu_put_8s(f, &s->cur_drv); | 614 | qemu_put_8s(f, &s->cur_drv); |
| 604 | qemu_put_8s(f, &s->bootsel); | 615 | qemu_put_8s(f, &s->bootsel); |
| 616 | + /* Command FIFO */ | ||
| 605 | qemu_put_buffer(f, s->fifo, FD_SECTOR_LEN); | 617 | qemu_put_buffer(f, s->fifo, FD_SECTOR_LEN); |
| 606 | qemu_put_be32s(f, &s->data_pos); | 618 | qemu_put_be32s(f, &s->data_pos); |
| 607 | qemu_put_be32s(f, &s->data_len); | 619 | qemu_put_be32s(f, &s->data_len); |
| 608 | qemu_put_8s(f, &s->data_state); | 620 | qemu_put_8s(f, &s->data_state); |
| 609 | qemu_put_8s(f, &s->data_dir); | 621 | qemu_put_8s(f, &s->data_dir); |
| 610 | - qemu_put_8s(f, &s->int_status); | ||
| 611 | qemu_put_8s(f, &s->eot); | 622 | qemu_put_8s(f, &s->eot); |
| 623 | + /* States kept only to be returned back */ | ||
| 612 | qemu_put_8s(f, &s->timer0); | 624 | qemu_put_8s(f, &s->timer0); |
| 613 | qemu_put_8s(f, &s->timer1); | 625 | qemu_put_8s(f, &s->timer1); |
| 614 | qemu_put_8s(f, &s->precomp_trk); | 626 | qemu_put_8s(f, &s->precomp_trk); |
| @@ -624,8 +636,6 @@ static int fd_load (QEMUFile *f, fdrive_t *fd) | @@ -624,8 +636,6 @@ static int fd_load (QEMUFile *f, fdrive_t *fd) | ||
| 624 | qemu_get_8s(f, &fd->head); | 636 | qemu_get_8s(f, &fd->head); |
| 625 | qemu_get_8s(f, &fd->track); | 637 | qemu_get_8s(f, &fd->track); |
| 626 | qemu_get_8s(f, &fd->sect); | 638 | qemu_get_8s(f, &fd->sect); |
| 627 | - qemu_get_8s(f, &fd->dir); | ||
| 628 | - qemu_get_8s(f, &fd->rw); | ||
| 629 | 639 | ||
| 630 | return 0; | 640 | return 0; |
| 631 | } | 641 | } |
| @@ -635,23 +645,27 @@ static int fdc_load (QEMUFile *f, void *opaque, int version_id) | @@ -635,23 +645,27 @@ static int fdc_load (QEMUFile *f, void *opaque, int version_id) | ||
| 635 | fdctrl_t *s = opaque; | 645 | fdctrl_t *s = opaque; |
| 636 | int ret; | 646 | int ret; |
| 637 | 647 | ||
| 638 | - if (version_id != 1) | 648 | + if (version_id != 2) |
| 639 | return -EINVAL; | 649 | return -EINVAL; |
| 640 | 650 | ||
| 641 | /* Controller state */ | 651 | /* Controller state */ |
| 642 | qemu_get_8s(f, &s->sra); | 652 | qemu_get_8s(f, &s->sra); |
| 643 | qemu_get_8s(f, &s->srb); | 653 | qemu_get_8s(f, &s->srb); |
| 644 | - qemu_get_8s(f, &s->state); | ||
| 645 | - qemu_get_8s(f, &s->dma_en); | 654 | + qemu_get_8s(f, &s->dsr); |
| 655 | + qemu_get_8s(f, &s->msr); | ||
| 656 | + qemu_get_8s(f, &s->status0); | ||
| 657 | + qemu_get_8s(f, &s->status1); | ||
| 658 | + qemu_get_8s(f, &s->status2); | ||
| 646 | qemu_get_8s(f, &s->cur_drv); | 659 | qemu_get_8s(f, &s->cur_drv); |
| 647 | qemu_get_8s(f, &s->bootsel); | 660 | qemu_get_8s(f, &s->bootsel); |
| 661 | + /* Command FIFO */ | ||
| 648 | qemu_get_buffer(f, s->fifo, FD_SECTOR_LEN); | 662 | qemu_get_buffer(f, s->fifo, FD_SECTOR_LEN); |
| 649 | qemu_get_be32s(f, &s->data_pos); | 663 | qemu_get_be32s(f, &s->data_pos); |
| 650 | qemu_get_be32s(f, &s->data_len); | 664 | qemu_get_be32s(f, &s->data_len); |
| 651 | qemu_get_8s(f, &s->data_state); | 665 | qemu_get_8s(f, &s->data_state); |
| 652 | qemu_get_8s(f, &s->data_dir); | 666 | qemu_get_8s(f, &s->data_dir); |
| 653 | - qemu_get_8s(f, &s->int_status); | ||
| 654 | qemu_get_8s(f, &s->eot); | 667 | qemu_get_8s(f, &s->eot); |
| 668 | + /* States kept only to be returned back */ | ||
| 655 | qemu_get_8s(f, &s->timer0); | 669 | qemu_get_8s(f, &s->timer0); |
| 656 | qemu_get_8s(f, &s->timer1); | 670 | qemu_get_8s(f, &s->timer1); |
| 657 | qemu_get_8s(f, &s->precomp_trk); | 671 | qemu_get_8s(f, &s->precomp_trk); |
| @@ -699,22 +713,22 @@ static void fdctrl_reset_irq (fdctrl_t *fdctrl) | @@ -699,22 +713,22 @@ static void fdctrl_reset_irq (fdctrl_t *fdctrl) | ||
| 699 | fdctrl->sra &= ~FD_SRA_INTPEND; | 713 | fdctrl->sra &= ~FD_SRA_INTPEND; |
| 700 | } | 714 | } |
| 701 | 715 | ||
| 702 | -static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status) | 716 | +static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status0) |
| 703 | { | 717 | { |
| 704 | /* Sparc mutation */ | 718 | /* Sparc mutation */ |
| 705 | if (fdctrl->sun4m && (fdctrl->msr & FD_MSR_CMDBUSY)) { | 719 | if (fdctrl->sun4m && (fdctrl->msr & FD_MSR_CMDBUSY)) { |
| 706 | /* XXX: not sure */ | 720 | /* XXX: not sure */ |
| 707 | fdctrl->msr &= ~FD_MSR_CMDBUSY; | 721 | fdctrl->msr &= ~FD_MSR_CMDBUSY; |
| 708 | fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO; | 722 | fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO; |
| 709 | - fdctrl->int_status = status; | 723 | + fdctrl->status0 = status0; |
| 710 | return; | 724 | return; |
| 711 | } | 725 | } |
| 712 | if (!(fdctrl->sra & FD_SRA_INTPEND)) { | 726 | if (!(fdctrl->sra & FD_SRA_INTPEND)) { |
| 713 | qemu_set_irq(fdctrl->irq, 1); | 727 | qemu_set_irq(fdctrl->irq, 1); |
| 714 | fdctrl->sra |= FD_SRA_INTPEND; | 728 | fdctrl->sra |= FD_SRA_INTPEND; |
| 715 | } | 729 | } |
| 716 | - FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", status); | ||
| 717 | - fdctrl->int_status = status; | 730 | + fdctrl->status0 = status0; |
| 731 | + FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", fdctrl->status0); | ||
| 718 | } | 732 | } |
| 719 | 733 | ||
| 720 | /* Reset controller */ | 734 | /* Reset controller */ |
| @@ -741,8 +755,9 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq) | @@ -741,8 +755,9 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq) | ||
| 741 | for (i = 0; i < MAX_FD; i++) | 755 | for (i = 0; i < MAX_FD; i++) |
| 742 | fd_recalibrate(&fdctrl->drives[i]); | 756 | fd_recalibrate(&fdctrl->drives[i]); |
| 743 | fdctrl_reset_fifo(fdctrl); | 757 | fdctrl_reset_fifo(fdctrl); |
| 744 | - if (do_irq) | 758 | + if (do_irq) { |
| 745 | fdctrl_raise_irq(fdctrl, FD_SR0_RDYCHG); | 759 | fdctrl_raise_irq(fdctrl, FD_SR0_RDYCHG); |
| 760 | + } | ||
| 746 | } | 761 | } |
| 747 | 762 | ||
| 748 | static inline fdrive_t *drv0 (fdctrl_t *fdctrl) | 763 | static inline fdrive_t *drv0 (fdctrl_t *fdctrl) |
| @@ -939,19 +954,9 @@ static void fdctrl_set_fifo (fdctrl_t *fdctrl, int fifo_len, int do_irq) | @@ -939,19 +954,9 @@ static void fdctrl_set_fifo (fdctrl_t *fdctrl, int fifo_len, int do_irq) | ||
| 939 | /* Set an error: unimplemented/unknown command */ | 954 | /* Set an error: unimplemented/unknown command */ |
| 940 | static void fdctrl_unimplemented (fdctrl_t *fdctrl, int direction) | 955 | static void fdctrl_unimplemented (fdctrl_t *fdctrl, int direction) |
| 941 | { | 956 | { |
| 942 | -#if 0 | ||
| 943 | - fdrive_t *cur_drv; | ||
| 944 | - | ||
| 945 | - cur_drv = get_cur_drv(fdctrl); | ||
| 946 | - fdctrl->fifo[0] = FD_SR0_ABNTERM | FD_SR0_SEEK | (cur_drv->head << 2) | fdctrl->cur_drv; | ||
| 947 | - fdctrl->fifo[1] = 0x00; | ||
| 948 | - fdctrl->fifo[2] = 0x00; | ||
| 949 | - fdctrl_set_fifo(fdctrl, 3, 1); | ||
| 950 | -#else | ||
| 951 | - // fdctrl_reset_fifo(fdctrl); | 957 | + FLOPPY_ERROR("unimplemented command 0x%02x\n", fdctrl->fifo[0]); |
| 952 | fdctrl->fifo[0] = FD_SR0_INVCMD; | 958 | fdctrl->fifo[0] = FD_SR0_INVCMD; |
| 953 | fdctrl_set_fifo(fdctrl, 1, 0); | 959 | fdctrl_set_fifo(fdctrl, 1, 0); |
| 954 | -#endif | ||
| 955 | } | 960 | } |
| 956 | 961 | ||
| 957 | /* Seek to next sector */ | 962 | /* Seek to next sector */ |
| @@ -1019,7 +1024,7 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) | @@ -1019,7 +1024,7 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) | ||
| 1019 | { | 1024 | { |
| 1020 | fdrive_t *cur_drv; | 1025 | fdrive_t *cur_drv; |
| 1021 | uint8_t kh, kt, ks; | 1026 | uint8_t kh, kt, ks; |
| 1022 | - int did_seek; | 1027 | + int did_seek = 0; |
| 1023 | 1028 | ||
| 1024 | fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK; | 1029 | fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK; |
| 1025 | cur_drv = get_cur_drv(fdctrl); | 1030 | cur_drv = get_cur_drv(fdctrl); |
| @@ -1029,8 +1034,7 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) | @@ -1029,8 +1034,7 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) | ||
| 1029 | FLOPPY_DPRINTF("Start transfer at %d %d %02x %02x (%d)\n", | 1034 | FLOPPY_DPRINTF("Start transfer at %d %d %02x %02x (%d)\n", |
| 1030 | fdctrl->cur_drv, kh, kt, ks, | 1035 | fdctrl->cur_drv, kh, kt, ks, |
| 1031 | _fd_sector(kh, kt, ks, cur_drv->last_sect)); | 1036 | _fd_sector(kh, kt, ks, cur_drv->last_sect)); |
| 1032 | - did_seek = 0; | ||
| 1033 | - switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & 0x40)) { | 1037 | + switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) { |
| 1034 | case 2: | 1038 | case 2: |
| 1035 | /* sect too big */ | 1039 | /* sect too big */ |
| 1036 | fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00); | 1040 | fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00); |
| @@ -1040,7 +1044,7 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) | @@ -1040,7 +1044,7 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) | ||
| 1040 | return; | 1044 | return; |
| 1041 | case 3: | 1045 | case 3: |
| 1042 | /* track too big */ | 1046 | /* track too big */ |
| 1043 | - fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x80, 0x00); | 1047 | + fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_EC, 0x00); |
| 1044 | fdctrl->fifo[3] = kt; | 1048 | fdctrl->fifo[3] = kt; |
| 1045 | fdctrl->fifo[4] = kh; | 1049 | fdctrl->fifo[4] = kh; |
| 1046 | fdctrl->fifo[5] = ks; | 1050 | fdctrl->fifo[5] = ks; |
| @@ -1120,6 +1124,8 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) | @@ -1120,6 +1124,8 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) | ||
| 1120 | /* Prepare a transfer of deleted data */ | 1124 | /* Prepare a transfer of deleted data */ |
| 1121 | static void fdctrl_start_transfer_del (fdctrl_t *fdctrl, int direction) | 1125 | static void fdctrl_start_transfer_del (fdctrl_t *fdctrl, int direction) |
| 1122 | { | 1126 | { |
| 1127 | + FLOPPY_ERROR("fdctrl_start_transfer_del() unimplemented\n"); | ||
| 1128 | + | ||
| 1123 | /* We don't handle deleted data, | 1129 | /* We don't handle deleted data, |
| 1124 | * so we don't return *ANYTHING* | 1130 | * so we don't return *ANYTHING* |
| 1125 | */ | 1131 | */ |
| @@ -1143,7 +1149,7 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, | @@ -1143,7 +1149,7 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, | ||
| 1143 | cur_drv = get_cur_drv(fdctrl); | 1149 | cur_drv = get_cur_drv(fdctrl); |
| 1144 | if (fdctrl->data_dir == FD_DIR_SCANE || fdctrl->data_dir == FD_DIR_SCANL || | 1150 | if (fdctrl->data_dir == FD_DIR_SCANE || fdctrl->data_dir == FD_DIR_SCANL || |
| 1145 | fdctrl->data_dir == FD_DIR_SCANH) | 1151 | fdctrl->data_dir == FD_DIR_SCANH) |
| 1146 | - status2 = 0x04; | 1152 | + status2 = FD_SR2_SNS; |
| 1147 | if (dma_len > fdctrl->data_len) | 1153 | if (dma_len > fdctrl->data_len) |
| 1148 | dma_len = fdctrl->data_len; | 1154 | dma_len = fdctrl->data_len; |
| 1149 | if (cur_drv->bs == NULL) { | 1155 | if (cur_drv->bs == NULL) { |
| @@ -1187,7 +1193,7 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, | @@ -1187,7 +1193,7 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, | ||
| 1187 | fdctrl->data_pos, len); | 1193 | fdctrl->data_pos, len); |
| 1188 | if (bdrv_write(cur_drv->bs, fd_sector(cur_drv), | 1194 | if (bdrv_write(cur_drv->bs, fd_sector(cur_drv), |
| 1189 | fdctrl->fifo, 1) < 0) { | 1195 | fdctrl->fifo, 1) < 0) { |
| 1190 | - FLOPPY_ERROR("writting sector %d\n", fd_sector(cur_drv)); | 1196 | + FLOPPY_ERROR("writing sector %d\n", fd_sector(cur_drv)); |
| 1191 | fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00); | 1197 | fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00); |
| 1192 | goto transfer_error; | 1198 | goto transfer_error; |
| 1193 | } | 1199 | } |
| @@ -1200,7 +1206,7 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, | @@ -1200,7 +1206,7 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, | ||
| 1200 | DMA_read_memory (nchan, tmpbuf, fdctrl->data_pos, len); | 1206 | DMA_read_memory (nchan, tmpbuf, fdctrl->data_pos, len); |
| 1201 | ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len); | 1207 | ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len); |
| 1202 | if (ret == 0) { | 1208 | if (ret == 0) { |
| 1203 | - status2 = 0x08; | 1209 | + status2 = FD_SR2_SEH; |
| 1204 | goto end_transfer; | 1210 | goto end_transfer; |
| 1205 | } | 1211 | } |
| 1206 | if ((ret < 0 && fdctrl->data_dir == FD_DIR_SCANL) || | 1212 | if ((ret < 0 && fdctrl->data_dir == FD_DIR_SCANL) || |
| @@ -1226,11 +1232,10 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, | @@ -1226,11 +1232,10 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, | ||
| 1226 | if (fdctrl->data_dir == FD_DIR_SCANE || | 1232 | if (fdctrl->data_dir == FD_DIR_SCANE || |
| 1227 | fdctrl->data_dir == FD_DIR_SCANL || | 1233 | fdctrl->data_dir == FD_DIR_SCANL || |
| 1228 | fdctrl->data_dir == FD_DIR_SCANH) | 1234 | fdctrl->data_dir == FD_DIR_SCANH) |
| 1229 | - status2 = 0x08; | 1235 | + status2 = FD_SR2_SEH; |
| 1230 | if (FD_DID_SEEK(fdctrl->data_state)) | 1236 | if (FD_DID_SEEK(fdctrl->data_state)) |
| 1231 | status0 |= FD_SR0_SEEK; | 1237 | status0 |= FD_SR0_SEEK; |
| 1232 | fdctrl->data_len -= len; | 1238 | fdctrl->data_len -= len; |
| 1233 | - // if (fdctrl->data_len == 0) | ||
| 1234 | fdctrl_stop_transfer(fdctrl, status0, status1, status2); | 1239 | fdctrl_stop_transfer(fdctrl, status0, status1, status2); |
| 1235 | transfer_error: | 1240 | transfer_error: |
| 1236 | 1241 | ||
| @@ -1260,7 +1265,12 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl) | @@ -1260,7 +1265,12 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl) | ||
| 1260 | fd_sector(cur_drv)); | 1265 | fd_sector(cur_drv)); |
| 1261 | return 0; | 1266 | return 0; |
| 1262 | } | 1267 | } |
| 1263 | - bdrv_read(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1); | 1268 | + if (bdrv_read(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) { |
| 1269 | + FLOPPY_DPRINTF("error getting sector %d\n", | ||
| 1270 | + fd_sector(cur_drv)); | ||
| 1271 | + /* Sure, image size is too small... */ | ||
| 1272 | + memset(fdctrl->fifo, 0, FD_SECTOR_LEN); | ||
| 1273 | + } | ||
| 1264 | } | 1274 | } |
| 1265 | } | 1275 | } |
| 1266 | retval = fdctrl->fifo[pos]; | 1276 | retval = fdctrl->fifo[pos]; |
| @@ -1285,7 +1295,6 @@ static void fdctrl_format_sector (fdctrl_t *fdctrl) | @@ -1285,7 +1295,6 @@ static void fdctrl_format_sector (fdctrl_t *fdctrl) | ||
| 1285 | { | 1295 | { |
| 1286 | fdrive_t *cur_drv; | 1296 | fdrive_t *cur_drv; |
| 1287 | uint8_t kh, kt, ks; | 1297 | uint8_t kh, kt, ks; |
| 1288 | - int did_seek; | ||
| 1289 | 1298 | ||
| 1290 | fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK; | 1299 | fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK; |
| 1291 | cur_drv = get_cur_drv(fdctrl); | 1300 | cur_drv = get_cur_drv(fdctrl); |
| @@ -1295,7 +1304,6 @@ static void fdctrl_format_sector (fdctrl_t *fdctrl) | @@ -1295,7 +1304,6 @@ static void fdctrl_format_sector (fdctrl_t *fdctrl) | ||
| 1295 | FLOPPY_DPRINTF("format sector at %d %d %02x %02x (%d)\n", | 1304 | FLOPPY_DPRINTF("format sector at %d %d %02x %02x (%d)\n", |
| 1296 | fdctrl->cur_drv, kh, kt, ks, | 1305 | fdctrl->cur_drv, kh, kt, ks, |
| 1297 | _fd_sector(kh, kt, ks, cur_drv->last_sect)); | 1306 | _fd_sector(kh, kt, ks, cur_drv->last_sect)); |
| 1298 | - did_seek = 0; | ||
| 1299 | switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) { | 1307 | switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) { |
| 1300 | case 2: | 1308 | case 2: |
| 1301 | /* sect too big */ | 1309 | /* sect too big */ |
| @@ -1306,7 +1314,7 @@ static void fdctrl_format_sector (fdctrl_t *fdctrl) | @@ -1306,7 +1314,7 @@ static void fdctrl_format_sector (fdctrl_t *fdctrl) | ||
| 1306 | return; | 1314 | return; |
| 1307 | case 3: | 1315 | case 3: |
| 1308 | /* track too big */ | 1316 | /* track too big */ |
| 1309 | - fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x80, 0x00); | 1317 | + fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_EC, 0x00); |
| 1310 | fdctrl->fifo[3] = kt; | 1318 | fdctrl->fifo[3] = kt; |
| 1311 | fdctrl->fifo[4] = kh; | 1319 | fdctrl->fifo[4] = kh; |
| 1312 | fdctrl->fifo[5] = ks; | 1320 | fdctrl->fifo[5] = ks; |
| @@ -1319,7 +1327,6 @@ static void fdctrl_format_sector (fdctrl_t *fdctrl) | @@ -1319,7 +1327,6 @@ static void fdctrl_format_sector (fdctrl_t *fdctrl) | ||
| 1319 | fdctrl->fifo[5] = ks; | 1327 | fdctrl->fifo[5] = ks; |
| 1320 | return; | 1328 | return; |
| 1321 | case 1: | 1329 | case 1: |
| 1322 | - did_seek = 1; | ||
| 1323 | fdctrl->data_state |= FD_STATE_SEEK; | 1330 | fdctrl->data_state |= FD_STATE_SEEK; |
| 1324 | break; | 1331 | break; |
| 1325 | default: | 1332 | default: |
| @@ -1515,18 +1522,18 @@ static void fdctrl_handle_sense_interrupt_status (fdctrl_t *fdctrl, int directio | @@ -1515,18 +1522,18 @@ static void fdctrl_handle_sense_interrupt_status (fdctrl_t *fdctrl, int directio | ||
| 1515 | 1522 | ||
| 1516 | #if 0 | 1523 | #if 0 |
| 1517 | fdctrl->fifo[0] = | 1524 | fdctrl->fifo[0] = |
| 1518 | - fdctrl->int_status | (cur_drv->head << 2) | fdctrl->cur_drv; | 1525 | + fdctrl->status0 | (cur_drv->head << 2) | fdctrl->cur_drv; |
| 1519 | #else | 1526 | #else |
| 1520 | - /* XXX: int_status handling is broken for read/write | 1527 | + /* XXX: status0 handling is broken for read/write |
| 1521 | commands, so we do this hack. It should be suppressed | 1528 | commands, so we do this hack. It should be suppressed |
| 1522 | ASAP */ | 1529 | ASAP */ |
| 1523 | fdctrl->fifo[0] = | 1530 | fdctrl->fifo[0] = |
| 1524 | - 0x20 | (cur_drv->head << 2) | fdctrl->cur_drv; | 1531 | + FD_SR0_SEEK | (cur_drv->head << 2) | fdctrl->cur_drv; |
| 1525 | #endif | 1532 | #endif |
| 1526 | fdctrl->fifo[1] = cur_drv->track; | 1533 | fdctrl->fifo[1] = cur_drv->track; |
| 1527 | fdctrl_set_fifo(fdctrl, 2, 0); | 1534 | fdctrl_set_fifo(fdctrl, 2, 0); |
| 1528 | fdctrl_reset_irq(fdctrl); | 1535 | fdctrl_reset_irq(fdctrl); |
| 1529 | - fdctrl->int_status = FD_SR0_RDYCHG; | 1536 | + fdctrl->status0 = FD_SR0_RDYCHG; |
| 1530 | } | 1537 | } |
| 1531 | 1538 | ||
| 1532 | static void fdctrl_handle_seek (fdctrl_t *fdctrl, int direction) | 1539 | static void fdctrl_handle_seek (fdctrl_t *fdctrl, int direction) |
| @@ -1535,10 +1542,6 @@ static void fdctrl_handle_seek (fdctrl_t *fdctrl, int direction) | @@ -1535,10 +1542,6 @@ static void fdctrl_handle_seek (fdctrl_t *fdctrl, int direction) | ||
| 1535 | 1542 | ||
| 1536 | fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK; | 1543 | fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK; |
| 1537 | cur_drv = get_cur_drv(fdctrl); | 1544 | cur_drv = get_cur_drv(fdctrl); |
| 1538 | - if (fdctrl->fifo[2] <= cur_drv->track) | ||
| 1539 | - cur_drv->dir = 1; | ||
| 1540 | - else | ||
| 1541 | - cur_drv->dir = 0; | ||
| 1542 | fdctrl_reset_fifo(fdctrl); | 1545 | fdctrl_reset_fifo(fdctrl); |
| 1543 | if (fdctrl->fifo[2] > cur_drv->max_track) { | 1546 | if (fdctrl->fifo[2] > cur_drv->max_track) { |
| 1544 | fdctrl_raise_irq(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK); | 1547 | fdctrl_raise_irq(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK); |
| @@ -1604,27 +1607,26 @@ static void fdctrl_handle_drive_specification_command (fdctrl_t *fdctrl, int dir | @@ -1604,27 +1607,26 @@ static void fdctrl_handle_drive_specification_command (fdctrl_t *fdctrl, int dir | ||
| 1604 | 1607 | ||
| 1605 | static void fdctrl_handle_relative_seek_out (fdctrl_t *fdctrl, int direction) | 1608 | static void fdctrl_handle_relative_seek_out (fdctrl_t *fdctrl, int direction) |
| 1606 | { | 1609 | { |
| 1607 | - fdrive_t *cur_drv = get_cur_drv(fdctrl); | 1610 | + fdrive_t *cur_drv; |
| 1608 | 1611 | ||
| 1609 | fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK; | 1612 | fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK; |
| 1610 | cur_drv = get_cur_drv(fdctrl); | 1613 | cur_drv = get_cur_drv(fdctrl); |
| 1611 | - cur_drv->dir = 0; | ||
| 1612 | if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) { | 1614 | if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) { |
| 1613 | cur_drv->track = cur_drv->max_track - 1; | 1615 | cur_drv->track = cur_drv->max_track - 1; |
| 1614 | } else { | 1616 | } else { |
| 1615 | cur_drv->track += fdctrl->fifo[2]; | 1617 | cur_drv->track += fdctrl->fifo[2]; |
| 1616 | } | 1618 | } |
| 1617 | fdctrl_reset_fifo(fdctrl); | 1619 | fdctrl_reset_fifo(fdctrl); |
| 1620 | + /* Raise Interrupt */ | ||
| 1618 | fdctrl_raise_irq(fdctrl, FD_SR0_SEEK); | 1621 | fdctrl_raise_irq(fdctrl, FD_SR0_SEEK); |
| 1619 | } | 1622 | } |
| 1620 | 1623 | ||
| 1621 | static void fdctrl_handle_relative_seek_in (fdctrl_t *fdctrl, int direction) | 1624 | static void fdctrl_handle_relative_seek_in (fdctrl_t *fdctrl, int direction) |
| 1622 | { | 1625 | { |
| 1623 | - fdrive_t *cur_drv = get_cur_drv(fdctrl); | 1626 | + fdrive_t *cur_drv; |
| 1624 | 1627 | ||
| 1625 | fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK; | 1628 | fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK; |
| 1626 | cur_drv = get_cur_drv(fdctrl); | 1629 | cur_drv = get_cur_drv(fdctrl); |
| 1627 | - cur_drv->dir = 1; | ||
| 1628 | if (fdctrl->fifo[2] > cur_drv->track) { | 1630 | if (fdctrl->fifo[2] > cur_drv->track) { |
| 1629 | cur_drv->track = 0; | 1631 | cur_drv->track = 0; |
| 1630 | } else { | 1632 | } else { |
| @@ -1684,7 +1686,6 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) | @@ -1684,7 +1686,6 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) | ||
| 1684 | fdrive_t *cur_drv; | 1686 | fdrive_t *cur_drv; |
| 1685 | int pos; | 1687 | int pos; |
| 1686 | 1688 | ||
| 1687 | - cur_drv = get_cur_drv(fdctrl); | ||
| 1688 | /* Reset mode */ | 1689 | /* Reset mode */ |
| 1689 | if (!(fdctrl->dor & FD_DOR_nRESET)) { | 1690 | if (!(fdctrl->dor & FD_DOR_nRESET)) { |
| 1690 | FLOPPY_DPRINTF("Floppy controller in RESET state !\n"); | 1691 | FLOPPY_DPRINTF("Floppy controller in RESET state !\n"); |
| @@ -1701,7 +1702,11 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) | @@ -1701,7 +1702,11 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) | ||
| 1701 | fdctrl->fifo[fdctrl->data_pos++] = value; | 1702 | fdctrl->fifo[fdctrl->data_pos++] = value; |
| 1702 | if (fdctrl->data_pos % FD_SECTOR_LEN == (FD_SECTOR_LEN - 1) || | 1703 | if (fdctrl->data_pos % FD_SECTOR_LEN == (FD_SECTOR_LEN - 1) || |
| 1703 | fdctrl->data_pos == fdctrl->data_len) { | 1704 | fdctrl->data_pos == fdctrl->data_len) { |
| 1704 | - bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1); | 1705 | + cur_drv = get_cur_drv(fdctrl); |
| 1706 | + if (bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) { | ||
| 1707 | + FLOPPY_ERROR("writing sector %d\n", fd_sector(cur_drv)); | ||
| 1708 | + return; | ||
| 1709 | + } | ||
| 1705 | if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) { | 1710 | if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) { |
| 1706 | FLOPPY_DPRINTF("error seeking to next sector %d\n", | 1711 | FLOPPY_DPRINTF("error seeking to next sector %d\n", |
| 1707 | fd_sector(cur_drv)); | 1712 | fd_sector(cur_drv)); |
| @@ -1723,8 +1728,8 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) | @@ -1723,8 +1728,8 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) | ||
| 1723 | } | 1728 | } |
| 1724 | 1729 | ||
| 1725 | FLOPPY_DPRINTF("%s: %02x\n", __func__, value); | 1730 | FLOPPY_DPRINTF("%s: %02x\n", __func__, value); |
| 1726 | - fdctrl->fifo[fdctrl->data_pos] = value; | ||
| 1727 | - if (++fdctrl->data_pos == fdctrl->data_len) { | 1731 | + fdctrl->fifo[fdctrl->data_pos++] = value; |
| 1732 | + if (fdctrl->data_pos == fdctrl->data_len) { | ||
| 1728 | /* We now have all parameters | 1733 | /* We now have all parameters |
| 1729 | * and will be able to treat the command | 1734 | * and will be able to treat the command |
| 1730 | */ | 1735 | */ |
| @@ -1793,8 +1798,8 @@ static fdctrl_t *fdctrl_init_common (qemu_irq irq, int dma_chann, | @@ -1793,8 +1798,8 @@ static fdctrl_t *fdctrl_init_common (qemu_irq irq, int dma_chann, | ||
| 1793 | for (i = 0; i < MAX_FD; i++) { | 1798 | for (i = 0; i < MAX_FD; i++) { |
| 1794 | fd_init(&fdctrl->drives[i], fds[i]); | 1799 | fd_init(&fdctrl->drives[i], fds[i]); |
| 1795 | } | 1800 | } |
| 1796 | - fdctrl_reset(fdctrl, 0); | ||
| 1797 | - register_savevm("fdc", io_base, 1, fdc_save, fdc_load, fdctrl); | 1801 | + fdctrl_external_reset(fdctrl); |
| 1802 | + register_savevm("fdc", io_base, 2, fdc_save, fdc_load, fdctrl); | ||
| 1798 | qemu_register_reset(fdctrl_external_reset, fdctrl); | 1803 | qemu_register_reset(fdctrl_external_reset, fdctrl); |
| 1799 | for (i = 0; i < MAX_FD; i++) { | 1804 | for (i = 0; i < MAX_FD; i++) { |
| 1800 | fd_revalidate(&fdctrl->drives[i]); | 1805 | fd_revalidate(&fdctrl->drives[i]); |