[solved] FDC FIFO error
Posted: Tue Aug 09, 2016 6:12 am
Hi,
I'm trying to read form a floppy disk. The code works on QEMU but fails with st1 = 0x10, which is apparently a FIFO error.(Yes I know I'm not waiting for the motor to spin up but for now the seek gives an adequate delay.)Here's the code that I'm using to initialise the FDC - I'm guessing that the FIFO is not configured correctly?Thanks,
onlyonemac
I'm trying to read form a floppy disk. The code works on QEMU but fails with st1 = 0x10, which is apparently a FIFO error.
Code: Select all
static void floppy_read_sectors(uint8_t track, uint8_t head, uint8_t start_sector, uint8_t sector_count, uint32_t buffer)
{
fdc_motor_on();
fdc_do_command(FDC_CMD_SEEK, (uint8_t[]){ 0, track }, NULL);
fdc_do_command(FDC_CMD_SENSE, NULL, fdc_results);
dma_setup(buffer, ((uint16_t) sector_count) * 512, FALSE);
fdc_do_command(FDC_CMD_READ, (uint8_t[]){ head << 2, track, head, start_sector + 1, 2, sector_count, 0x1B, 0xFF }, fdc_results);
fdc_motor_off();
}
Code: Select all
static void fdc_motor_on()
{
outb(FDC_REGISTER_DOR, 0x1C);
}
static void fdc_motor_off()
{
outb(FDC_REGISTER_DOR, 0x0C);
}
Code: Select all
static void fdc_do_command(fdc_command command, uint8_t* parameters, uint8_t* results)
{
uint32_t current_parameter;
uint32_t parameter_count;
uint32_t current_result;
uint32_t result_count;
uint32_t irq_expected;
while ((inb(FDC_REGISTER_MSR) & 0xC0) != 0x80)
{
// wait
}
switch (command)
{
case FDC_CMD_READ:
case FDC_CMD_WRITE:
parameter_count = 8;
result_count = 7;
irq_expected = TRUE;
break;
case FDC_CMD_SEEK:
parameter_count = 2;
result_count = 0;
irq_expected = TRUE;
break;
case FDC_CMD_RECALIBRATE:
parameter_count = 1;
result_count = 0;
irq_expected = TRUE;
break;
case FDC_CMD_SENSE:
parameter_count = 0;
result_count = 2;
irq_expected = FALSE;
break;
case FDC_CMD_CONFIGURE:
parameter_count = 3;
result_count = 0;
irq_expected = FALSE;
break;
case FDC_CMD_SPECIFY:
parameter_count = 2;
result_count = 0;
irq_expected = FALSE;
break;
case FDC_CMD_LOCK:
case FDC_CMD_UNLOCK:
parameter_count = 0;
result_count = 1;
irq_expected = FALSE;
break;
case FDC_CMD_VERSION:
parameter_count = 0;
result_count = 1;
irq_expected = FALSE;
break;
}
if (irq_expected == TRUE)
{
instance->irq = FALSE;
}
outb(FDC_REGISTER_FIFO, command);
current_parameter = 0;
while (current_parameter < parameter_count)
{
while ((inb(FDC_REGISTER_MSR) & 0xC0) != 0x80)
{
// wait
}
outb(FDC_REGISTER_FIFO, parameters[current_parameter]);
current_parameter++;
}
if (irq_expected == TRUE)
{
fdc_wait_for_irq();
}
current_result = 0;
while (current_result < result_count)
{
while ((inb(FDC_REGISTER_MSR) & 0xC0) != 0xC0)
{
// wait
}
results[current_result] = inb(FDC_REGISTER_FIFO);
current_result++;
}
}
Code: Select all
static void dma_setup(uint32_t address, uint16_t length, uint8_t direction) // direction = FALSE to read from disk; direction = TRUE to write to disk
{
outb(0x0B, direction == FALSE ? 0x06 : 0x0A);
outb(0x0C, 0x00);
outb(0x04, address & 0x000000FF);
outb(0x04, (address & 0x0000FF00) >> 8);
outb(0x0C, 0x00);
outb(0x05, (length - 1) & 0x00FF);
outb(0x05, ((length - 1) & 0xFF00) >> 8);
outb(0x81, (address & 0x00FF0000) >> 16);
}
Code: Select all
fdc_motor_off();
fdc_do_command(FDC_CMD_CONFIGURE, (uint8_t[]){ 0, 0x17, 0 }, NULL);
fdc_do_command(FDC_CMD_LOCK, NULL, fdc_results);
fdc_reset();
fdc_motor_on();
fdc_do_command(FDC_CMD_RECALIBRATE, (uint8_t[]){ 0 }, NULL);
fdc_do_command(FDC_CMD_SENSE, NULL, fdc_results);
fdc_motor_off();
Code: Select all
static void fdc_reset()
{
instance->irq = FALSE;
outb(FDC_REGISTER_DSR, 0x80);
fdc_wait_for_irq();
fdc_do_command(FDC_CMD_SPECIFY, (uint8_t[]){ (8 << 4) | 5, 15 << 1 }, NULL);
}
onlyonemac