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