5.2.20
04/06/20
Last Modified 05/21/07 by Walter Tasin
QEmu/OS9Patch Reload Page

Patches for QEmu (2007/05/21)

First at all,
QEmu and OS9/x86 work together, if you have already an harddisc-image with a working OS9/x86 installation and you disable the floppy support and you don't use the OS9/x86 boot menu to have the possibility to select the boot device.

Here are my patches (used against the snapshot version from 2007/05/21):

Compiled for Windows with MinGW and tested with OS9/x86, Win98 ERD, some old SuSE Linux boot floppies.





Floppy disc doesn't work in the bootloader

Symtoms: booting from floppy doesn't work. The guest hangs.
Problem: The OS9 floppy boot driver awaits the DMA status bit TC for the channel properly set.
Patches: vl.diff, dma.diff, fdc.diff
<geshi type="diff">--- vl.h Wed May 9 20:25:36 2007

vl.h Thu May 17 09:04:44 2007

@@ -1011,6 +1011,7 @@
int DMA_write_memory (int nchan, void *buf, int pos, int size);
void DMA_hold_DREQ (int nchan);
void DMA_release_DREQ (int nchan);

void DMA_set_TC (int nchan);

void DMA_schedule(int nchan);
void DMA_run (void);
void DMA_init (int high_page_enable);
--- hw/dma.c Mon Nov 21 23:29:56 2005

hw/dma.c Wed May 16 13:02:30 2007

@@ -311,6 +311,16 @@
dma_controllers[ncont].status |= 1 << (ichan + 4);
}

void DMA_set_TC (int nchan)

{

int ncont, ichan;

ncont = nchan > 3;

ichan = nchan & 3;

linfo ("tc set cont=%d chan=%d\n", ncont, ichan);

dma_controllers[ncont].status |= 1 << ichan;

}

void DMA_release_DREQ (int nchan)
{
int ncont, ichan;
--- hw/fdc.c Sat Apr 14 13:01:32 2007

hw/fdc.c Wed May 16 17:14:54 2007

@@ -917,7 +920,10 @@
fdctrl->fifo[6] = FD_SECTOR_SC;
fdctrl->data_dir = FD_DIR_READ;
if (fdctrl->state & FD_CTRL_BUSY) {
- DMA_release_DREQ(fdctrl->dma_chann);

if (fdctrl->dma_en) {

DMA_release_DREQ(fdctrl->dma_chann);

DMA_set_TC(fdctrl->dma_chann);

}

fdctrl->state &= ~FD_CTRL_BUSY;
}
fdctrl_set_fifo(fdctrl, 7, 1);
</geshi>





Floppy disc doesn't work (using OS9/x86)

Symtoms: calling a floppy command like a simply dir /d0 doesn't work. The guest hangs.
Problem: The OS9 driver uses the RESET / SENSE INTERRUPT STATUS sequence to continue operation.
(see also Intel 82078 64 PIN CHMOS SINGLE-CHIP FLOPPY DISK CONTROLLER data sheet - chapter 9.2. Initialization)
This should be done for every possible drive and at the end (the fifth call) a SENSE INTERRUPT STATUS call has to return status 0x8x.

The next call should be a SPECIFY to set the floppy to an operational state.
Patch: fdc1.diff
<geshi type="diff">--- hw/fdc.c Mon May 21 10:38:54 2007

hw/fdc.c Mon May 21 10:39:20 2007

@@ -377,6 +377,7 @@
uint8_t dma_en;
uint8_t cur_drv;
uint8_t bootsel;

uint8_t first_sense;

/* Command FIFO */
uint8_t fifo[FD_SECTOR_LEN];
uint32_t data_pos;
@@ -597,6 +598,7 @@
fdctrl->irq = irq;
fdctrl->dma_chann = dma_chann;
fdctrl->io_base = io_base;

fdctrl->first_sense=0;

fdctrl->config = 0x60; /* Implicit seek, polling & FIFO enabled */
if (fdctrl->dma_chann != -1) {
fdctrl->dma_en = 1;
@@ -655,7 +657,7 @@
return;
}
#endif
- if (~(fdctrl->state & FD_CTRL_INTR)) {

if (!(fdctrl->state & FD_CTRL_INTR)) {

qemu_set_irq(fdctrl->irq, 1);
fdctrl->state |= FD_CTRL_INTR;
}
@@ -672,6 +674,7 @@
fdctrl_reset_irq(fdctrl);
/* Initialise controller */
fdctrl->cur_drv = 0;

fdctrl->first_sense = 4;

/* FIFO state */
fdctrl->data_pos = 0;
fdctrl->data_len = 0;
@@ -1384,6 +1387,7 @@
FLOPPY_DPRINTF("SPECIFY command\n");
/* 1 parameter cmd */
fdctrl->data_len = 3;

fdctrl->first_sense=0;

goto enqueue;
case 0x04:
/* SENSE_DRIVE_STATUS */
@@ -1401,21 +1405,29 @@
/* SENSE_INTERRUPT_STATUS */
FLOPPY_DPRINTF("SENSE_INTERRUPT_STATUS command (%02x)\n",
fdctrl->int_status);

uint8_t act_drv = fdctrl->cur_drv;

/* No parameters cmd: returns status if no interrupt */

if (fdctrl->first_sense > 0)

act_drv=4-fdctrl->first_sense--;

#if 0
fdctrl->fifo[0] =
- fdctrl->int_status | (cur_drv->head << 2) | fdctrl->cur_drv;

(fdctrl->state & FD_CTRL_INTR) ?

(fdctrl->int_status | (cur_drv->head << 2) | act_drv) : 0x80;

#else
/* XXX: int_status handling is broken for read/write
commands, so we do this hack. It should be suppressed
ASAP */
fdctrl->fifo[0] =
- 0x20 | (cur_drv->head << 2) | fdctrl->cur_drv;

(fdctrl->state & FD_CTRL_INTR) ?

(0x20 | (cur_drv->head << 2) | act_drv) : 0x80 ;

#endif

fdctrl->fifo[1] = cur_drv->track;
- fdctrl_set_fifo(fdctrl, 2, 0);
- fdctrl_reset_irq(fdctrl);
- fdctrl->int_status = 0xC0;

fdctrl_set_fifo(fdctrl, (fdctrl->fifo[0] != 0x80) ? 2 : 1, 0);

fdctrl_reset_irq(fdctrl);

fdctrl->int_status = 0xC0;

return;
case 0x0E:
/* DUMPREG */
</geshi>

Notes:

  • Patch @@ -651,7 +653,7 @@ hasn't "really" to do with the problem, but I don't think that a binary not is intended as a bit checking.
  • After reading the data sheet again: 1) 0x80 should be sent in case of an error (not or'd with any value);
  • Not the RECALIBRATE but the SPECIFY call should be done after RESET / SENSE INTERRUPT STATUS sequence, so this call resets the first_sense variable.
  • line break char is LF (linux like), so the diff doesn't contain any CR+LF

Things I didn't change:

  • This second edition of the patch does not change the hack, sending 0x2x as ST0.
  • Considering the data sheet, after SENSE INTERRUPT STATUS the actual head value is not encoded in ST0. (see 6.2.6 SENSE INTERRUPT STATUS)




IDE reset doesn't work correctly

Symptoms:
Using the OS9 bootloader with the boot menu caused a new IDE reset sequence and this isn't handled correctly.

Solution: reset "at least" the value in s->cur_drive
Patch: ide.diff

<geshi type="diff">--- hw/ide.c Wed May 9 20:25:36 2007

hw/ide.c Thu May 17 22:36:25 2007

@@ -2176,6 +2176,7 @@
s->status = 0x00; /* NOTE: READY is _not_ set */
else
s->status = READY_STAT | SEEK_STAT;

s->cur_drive = s;

ide_set_signature(s);
}
}
</geshi>





Data Sheet Reference

Intel 82078 FLOPPY DISK CONTROLLER