Commit 78ae820cfeb04cb05b25bc024c4736cd80bf0007
1 parent
46d3233b
FDC fix 9/10 (Hervé Poussineau):
- Supports up to 4 floppy drives if MAX_FD is set to 4. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4289 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
75 additions
and
10 deletions
hw/fdc.c
@@ -417,7 +417,11 @@ enum { | @@ -417,7 +417,11 @@ enum { | ||
417 | }; | 417 | }; |
418 | 418 | ||
419 | enum { | 419 | enum { |
420 | +#if MAX_FD == 4 | ||
421 | + FD_DOR_SELMASK = 0x03, | ||
422 | +#else | ||
420 | FD_DOR_SELMASK = 0x01, | 423 | FD_DOR_SELMASK = 0x01, |
424 | +#endif | ||
421 | FD_DOR_nRESET = 0x04, | 425 | FD_DOR_nRESET = 0x04, |
422 | FD_DOR_DMAEN = 0x08, | 426 | FD_DOR_DMAEN = 0x08, |
423 | FD_DOR_MOTEN0 = 0x10, | 427 | FD_DOR_MOTEN0 = 0x10, |
@@ -427,7 +431,11 @@ enum { | @@ -427,7 +431,11 @@ enum { | ||
427 | }; | 431 | }; |
428 | 432 | ||
429 | enum { | 433 | enum { |
434 | +#if MAX_FD == 4 | ||
430 | FD_TDR_BOOTSEL = 0x0c, | 435 | FD_TDR_BOOTSEL = 0x0c, |
436 | +#else | ||
437 | + FD_TDR_BOOTSEL = 0x04, | ||
438 | +#endif | ||
431 | }; | 439 | }; |
432 | 440 | ||
433 | enum { | 441 | enum { |
@@ -494,7 +502,7 @@ struct fdctrl_t { | @@ -494,7 +502,7 @@ struct fdctrl_t { | ||
494 | /* Sun4m quirks? */ | 502 | /* Sun4m quirks? */ |
495 | int sun4m; | 503 | int sun4m; |
496 | /* Floppy drives */ | 504 | /* Floppy drives */ |
497 | - fdrive_t drives[2]; | 505 | + fdrive_t drives[MAX_FD]; |
498 | }; | 506 | }; |
499 | 507 | ||
500 | static uint32_t fdctrl_read (void *opaque, uint32_t reg) | 508 | static uint32_t fdctrl_read (void *opaque, uint32_t reg) |
@@ -602,6 +610,8 @@ static void fd_save (QEMUFile *f, fdrive_t *fd) | @@ -602,6 +610,8 @@ static void fd_save (QEMUFile *f, fdrive_t *fd) | ||
602 | static void fdc_save (QEMUFile *f, void *opaque) | 610 | static void fdc_save (QEMUFile *f, void *opaque) |
603 | { | 611 | { |
604 | fdctrl_t *s = opaque; | 612 | fdctrl_t *s = opaque; |
613 | + uint8_t tmp; | ||
614 | + int i; | ||
605 | 615 | ||
606 | /* Controller state */ | 616 | /* Controller state */ |
607 | qemu_put_8s(f, &s->sra); | 617 | qemu_put_8s(f, &s->sra); |
@@ -627,8 +637,11 @@ static void fdc_save (QEMUFile *f, void *opaque) | @@ -627,8 +637,11 @@ static void fdc_save (QEMUFile *f, void *opaque) | ||
627 | qemu_put_8s(f, &s->config); | 637 | qemu_put_8s(f, &s->config); |
628 | qemu_put_8s(f, &s->lock); | 638 | qemu_put_8s(f, &s->lock); |
629 | qemu_put_8s(f, &s->pwrd); | 639 | qemu_put_8s(f, &s->pwrd); |
630 | - fd_save(f, &s->drives[0]); | ||
631 | - fd_save(f, &s->drives[1]); | 640 | + |
641 | + tmp = MAX_FD; | ||
642 | + qemu_put_8s(f, &tmp); | ||
643 | + for (i = 0; i < MAX_FD; i++) | ||
644 | + fd_save(f, &s->drives[i]); | ||
632 | } | 645 | } |
633 | 646 | ||
634 | static int fd_load (QEMUFile *f, fdrive_t *fd) | 647 | static int fd_load (QEMUFile *f, fdrive_t *fd) |
@@ -643,7 +656,8 @@ static int fd_load (QEMUFile *f, fdrive_t *fd) | @@ -643,7 +656,8 @@ static int fd_load (QEMUFile *f, fdrive_t *fd) | ||
643 | static int fdc_load (QEMUFile *f, void *opaque, int version_id) | 656 | static int fdc_load (QEMUFile *f, void *opaque, int version_id) |
644 | { | 657 | { |
645 | fdctrl_t *s = opaque; | 658 | fdctrl_t *s = opaque; |
646 | - int ret; | 659 | + int i, ret = 0; |
660 | + uint8_t n; | ||
647 | 661 | ||
648 | if (version_id != 2) | 662 | if (version_id != 2) |
649 | return -EINVAL; | 663 | return -EINVAL; |
@@ -672,10 +686,16 @@ static int fdc_load (QEMUFile *f, void *opaque, int version_id) | @@ -672,10 +686,16 @@ static int fdc_load (QEMUFile *f, void *opaque, int version_id) | ||
672 | qemu_get_8s(f, &s->config); | 686 | qemu_get_8s(f, &s->config); |
673 | qemu_get_8s(f, &s->lock); | 687 | qemu_get_8s(f, &s->lock); |
674 | qemu_get_8s(f, &s->pwrd); | 688 | qemu_get_8s(f, &s->pwrd); |
689 | + qemu_get_8s(f, &n); | ||
675 | 690 | ||
676 | - ret = fd_load(f, &s->drives[0]); | ||
677 | - if (ret == 0) | ||
678 | - ret = fd_load(f, &s->drives[1]); | 691 | + if (n > MAX_FD) |
692 | + return -EINVAL; | ||
693 | + | ||
694 | + for (i = 0; i < n; i++) { | ||
695 | + ret = fd_load(f, &s->drives[i]); | ||
696 | + if (ret != 0) | ||
697 | + break; | ||
698 | + } | ||
679 | 699 | ||
680 | return ret; | 700 | return ret; |
681 | } | 701 | } |
@@ -773,9 +793,35 @@ static inline fdrive_t *drv1 (fdctrl_t *fdctrl) | @@ -773,9 +793,35 @@ static inline fdrive_t *drv1 (fdctrl_t *fdctrl) | ||
773 | return &fdctrl->drives[0]; | 793 | return &fdctrl->drives[0]; |
774 | } | 794 | } |
775 | 795 | ||
796 | +#if MAX_FD == 4 | ||
797 | +static inline fdrive_t *drv2 (fdctrl_t *fdctrl) | ||
798 | +{ | ||
799 | + if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (2 << 2)) | ||
800 | + return &fdctrl->drives[2]; | ||
801 | + else | ||
802 | + return &fdctrl->drives[1]; | ||
803 | +} | ||
804 | + | ||
805 | +static inline fdrive_t *drv3 (fdctrl_t *fdctrl) | ||
806 | +{ | ||
807 | + if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (3 << 2)) | ||
808 | + return &fdctrl->drives[3]; | ||
809 | + else | ||
810 | + return &fdctrl->drives[2]; | ||
811 | +} | ||
812 | +#endif | ||
813 | + | ||
776 | static fdrive_t *get_cur_drv (fdctrl_t *fdctrl) | 814 | static fdrive_t *get_cur_drv (fdctrl_t *fdctrl) |
777 | { | 815 | { |
778 | - return fdctrl->cur_drv == 0 ? drv0(fdctrl) : drv1(fdctrl); | 816 | + switch (fdctrl->cur_drv) { |
817 | + case 0: return drv0(fdctrl); | ||
818 | + case 1: return drv1(fdctrl); | ||
819 | +#if MAX_FD == 4 | ||
820 | + case 2: return drv2(fdctrl); | ||
821 | + case 3: return drv3(fdctrl); | ||
822 | +#endif | ||
823 | + default: return NULL; | ||
824 | + } | ||
779 | } | 825 | } |
780 | 826 | ||
781 | /* Status A register : 0x00 (read-only) */ | 827 | /* Status A register : 0x00 (read-only) */ |
@@ -923,8 +969,13 @@ static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl) | @@ -923,8 +969,13 @@ static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl) | ||
923 | { | 969 | { |
924 | uint32_t retval = 0; | 970 | uint32_t retval = 0; |
925 | 971 | ||
926 | - if (fdctrl_media_changed(drv0(fdctrl)) || | ||
927 | - fdctrl_media_changed(drv1(fdctrl))) | 972 | + if (fdctrl_media_changed(drv0(fdctrl)) |
973 | + || fdctrl_media_changed(drv1(fdctrl)) | ||
974 | +#if MAX_FD == 4 | ||
975 | + || fdctrl_media_changed(drv2(fdctrl)) | ||
976 | + || fdctrl_media_changed(drv3(fdctrl)) | ||
977 | +#endif | ||
978 | + ) | ||
928 | retval |= FD_DIR_DSKCHG; | 979 | retval |= FD_DIR_DSKCHG; |
929 | if (retval != 0) | 980 | if (retval != 0) |
930 | FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval); | 981 | FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval); |
@@ -1367,8 +1418,13 @@ static void fdctrl_handle_dumpreg (fdctrl_t *fdctrl, int direction) | @@ -1367,8 +1418,13 @@ static void fdctrl_handle_dumpreg (fdctrl_t *fdctrl, int direction) | ||
1367 | /* Drives position */ | 1418 | /* Drives position */ |
1368 | fdctrl->fifo[0] = drv0(fdctrl)->track; | 1419 | fdctrl->fifo[0] = drv0(fdctrl)->track; |
1369 | fdctrl->fifo[1] = drv1(fdctrl)->track; | 1420 | fdctrl->fifo[1] = drv1(fdctrl)->track; |
1421 | +#if MAX_FD == 4 | ||
1422 | + fdctrl->fifo[2] = drv2(fdctrl)->track; | ||
1423 | + fdctrl->fifo[3] = drv3(fdctrl)->track; | ||
1424 | +#else | ||
1370 | fdctrl->fifo[2] = 0; | 1425 | fdctrl->fifo[2] = 0; |
1371 | fdctrl->fifo[3] = 0; | 1426 | fdctrl->fifo[3] = 0; |
1427 | +#endif | ||
1372 | /* timers */ | 1428 | /* timers */ |
1373 | fdctrl->fifo[4] = fdctrl->timer0; | 1429 | fdctrl->fifo[4] = fdctrl->timer0; |
1374 | fdctrl->fifo[5] = (fdctrl->timer1 << 1) | (fdctrl->dor & FD_DOR_DMAEN ? 1 : 0); | 1430 | fdctrl->fifo[5] = (fdctrl->timer1 << 1) | (fdctrl->dor & FD_DOR_DMAEN ? 1 : 0); |
@@ -1400,6 +1456,10 @@ static void fdctrl_handle_restore (fdctrl_t *fdctrl, int direction) | @@ -1400,6 +1456,10 @@ static void fdctrl_handle_restore (fdctrl_t *fdctrl, int direction) | ||
1400 | /* Drives position */ | 1456 | /* Drives position */ |
1401 | drv0(fdctrl)->track = fdctrl->fifo[3]; | 1457 | drv0(fdctrl)->track = fdctrl->fifo[3]; |
1402 | drv1(fdctrl)->track = fdctrl->fifo[4]; | 1458 | drv1(fdctrl)->track = fdctrl->fifo[4]; |
1459 | +#if MAX_FD == 4 | ||
1460 | + drv2(fdctrl)->track = fdctrl->fifo[5]; | ||
1461 | + drv3(fdctrl)->track = fdctrl->fifo[6]; | ||
1462 | +#endif | ||
1403 | /* timers */ | 1463 | /* timers */ |
1404 | fdctrl->timer0 = fdctrl->fifo[7]; | 1464 | fdctrl->timer0 = fdctrl->fifo[7]; |
1405 | fdctrl->timer1 = fdctrl->fifo[8]; | 1465 | fdctrl->timer1 = fdctrl->fifo[8]; |
@@ -1421,8 +1481,13 @@ static void fdctrl_handle_save (fdctrl_t *fdctrl, int direction) | @@ -1421,8 +1481,13 @@ static void fdctrl_handle_save (fdctrl_t *fdctrl, int direction) | ||
1421 | /* Drives position */ | 1481 | /* Drives position */ |
1422 | fdctrl->fifo[2] = drv0(fdctrl)->track; | 1482 | fdctrl->fifo[2] = drv0(fdctrl)->track; |
1423 | fdctrl->fifo[3] = drv1(fdctrl)->track; | 1483 | fdctrl->fifo[3] = drv1(fdctrl)->track; |
1484 | +#if MAX_FD == 4 | ||
1485 | + fdctrl->fifo[4] = drv2(fdctrl)->track; | ||
1486 | + fdctrl->fifo[5] = drv3(fdctrl)->track; | ||
1487 | +#else | ||
1424 | fdctrl->fifo[4] = 0; | 1488 | fdctrl->fifo[4] = 0; |
1425 | fdctrl->fifo[5] = 0; | 1489 | fdctrl->fifo[5] = 0; |
1490 | +#endif | ||
1426 | /* timers */ | 1491 | /* timers */ |
1427 | fdctrl->fifo[6] = fdctrl->timer0; | 1492 | fdctrl->fifo[6] = fdctrl->timer0; |
1428 | fdctrl->fifo[7] = fdctrl->timer1; | 1493 | fdctrl->fifo[7] = fdctrl->timer1; |