The floppy controller spec describes three different controller phases, which are currently not explicitly modelled in our emulation. Instead, each phase is represented by a combination of flags in registers.
This patch makes explicit in which phase the controller currently is. Signed-off-by: Kevin Wolf <kw...@redhat.com> --- hw/block/fdc.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/hw/block/fdc.c b/hw/block/fdc.c index 8c41434..4d4868e 100644 --- a/hw/block/fdc.c +++ b/hw/block/fdc.c @@ -495,6 +495,30 @@ enum { FD_DIR_DSKCHG = 0x80, }; +/* + * See chapter 5.0 "Controller phases" of the spec: + * + * Command phase: + * The host writes a command and its parameters into the FIFO. The command + * phase is completed when all parameters for the command have been supplied, + * and execution phase is entered. + * + * Execution phase: + * Data transfers, either DMA or non-DMA. For non-DMA transfers, the FIFO + * contains the payload now, otherwise it's unused. When all bytes of the + * required data have been transferred, the state is switched to either result + * phase (if the command produces status bytes) or directly back into the + * command phase for the next command. + * + * Result phase: + * The host reads out the FIFO, which contains one or more result bytes now. + */ +typedef enum FDCtrlPhase { + FD_PHASE_COMMAND, + FD_PHASE_EXECUTION, + FD_PHASE_RESULT, +} FDCtrlPhase; + #define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI) #define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT) @@ -504,6 +528,7 @@ struct FDCtrl { /* Controller state */ QEMUTimer *result_timer; int dma_chann; + FDCtrlPhase phase; /* Controller's identification */ uint8_t version; /* HW */ @@ -1137,6 +1162,7 @@ static uint32_t fdctrl_read_dir(FDCtrl *fdctrl) /* Clear the FIFO and update the state for receiving the next command */ static void fdctrl_to_command_phase(FDCtrl *fdctrl) { + fdctrl->phase = FD_PHASE_COMMAND; fdctrl->data_dir = FD_DIR_WRITE; fdctrl->data_pos = 0; fdctrl->msr &= ~(FD_MSR_CMDBUSY | FD_MSR_DIO); @@ -1146,6 +1172,7 @@ static void fdctrl_to_command_phase(FDCtrl *fdctrl) * @fifo_len is the number of result bytes to be read out. */ static void fdctrl_to_result_phase(FDCtrl *fdctrl, int fifo_len) { + fdctrl->phase = FD_PHASE_RESULT; fdctrl->data_dir = FD_DIR_READ; fdctrl->data_len = fifo_len; fdctrl->data_pos = 0; @@ -1912,6 +1939,9 @@ static void fdctrl_handle_relative_seek_out(FDCtrl *fdctrl, int direction) fdctrl_raise_irq(fdctrl); } +/* + * Handlers for the execution phase of each command + */ static const struct { uint8_t value; uint8_t mask; @@ -2015,6 +2045,7 @@ static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value) /* We now have all parameters * and will be able to treat the command */ + fdctrl->phase = FD_PHASE_EXECUTION; if (fdctrl->data_state & FD_STATE_FORMAT) { fdctrl_format_sector(fdctrl); return; -- 1.8.3.1