Commit 8c6a4d7742b12994791f33da17283d90f1278926
1 parent
746d6de7
FDC fix 3/10 (Hervé Poussineau):
- Fixes status A and status B registers. It removes one Sun4m mutation. Also removes the internal FD_CTRL_INTR flag. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4283 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
75 additions
and
16 deletions
hw/fdc.c
| @@ -323,6 +323,7 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, | @@ -323,6 +323,7 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, | ||
| 323 | int dma_pos, int dma_len); | 323 | int dma_pos, int dma_len); |
| 324 | static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status); | 324 | static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status); |
| 325 | 325 | ||
| 326 | +static uint32_t fdctrl_read_statusA (fdctrl_t *fdctrl); | ||
| 326 | static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl); | 327 | static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl); |
| 327 | static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl); | 328 | static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl); |
| 328 | static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value); | 329 | static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value); |
| @@ -339,7 +340,6 @@ enum { | @@ -339,7 +340,6 @@ enum { | ||
| 339 | FD_CTRL_RESET = 0x02, | 340 | FD_CTRL_RESET = 0x02, |
| 340 | FD_CTRL_SLEEP = 0x04, /* XXX: suppress that */ | 341 | FD_CTRL_SLEEP = 0x04, /* XXX: suppress that */ |
| 341 | FD_CTRL_BUSY = 0x08, /* dma transfer in progress */ | 342 | FD_CTRL_BUSY = 0x08, /* dma transfer in progress */ |
| 342 | - FD_CTRL_INTR = 0x10, | ||
| 343 | }; | 343 | }; |
| 344 | 344 | ||
| 345 | enum { | 345 | enum { |
| @@ -361,8 +361,8 @@ enum { | @@ -361,8 +361,8 @@ enum { | ||
| 361 | }; | 361 | }; |
| 362 | 362 | ||
| 363 | enum { | 363 | enum { |
| 364 | - FD_REG_0 = 0x00, | ||
| 365 | - FD_REG_STATUSB = 0x01, | 364 | + FD_REG_SRA = 0x00, |
| 365 | + FD_REG_SRB = 0x01, | ||
| 366 | FD_REG_DOR = 0x02, | 366 | FD_REG_DOR = 0x02, |
| 367 | FD_REG_TDR = 0x03, | 367 | FD_REG_TDR = 0x03, |
| 368 | FD_REG_MSR = 0x04, | 368 | FD_REG_MSR = 0x04, |
| @@ -421,6 +421,26 @@ enum { | @@ -421,6 +421,26 @@ enum { | ||
| 421 | }; | 421 | }; |
| 422 | 422 | ||
| 423 | enum { | 423 | enum { |
| 424 | + FD_SRA_DIR = 0x01, | ||
| 425 | + FD_SRA_nWP = 0x02, | ||
| 426 | + FD_SRA_nINDX = 0x04, | ||
| 427 | + FD_SRA_HDSEL = 0x08, | ||
| 428 | + FD_SRA_nTRK0 = 0x10, | ||
| 429 | + FD_SRA_STEP = 0x20, | ||
| 430 | + FD_SRA_nDRV2 = 0x40, | ||
| 431 | + FD_SRA_INTPEND = 0x80, | ||
| 432 | +}; | ||
| 433 | + | ||
| 434 | +enum { | ||
| 435 | + FD_SRB_MTR0 = 0x01, | ||
| 436 | + FD_SRB_MTR1 = 0x02, | ||
| 437 | + FD_SRB_WGATE = 0x04, | ||
| 438 | + FD_SRB_RDATA = 0x08, | ||
| 439 | + FD_SRB_WDATA = 0x10, | ||
| 440 | + FD_SRB_DR0 = 0x20, | ||
| 441 | +}; | ||
| 442 | + | ||
| 443 | +enum { | ||
| 424 | FD_DOR_SELMASK = 0x01, | 444 | FD_DOR_SELMASK = 0x01, |
| 425 | FD_DOR_nRESET = 0x04, | 445 | FD_DOR_nRESET = 0x04, |
| 426 | FD_DOR_DMAEN = 0x08, | 446 | FD_DOR_DMAEN = 0x08, |
| @@ -472,6 +492,8 @@ struct fdctrl_t { | @@ -472,6 +492,8 @@ struct fdctrl_t { | ||
| 472 | target_phys_addr_t io_base; | 492 | target_phys_addr_t io_base; |
| 473 | /* Controller state */ | 493 | /* Controller state */ |
| 474 | QEMUTimer *result_timer; | 494 | QEMUTimer *result_timer; |
| 495 | + uint8_t sra; | ||
| 496 | + uint8_t srb; | ||
| 475 | uint8_t state; | 497 | uint8_t state; |
| 476 | uint8_t dma_en; | 498 | uint8_t dma_en; |
| 477 | uint8_t cur_drv; | 499 | uint8_t cur_drv; |
| @@ -506,15 +528,10 @@ static uint32_t fdctrl_read (void *opaque, uint32_t reg) | @@ -506,15 +528,10 @@ static uint32_t fdctrl_read (void *opaque, uint32_t reg) | ||
| 506 | uint32_t retval; | 528 | uint32_t retval; |
| 507 | 529 | ||
| 508 | switch (reg & 0x07) { | 530 | switch (reg & 0x07) { |
| 509 | - case FD_REG_0: | ||
| 510 | - if (fdctrl->sun4m) { | ||
| 511 | - // Identify to Linux as S82078B | ||
| 512 | - retval = fdctrl_read_statusB(fdctrl); | ||
| 513 | - } else { | ||
| 514 | - retval = (uint32_t)(-1); | ||
| 515 | - } | 531 | + case FD_REG_SRA: |
| 532 | + retval = fdctrl_read_statusA(fdctrl); | ||
| 516 | break; | 533 | break; |
| 517 | - case FD_REG_STATUSB: | 534 | + case FD_REG_SRB: |
| 518 | retval = fdctrl_read_statusB(fdctrl); | 535 | retval = fdctrl_read_statusB(fdctrl); |
| 519 | break; | 536 | break; |
| 520 | case FD_REG_DOR: | 537 | case FD_REG_DOR: |
| @@ -617,6 +634,9 @@ static void fdc_save (QEMUFile *f, void *opaque) | @@ -617,6 +634,9 @@ static void fdc_save (QEMUFile *f, void *opaque) | ||
| 617 | { | 634 | { |
| 618 | fdctrl_t *s = opaque; | 635 | fdctrl_t *s = opaque; |
| 619 | 636 | ||
| 637 | + /* Controller state */ | ||
| 638 | + qemu_put_8s(f, &s->sra); | ||
| 639 | + qemu_put_8s(f, &s->srb); | ||
| 620 | qemu_put_8s(f, &s->state); | 640 | qemu_put_8s(f, &s->state); |
| 621 | qemu_put_8s(f, &s->dma_en); | 641 | qemu_put_8s(f, &s->dma_en); |
| 622 | qemu_put_8s(f, &s->cur_drv); | 642 | qemu_put_8s(f, &s->cur_drv); |
| @@ -661,6 +681,9 @@ static int fdc_load (QEMUFile *f, void *opaque, int version_id) | @@ -661,6 +681,9 @@ static int fdc_load (QEMUFile *f, void *opaque, int version_id) | ||
| 661 | if (version_id != 1) | 681 | if (version_id != 1) |
| 662 | return -EINVAL; | 682 | return -EINVAL; |
| 663 | 683 | ||
| 684 | + /* Controller state */ | ||
| 685 | + qemu_get_8s(f, &s->sra); | ||
| 686 | + qemu_get_8s(f, &s->srb); | ||
| 664 | qemu_get_8s(f, &s->state); | 687 | qemu_get_8s(f, &s->state); |
| 665 | qemu_get_8s(f, &s->dma_en); | 688 | qemu_get_8s(f, &s->dma_en); |
| 666 | qemu_get_8s(f, &s->cur_drv); | 689 | qemu_get_8s(f, &s->cur_drv); |
| @@ -712,9 +735,11 @@ int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num) | @@ -712,9 +735,11 @@ int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num) | ||
| 712 | /* Change IRQ state */ | 735 | /* Change IRQ state */ |
| 713 | static void fdctrl_reset_irq (fdctrl_t *fdctrl) | 736 | static void fdctrl_reset_irq (fdctrl_t *fdctrl) |
| 714 | { | 737 | { |
| 738 | + if (!(fdctrl->sra & FD_SRA_INTPEND)) | ||
| 739 | + return; | ||
| 715 | FLOPPY_DPRINTF("Reset interrupt\n"); | 740 | FLOPPY_DPRINTF("Reset interrupt\n"); |
| 716 | qemu_set_irq(fdctrl->irq, 0); | 741 | qemu_set_irq(fdctrl->irq, 0); |
| 717 | - fdctrl->state &= ~FD_CTRL_INTR; | 742 | + fdctrl->sra &= ~FD_SRA_INTPEND; |
| 718 | } | 743 | } |
| 719 | 744 | ||
| 720 | static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status) | 745 | static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status) |
| @@ -725,9 +750,9 @@ static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status) | @@ -725,9 +750,9 @@ static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status) | ||
| 725 | fdctrl->int_status = status; | 750 | fdctrl->int_status = status; |
| 726 | return; | 751 | return; |
| 727 | } | 752 | } |
| 728 | - if (~(fdctrl->state & FD_CTRL_INTR)) { | 753 | + if (!(fdctrl->sra & FD_SRA_INTPEND)) { |
| 729 | qemu_set_irq(fdctrl->irq, 1); | 754 | qemu_set_irq(fdctrl->irq, 1); |
| 730 | - fdctrl->state |= FD_CTRL_INTR; | 755 | + fdctrl->sra |= FD_SRA_INTPEND; |
| 731 | } | 756 | } |
| 732 | FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", status); | 757 | FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", status); |
| 733 | fdctrl->int_status = status; | 758 | fdctrl->int_status = status; |
| @@ -741,6 +766,10 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq) | @@ -741,6 +766,10 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq) | ||
| 741 | FLOPPY_DPRINTF("reset controller\n"); | 766 | FLOPPY_DPRINTF("reset controller\n"); |
| 742 | fdctrl_reset_irq(fdctrl); | 767 | fdctrl_reset_irq(fdctrl); |
| 743 | /* Initialise controller */ | 768 | /* Initialise controller */ |
| 769 | + fdctrl->sra = 0; | ||
| 770 | + fdctrl->srb = 0xc0; | ||
| 771 | + if (!fdctrl->drives[1].bs) | ||
| 772 | + fdctrl->sra |= FD_SRA_nDRV2; | ||
| 744 | fdctrl->cur_drv = 0; | 773 | fdctrl->cur_drv = 0; |
| 745 | /* FIFO state */ | 774 | /* FIFO state */ |
| 746 | fdctrl->data_pos = 0; | 775 | fdctrl->data_pos = 0; |
| @@ -769,11 +798,24 @@ static fdrive_t *get_cur_drv (fdctrl_t *fdctrl) | @@ -769,11 +798,24 @@ static fdrive_t *get_cur_drv (fdctrl_t *fdctrl) | ||
| 769 | return fdctrl->cur_drv == 0 ? drv0(fdctrl) : drv1(fdctrl); | 798 | return fdctrl->cur_drv == 0 ? drv0(fdctrl) : drv1(fdctrl); |
| 770 | } | 799 | } |
| 771 | 800 | ||
| 801 | +/* Status A register : 0x00 (read-only) */ | ||
| 802 | +static uint32_t fdctrl_read_statusA (fdctrl_t *fdctrl) | ||
| 803 | +{ | ||
| 804 | + uint32_t retval = fdctrl->sra; | ||
| 805 | + | ||
| 806 | + FLOPPY_DPRINTF("status register A: 0x%02x\n", retval); | ||
| 807 | + | ||
| 808 | + return retval; | ||
| 809 | +} | ||
| 810 | + | ||
| 772 | /* Status B register : 0x01 (read-only) */ | 811 | /* Status B register : 0x01 (read-only) */ |
| 773 | static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl) | 812 | static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl) |
| 774 | { | 813 | { |
| 775 | - FLOPPY_DPRINTF("status register: 0x00\n"); | ||
| 776 | - return 0; | 814 | + uint32_t retval = fdctrl->srb; |
| 815 | + | ||
| 816 | + FLOPPY_DPRINTF("status register B: 0x%02x\n", retval); | ||
| 817 | + | ||
| 818 | + return retval; | ||
| 777 | } | 819 | } |
| 778 | 820 | ||
| 779 | /* Digital output register : 0x02 */ | 821 | /* Digital output register : 0x02 */ |
| @@ -809,6 +851,23 @@ static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value) | @@ -809,6 +851,23 @@ static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value) | ||
| 809 | } | 851 | } |
| 810 | } | 852 | } |
| 811 | FLOPPY_DPRINTF("digital output register set to 0x%02x\n", value); | 853 | FLOPPY_DPRINTF("digital output register set to 0x%02x\n", value); |
| 854 | + | ||
| 855 | + /* Motors */ | ||
| 856 | + if (value & FD_DOR_MOTEN0) | ||
| 857 | + fdctrl->srb |= FD_SRB_MTR0; | ||
| 858 | + else | ||
| 859 | + fdctrl->srb &= ~FD_SRB_MTR0; | ||
| 860 | + if (value & FD_DOR_MOTEN1) | ||
| 861 | + fdctrl->srb |= FD_SRB_MTR1; | ||
| 862 | + else | ||
| 863 | + fdctrl->srb &= ~FD_SRB_MTR1; | ||
| 864 | + | ||
| 865 | + /* Drive */ | ||
| 866 | + if (value & 1) | ||
| 867 | + fdctrl->srb |= FD_SRB_DR0; | ||
| 868 | + else | ||
| 869 | + fdctrl->srb &= ~FD_SRB_DR0; | ||
| 870 | + | ||
| 812 | /* Drive motors state indicators */ | 871 | /* Drive motors state indicators */ |
| 813 | if (value & FD_DOR_MOTEN1) | 872 | if (value & FD_DOR_MOTEN1) |
| 814 | fd_start(drv1(fdctrl)); | 873 | fd_start(drv1(fdctrl)); |