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]); |