Commit f2d81b33007d2ab53d4e90ba16f1326f3e81a12d

Authored by blueswir1
1 parent 7373048c

Floppy: Properly handle Sense Interrupt Status after FDC Reset

Original text below.

Attached is a patch that changes how the emulated floppy controller replies to Sense Interrupt Status commands immediately after a controller reset. The specs state that after a Reset the 82078 goes into polling mode which needs four Sense Interrupt Status commands to be issued afterwards to clear the status of each drive. Currently we always respond to Sense Interrupt Status with a SEEK END instead of POLLING. This causes a problem with the SCO Openserver installer which is expects a POLLING state after reset. This patch returns a POLLING status for four Sense Interrupt Status requests immediately after a controller reset. This approach mirrors the way Bochs handles this situation. With the attached patch applied Openserver gets further when trying to load storage drivers from the floppy disk (blocked by another issue, patch on its way). I have successfully tested the floppy drive on the following OSs after applying this patch: Windows 98, Windows XP SP2, Linux x86 (SysRescCD 1.1.3 and Ubuntu 8.10).

Justin

Changelog:

Properly handle Sense Interrupt Status after FDC Reset

Signed-off-by: Justin Chevrier <theburner1@yahoo.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6416 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 18 additions and 12 deletions
hw/fdc.c
@@ -53,8 +53,9 @@ do { printf(&quot;FLOPPY ERROR: %s: &quot; fmt, __func__ , ##args); } while (0) @@ -53,8 +53,9 @@ do { printf(&quot;FLOPPY ERROR: %s: &quot; fmt, __func__ , ##args); } while (0)
53 #define SET_CUR_DRV(fdctrl, drive) ((fdctrl)->cur_drv = (drive)) 53 #define SET_CUR_DRV(fdctrl, drive) ((fdctrl)->cur_drv = (drive))
54 54
55 /* Will always be a fixed parameter for us */ 55 /* Will always be a fixed parameter for us */
56 -#define FD_SECTOR_LEN 512  
57 -#define FD_SECTOR_SC 2 /* Sector size code */ 56 +#define FD_SECTOR_LEN 512
  57 +#define FD_SECTOR_SC 2 /* Sector size code */
  58 +#define FD_RESET_SENSEI_COUNT 4 /* Number of sense interrupts on RESET */
58 59
59 /* Floppy disk drive emulation */ 60 /* Floppy disk drive emulation */
60 typedef enum fdisk_type_t { 61 typedef enum fdisk_type_t {
@@ -506,6 +507,7 @@ struct fdctrl_t { @@ -506,6 +507,7 @@ struct fdctrl_t {
506 int sun4m; 507 int sun4m;
507 /* Floppy drives */ 508 /* Floppy drives */
508 fdrive_t drives[MAX_FD]; 509 fdrive_t drives[MAX_FD];
  510 + int reset_sensei;
509 }; 511 };
510 512
511 static uint32_t fdctrl_read (void *opaque, uint32_t reg) 513 static uint32_t fdctrl_read (void *opaque, uint32_t reg)
@@ -763,6 +765,7 @@ static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status0) @@ -763,6 +765,7 @@ static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status0)
763 qemu_set_irq(fdctrl->irq, 1); 765 qemu_set_irq(fdctrl->irq, 1);
764 fdctrl->sra |= FD_SRA_INTPEND; 766 fdctrl->sra |= FD_SRA_INTPEND;
765 } 767 }
  768 + fdctrl->reset_sensei = 0;
766 fdctrl->status0 = status0; 769 fdctrl->status0 = status0;
767 FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", fdctrl->status0); 770 FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", fdctrl->status0);
768 } 771 }
@@ -793,6 +796,7 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq) @@ -793,6 +796,7 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq)
793 fdctrl_reset_fifo(fdctrl); 796 fdctrl_reset_fifo(fdctrl);
794 if (do_irq) { 797 if (do_irq) {
795 fdctrl_raise_irq(fdctrl, FD_SR0_RDYCHG); 798 fdctrl_raise_irq(fdctrl, FD_SR0_RDYCHG);
  799 + fdctrl->reset_sensei = FD_RESET_SENSEI_COUNT;
796 } 800 }
797 } 801 }
798 802
@@ -1601,16 +1605,18 @@ static void fdctrl_handle_sense_interrupt_status (fdctrl_t *fdctrl, int directio @@ -1601,16 +1605,18 @@ static void fdctrl_handle_sense_interrupt_status (fdctrl_t *fdctrl, int directio
1601 { 1605 {
1602 fdrive_t *cur_drv = get_cur_drv(fdctrl); 1606 fdrive_t *cur_drv = get_cur_drv(fdctrl);
1603 1607
1604 -#if 0  
1605 - fdctrl->fifo[0] =  
1606 - fdctrl->status0 | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);  
1607 -#else  
1608 - /* XXX: status0 handling is broken for read/write  
1609 - commands, so we do this hack. It should be suppressed  
1610 - ASAP */  
1611 - fdctrl->fifo[0] =  
1612 - FD_SR0_SEEK | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);  
1613 -#endif 1608 + if(fdctrl->reset_sensei > 0) {
  1609 + fdctrl->fifo[0] =
  1610 + FD_SR0_RDYCHG + FD_RESET_SENSEI_COUNT - fdctrl->reset_sensei;
  1611 + fdctrl->reset_sensei--;
  1612 + } else {
  1613 + /* XXX: status0 handling is broken for read/write
  1614 + commands, so we do this hack. It should be suppressed
  1615 + ASAP */
  1616 + fdctrl->fifo[0] =
  1617 + FD_SR0_SEEK | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
  1618 + }
  1619 +
1614 fdctrl->fifo[1] = cur_drv->track; 1620 fdctrl->fifo[1] = cur_drv->track;
1615 fdctrl_set_fifo(fdctrl, 2, 0); 1621 fdctrl_set_fifo(fdctrl, 2, 0);
1616 fdctrl_reset_irq(fdctrl); 1622 fdctrl_reset_irq(fdctrl);