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 | 417 | }; |
418 | 418 | |
419 | 419 | enum { |
420 | +#if MAX_FD == 4 | |
421 | + FD_DOR_SELMASK = 0x03, | |
422 | +#else | |
420 | 423 | FD_DOR_SELMASK = 0x01, |
424 | +#endif | |
421 | 425 | FD_DOR_nRESET = 0x04, |
422 | 426 | FD_DOR_DMAEN = 0x08, |
423 | 427 | FD_DOR_MOTEN0 = 0x10, |
... | ... | @@ -427,7 +431,11 @@ enum { |
427 | 431 | }; |
428 | 432 | |
429 | 433 | enum { |
434 | +#if MAX_FD == 4 | |
430 | 435 | FD_TDR_BOOTSEL = 0x0c, |
436 | +#else | |
437 | + FD_TDR_BOOTSEL = 0x04, | |
438 | +#endif | |
431 | 439 | }; |
432 | 440 | |
433 | 441 | enum { |
... | ... | @@ -494,7 +502,7 @@ struct fdctrl_t { |
494 | 502 | /* Sun4m quirks? */ |
495 | 503 | int sun4m; |
496 | 504 | /* Floppy drives */ |
497 | - fdrive_t drives[2]; | |
505 | + fdrive_t drives[MAX_FD]; | |
498 | 506 | }; |
499 | 507 | |
500 | 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 | 610 | static void fdc_save (QEMUFile *f, void *opaque) |
603 | 611 | { |
604 | 612 | fdctrl_t *s = opaque; |
613 | + uint8_t tmp; | |
614 | + int i; | |
605 | 615 | |
606 | 616 | /* Controller state */ |
607 | 617 | qemu_put_8s(f, &s->sra); |
... | ... | @@ -627,8 +637,11 @@ static void fdc_save (QEMUFile *f, void *opaque) |
627 | 637 | qemu_put_8s(f, &s->config); |
628 | 638 | qemu_put_8s(f, &s->lock); |
629 | 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 | 647 | static int fd_load (QEMUFile *f, fdrive_t *fd) |
... | ... | @@ -643,7 +656,8 @@ static int fd_load (QEMUFile *f, fdrive_t *fd) |
643 | 656 | static int fdc_load (QEMUFile *f, void *opaque, int version_id) |
644 | 657 | { |
645 | 658 | fdctrl_t *s = opaque; |
646 | - int ret; | |
659 | + int i, ret = 0; | |
660 | + uint8_t n; | |
647 | 661 | |
648 | 662 | if (version_id != 2) |
649 | 663 | return -EINVAL; |
... | ... | @@ -672,10 +686,16 @@ static int fdc_load (QEMUFile *f, void *opaque, int version_id) |
672 | 686 | qemu_get_8s(f, &s->config); |
673 | 687 | qemu_get_8s(f, &s->lock); |
674 | 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 | 700 | return ret; |
681 | 701 | } |
... | ... | @@ -773,9 +793,35 @@ static inline fdrive_t *drv1 (fdctrl_t *fdctrl) |
773 | 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 | 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 | 827 | /* Status A register : 0x00 (read-only) */ |
... | ... | @@ -923,8 +969,13 @@ static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl) |
923 | 969 | { |
924 | 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 | 979 | retval |= FD_DIR_DSKCHG; |
929 | 980 | if (retval != 0) |
930 | 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 | 1418 | /* Drives position */ |
1368 | 1419 | fdctrl->fifo[0] = drv0(fdctrl)->track; |
1369 | 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 | 1425 | fdctrl->fifo[2] = 0; |
1371 | 1426 | fdctrl->fifo[3] = 0; |
1427 | +#endif | |
1372 | 1428 | /* timers */ |
1373 | 1429 | fdctrl->fifo[4] = fdctrl->timer0; |
1374 | 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 | 1456 | /* Drives position */ |
1401 | 1457 | drv0(fdctrl)->track = fdctrl->fifo[3]; |
1402 | 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 | 1463 | /* timers */ |
1404 | 1464 | fdctrl->timer0 = fdctrl->fifo[7]; |
1405 | 1465 | fdctrl->timer1 = fdctrl->fifo[8]; |
... | ... | @@ -1421,8 +1481,13 @@ static void fdctrl_handle_save (fdctrl_t *fdctrl, int direction) |
1421 | 1481 | /* Drives position */ |
1422 | 1482 | fdctrl->fifo[2] = drv0(fdctrl)->track; |
1423 | 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 | 1488 | fdctrl->fifo[4] = 0; |
1425 | 1489 | fdctrl->fifo[5] = 0; |
1490 | +#endif | |
1426 | 1491 | /* timers */ |
1427 | 1492 | fdctrl->fifo[6] = fdctrl->timer0; |
1428 | 1493 | fdctrl->fifo[7] = fdctrl->timer1; | ... | ... |