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 | 82 | uint8_t head; |
83 | 83 | uint8_t track; |
84 | 84 | uint8_t sect; |
85 | - /* Last operation status */ | |
86 | - uint8_t dir; /* Direction */ | |
87 | - uint8_t rw; /* Read/write */ | |
88 | 85 | /* Media */ |
89 | 86 | fdisk_flags_t flags; |
90 | 87 | uint8_t last_sect; /* Nb sector per track */ |
... | ... | @@ -116,6 +113,13 @@ static int fd_sector (fdrive_t *drv) |
116 | 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 | 123 | static int fd_seek (fdrive_t *drv, uint8_t head, uint8_t track, uint8_t sect, |
120 | 124 | int enable_seek) |
121 | 125 | { |
... | ... | @@ -164,8 +168,6 @@ static void fd_recalibrate (fdrive_t *drv) |
164 | 168 | drv->head = 0; |
165 | 169 | drv->track = 0; |
166 | 170 | drv->sect = 1; |
167 | - drv->dir = 1; | |
168 | - drv->rw = 0; | |
169 | 171 | } |
170 | 172 | |
171 | 173 | /* Recognize floppy formats */ |
... | ... | @@ -297,7 +299,7 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq); |
297 | 299 | static void fdctrl_reset_fifo (fdctrl_t *fdctrl); |
298 | 300 | static int fdctrl_transfer_handler (void *opaque, int nchan, |
299 | 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 | 304 | static uint32_t fdctrl_read_statusA (fdctrl_t *fdctrl); |
303 | 305 | static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl); |
... | ... | @@ -386,6 +388,15 @@ enum { |
386 | 388 | }; |
387 | 389 | |
388 | 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 | 400 | FD_SRA_DIR = 0x01, |
390 | 401 | FD_SRA_nWP = 0x02, |
391 | 402 | FD_SRA_nINDX = 0x04, |
... | ... | @@ -445,7 +456,6 @@ enum { |
445 | 456 | #define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT) |
446 | 457 | |
447 | 458 | struct fdctrl_t { |
448 | - fdctrl_t *fdctrl; | |
449 | 459 | /* Controller's identification */ |
450 | 460 | uint8_t version; |
451 | 461 | /* HW */ |
... | ... | @@ -459,17 +469,17 @@ struct fdctrl_t { |
459 | 469 | uint8_t dor; |
460 | 470 | uint8_t dsr; |
461 | 471 | uint8_t msr; |
462 | - uint8_t state; | |
463 | - uint8_t dma_en; | |
464 | 472 | uint8_t cur_drv; |
465 | 473 | uint8_t bootsel; |
474 | + uint8_t status0; | |
475 | + uint8_t status1; | |
476 | + uint8_t status2; | |
466 | 477 | /* Command FIFO */ |
467 | 478 | uint8_t *fifo; |
468 | 479 | uint32_t data_pos; |
469 | 480 | uint32_t data_len; |
470 | 481 | uint8_t data_state; |
471 | 482 | uint8_t data_dir; |
472 | - uint8_t int_status; | |
473 | 483 | uint8_t eot; /* last wanted sector */ |
474 | 484 | /* States kept only to be returned back */ |
475 | 485 | /* Timers state */ |
... | ... | @@ -587,8 +597,6 @@ static void fd_save (QEMUFile *f, fdrive_t *fd) |
587 | 597 | qemu_put_8s(f, &fd->head); |
588 | 598 | qemu_put_8s(f, &fd->track); |
589 | 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 | 602 | static void fdc_save (QEMUFile *f, void *opaque) |
... | ... | @@ -598,17 +606,21 @@ static void fdc_save (QEMUFile *f, void *opaque) |
598 | 606 | /* Controller state */ |
599 | 607 | qemu_put_8s(f, &s->sra); |
600 | 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 | 614 | qemu_put_8s(f, &s->cur_drv); |
604 | 615 | qemu_put_8s(f, &s->bootsel); |
616 | + /* Command FIFO */ | |
605 | 617 | qemu_put_buffer(f, s->fifo, FD_SECTOR_LEN); |
606 | 618 | qemu_put_be32s(f, &s->data_pos); |
607 | 619 | qemu_put_be32s(f, &s->data_len); |
608 | 620 | qemu_put_8s(f, &s->data_state); |
609 | 621 | qemu_put_8s(f, &s->data_dir); |
610 | - qemu_put_8s(f, &s->int_status); | |
611 | 622 | qemu_put_8s(f, &s->eot); |
623 | + /* States kept only to be returned back */ | |
612 | 624 | qemu_put_8s(f, &s->timer0); |
613 | 625 | qemu_put_8s(f, &s->timer1); |
614 | 626 | qemu_put_8s(f, &s->precomp_trk); |
... | ... | @@ -624,8 +636,6 @@ static int fd_load (QEMUFile *f, fdrive_t *fd) |
624 | 636 | qemu_get_8s(f, &fd->head); |
625 | 637 | qemu_get_8s(f, &fd->track); |
626 | 638 | qemu_get_8s(f, &fd->sect); |
627 | - qemu_get_8s(f, &fd->dir); | |
628 | - qemu_get_8s(f, &fd->rw); | |
629 | 639 | |
630 | 640 | return 0; |
631 | 641 | } |
... | ... | @@ -635,23 +645,27 @@ static int fdc_load (QEMUFile *f, void *opaque, int version_id) |
635 | 645 | fdctrl_t *s = opaque; |
636 | 646 | int ret; |
637 | 647 | |
638 | - if (version_id != 1) | |
648 | + if (version_id != 2) | |
639 | 649 | return -EINVAL; |
640 | 650 | |
641 | 651 | /* Controller state */ |
642 | 652 | qemu_get_8s(f, &s->sra); |
643 | 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 | 659 | qemu_get_8s(f, &s->cur_drv); |
647 | 660 | qemu_get_8s(f, &s->bootsel); |
661 | + /* Command FIFO */ | |
648 | 662 | qemu_get_buffer(f, s->fifo, FD_SECTOR_LEN); |
649 | 663 | qemu_get_be32s(f, &s->data_pos); |
650 | 664 | qemu_get_be32s(f, &s->data_len); |
651 | 665 | qemu_get_8s(f, &s->data_state); |
652 | 666 | qemu_get_8s(f, &s->data_dir); |
653 | - qemu_get_8s(f, &s->int_status); | |
654 | 667 | qemu_get_8s(f, &s->eot); |
668 | + /* States kept only to be returned back */ | |
655 | 669 | qemu_get_8s(f, &s->timer0); |
656 | 670 | qemu_get_8s(f, &s->timer1); |
657 | 671 | qemu_get_8s(f, &s->precomp_trk); |
... | ... | @@ -699,22 +713,22 @@ static void fdctrl_reset_irq (fdctrl_t *fdctrl) |
699 | 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 | 718 | /* Sparc mutation */ |
705 | 719 | if (fdctrl->sun4m && (fdctrl->msr & FD_MSR_CMDBUSY)) { |
706 | 720 | /* XXX: not sure */ |
707 | 721 | fdctrl->msr &= ~FD_MSR_CMDBUSY; |
708 | 722 | fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO; |
709 | - fdctrl->int_status = status; | |
723 | + fdctrl->status0 = status0; | |
710 | 724 | return; |
711 | 725 | } |
712 | 726 | if (!(fdctrl->sra & FD_SRA_INTPEND)) { |
713 | 727 | qemu_set_irq(fdctrl->irq, 1); |
714 | 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 | 734 | /* Reset controller */ |
... | ... | @@ -741,8 +755,9 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq) |
741 | 755 | for (i = 0; i < MAX_FD; i++) |
742 | 756 | fd_recalibrate(&fdctrl->drives[i]); |
743 | 757 | fdctrl_reset_fifo(fdctrl); |
744 | - if (do_irq) | |
758 | + if (do_irq) { | |
745 | 759 | fdctrl_raise_irq(fdctrl, FD_SR0_RDYCHG); |
760 | + } | |
746 | 761 | } |
747 | 762 | |
748 | 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 | 954 | /* Set an error: unimplemented/unknown command */ |
940 | 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 | 958 | fdctrl->fifo[0] = FD_SR0_INVCMD; |
953 | 959 | fdctrl_set_fifo(fdctrl, 1, 0); |
954 | -#endif | |
955 | 960 | } |
956 | 961 | |
957 | 962 | /* Seek to next sector */ |
... | ... | @@ -1019,7 +1024,7 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) |
1019 | 1024 | { |
1020 | 1025 | fdrive_t *cur_drv; |
1021 | 1026 | uint8_t kh, kt, ks; |
1022 | - int did_seek; | |
1027 | + int did_seek = 0; | |
1023 | 1028 | |
1024 | 1029 | fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK; |
1025 | 1030 | cur_drv = get_cur_drv(fdctrl); |
... | ... | @@ -1029,8 +1034,7 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) |
1029 | 1034 | FLOPPY_DPRINTF("Start transfer at %d %d %02x %02x (%d)\n", |
1030 | 1035 | fdctrl->cur_drv, kh, kt, ks, |
1031 | 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 | 1038 | case 2: |
1035 | 1039 | /* sect too big */ |
1036 | 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 | 1044 | return; |
1041 | 1045 | case 3: |
1042 | 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 | 1048 | fdctrl->fifo[3] = kt; |
1045 | 1049 | fdctrl->fifo[4] = kh; |
1046 | 1050 | fdctrl->fifo[5] = ks; |
... | ... | @@ -1120,6 +1124,8 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) |
1120 | 1124 | /* Prepare a transfer of deleted data */ |
1121 | 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 | 1129 | /* We don't handle deleted data, |
1124 | 1130 | * so we don't return *ANYTHING* |
1125 | 1131 | */ |
... | ... | @@ -1143,7 +1149,7 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, |
1143 | 1149 | cur_drv = get_cur_drv(fdctrl); |
1144 | 1150 | if (fdctrl->data_dir == FD_DIR_SCANE || fdctrl->data_dir == FD_DIR_SCANL || |
1145 | 1151 | fdctrl->data_dir == FD_DIR_SCANH) |
1146 | - status2 = 0x04; | |
1152 | + status2 = FD_SR2_SNS; | |
1147 | 1153 | if (dma_len > fdctrl->data_len) |
1148 | 1154 | dma_len = fdctrl->data_len; |
1149 | 1155 | if (cur_drv->bs == NULL) { |
... | ... | @@ -1187,7 +1193,7 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, |
1187 | 1193 | fdctrl->data_pos, len); |
1188 | 1194 | if (bdrv_write(cur_drv->bs, fd_sector(cur_drv), |
1189 | 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 | 1197 | fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00); |
1192 | 1198 | goto transfer_error; |
1193 | 1199 | } |
... | ... | @@ -1200,7 +1206,7 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, |
1200 | 1206 | DMA_read_memory (nchan, tmpbuf, fdctrl->data_pos, len); |
1201 | 1207 | ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len); |
1202 | 1208 | if (ret == 0) { |
1203 | - status2 = 0x08; | |
1209 | + status2 = FD_SR2_SEH; | |
1204 | 1210 | goto end_transfer; |
1205 | 1211 | } |
1206 | 1212 | if ((ret < 0 && fdctrl->data_dir == FD_DIR_SCANL) || |
... | ... | @@ -1226,11 +1232,10 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, |
1226 | 1232 | if (fdctrl->data_dir == FD_DIR_SCANE || |
1227 | 1233 | fdctrl->data_dir == FD_DIR_SCANL || |
1228 | 1234 | fdctrl->data_dir == FD_DIR_SCANH) |
1229 | - status2 = 0x08; | |
1235 | + status2 = FD_SR2_SEH; | |
1230 | 1236 | if (FD_DID_SEEK(fdctrl->data_state)) |
1231 | 1237 | status0 |= FD_SR0_SEEK; |
1232 | 1238 | fdctrl->data_len -= len; |
1233 | - // if (fdctrl->data_len == 0) | |
1234 | 1239 | fdctrl_stop_transfer(fdctrl, status0, status1, status2); |
1235 | 1240 | transfer_error: |
1236 | 1241 | |
... | ... | @@ -1260,7 +1265,12 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl) |
1260 | 1265 | fd_sector(cur_drv)); |
1261 | 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 | 1276 | retval = fdctrl->fifo[pos]; |
... | ... | @@ -1285,7 +1295,6 @@ static void fdctrl_format_sector (fdctrl_t *fdctrl) |
1285 | 1295 | { |
1286 | 1296 | fdrive_t *cur_drv; |
1287 | 1297 | uint8_t kh, kt, ks; |
1288 | - int did_seek; | |
1289 | 1298 | |
1290 | 1299 | fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK; |
1291 | 1300 | cur_drv = get_cur_drv(fdctrl); |
... | ... | @@ -1295,7 +1304,6 @@ static void fdctrl_format_sector (fdctrl_t *fdctrl) |
1295 | 1304 | FLOPPY_DPRINTF("format sector at %d %d %02x %02x (%d)\n", |
1296 | 1305 | fdctrl->cur_drv, kh, kt, ks, |
1297 | 1306 | _fd_sector(kh, kt, ks, cur_drv->last_sect)); |
1298 | - did_seek = 0; | |
1299 | 1307 | switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) { |
1300 | 1308 | case 2: |
1301 | 1309 | /* sect too big */ |
... | ... | @@ -1306,7 +1314,7 @@ static void fdctrl_format_sector (fdctrl_t *fdctrl) |
1306 | 1314 | return; |
1307 | 1315 | case 3: |
1308 | 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 | 1318 | fdctrl->fifo[3] = kt; |
1311 | 1319 | fdctrl->fifo[4] = kh; |
1312 | 1320 | fdctrl->fifo[5] = ks; |
... | ... | @@ -1319,7 +1327,6 @@ static void fdctrl_format_sector (fdctrl_t *fdctrl) |
1319 | 1327 | fdctrl->fifo[5] = ks; |
1320 | 1328 | return; |
1321 | 1329 | case 1: |
1322 | - did_seek = 1; | |
1323 | 1330 | fdctrl->data_state |= FD_STATE_SEEK; |
1324 | 1331 | break; |
1325 | 1332 | default: |
... | ... | @@ -1515,18 +1522,18 @@ static void fdctrl_handle_sense_interrupt_status (fdctrl_t *fdctrl, int directio |
1515 | 1522 | |
1516 | 1523 | #if 0 |
1517 | 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 | 1526 | #else |
1520 | - /* XXX: int_status handling is broken for read/write | |
1527 | + /* XXX: status0 handling is broken for read/write | |
1521 | 1528 | commands, so we do this hack. It should be suppressed |
1522 | 1529 | ASAP */ |
1523 | 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 | 1532 | #endif |
1526 | 1533 | fdctrl->fifo[1] = cur_drv->track; |
1527 | 1534 | fdctrl_set_fifo(fdctrl, 2, 0); |
1528 | 1535 | fdctrl_reset_irq(fdctrl); |
1529 | - fdctrl->int_status = FD_SR0_RDYCHG; | |
1536 | + fdctrl->status0 = FD_SR0_RDYCHG; | |
1530 | 1537 | } |
1531 | 1538 | |
1532 | 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 | 1542 | |
1536 | 1543 | fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK; |
1537 | 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 | 1545 | fdctrl_reset_fifo(fdctrl); |
1543 | 1546 | if (fdctrl->fifo[2] > cur_drv->max_track) { |
1544 | 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 | 1607 | |
1605 | 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 | 1612 | fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK; |
1610 | 1613 | cur_drv = get_cur_drv(fdctrl); |
1611 | - cur_drv->dir = 0; | |
1612 | 1614 | if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) { |
1613 | 1615 | cur_drv->track = cur_drv->max_track - 1; |
1614 | 1616 | } else { |
1615 | 1617 | cur_drv->track += fdctrl->fifo[2]; |
1616 | 1618 | } |
1617 | 1619 | fdctrl_reset_fifo(fdctrl); |
1620 | + /* Raise Interrupt */ | |
1618 | 1621 | fdctrl_raise_irq(fdctrl, FD_SR0_SEEK); |
1619 | 1622 | } |
1620 | 1623 | |
1621 | 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 | 1628 | fdctrl->cur_drv = fdctrl->fifo[1] & FD_DOR_SELMASK; |
1626 | 1629 | cur_drv = get_cur_drv(fdctrl); |
1627 | - cur_drv->dir = 1; | |
1628 | 1630 | if (fdctrl->fifo[2] > cur_drv->track) { |
1629 | 1631 | cur_drv->track = 0; |
1630 | 1632 | } else { |
... | ... | @@ -1684,7 +1686,6 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) |
1684 | 1686 | fdrive_t *cur_drv; |
1685 | 1687 | int pos; |
1686 | 1688 | |
1687 | - cur_drv = get_cur_drv(fdctrl); | |
1688 | 1689 | /* Reset mode */ |
1689 | 1690 | if (!(fdctrl->dor & FD_DOR_nRESET)) { |
1690 | 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 | 1702 | fdctrl->fifo[fdctrl->data_pos++] = value; |
1702 | 1703 | if (fdctrl->data_pos % FD_SECTOR_LEN == (FD_SECTOR_LEN - 1) || |
1703 | 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 | 1710 | if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) { |
1706 | 1711 | FLOPPY_DPRINTF("error seeking to next sector %d\n", |
1707 | 1712 | fd_sector(cur_drv)); |
... | ... | @@ -1723,8 +1728,8 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) |
1723 | 1728 | } |
1724 | 1729 | |
1725 | 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 | 1733 | /* We now have all parameters |
1729 | 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 | 1798 | for (i = 0; i < MAX_FD; i++) { |
1794 | 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 | 1803 | qemu_register_reset(fdctrl_external_reset, fdctrl); |
1799 | 1804 | for (i = 0; i < MAX_FD; i++) { |
1800 | 1805 | fd_revalidate(&fdctrl->drives[i]); | ... | ... |