Commit 8c6a4d7742b12994791f33da17283d90f1278926

Authored by blueswir1
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));