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; | ... | ... |