Commit 77370520924697c6deb6964a7328f7fceaaecc17

Authored by blueswir1
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]);