More findings regarding the disk controller

Juergen Buchmueller pullmoll at
Wed Jun 20 05:36:56 PDT 2007

One important thing I found out after hours of debuggig is this:

The WDTASKACT && WDINIT branch to 037 is true for _all_ disk controller
branches! This means that if the WDINIT flip-flop is set, and the currently
executing task is the KWD, then any of the KWD F2s: INIT, RWC, RECNO,

In other words, you'd have to OR not just the result of the specific F2,
but also OR 037, if the WDTASKACT && WDINIT is true. This seems to be a
kind of global break for the KWD task.

And this was what was causing the word task from commencing in the first
place, and by no means a RWC branch 1 that I suspected in a previous mail.
The hardware just doesn't make a branch 1 possible for RWC.

I now have got the drive and disk controller emulated well enough,
including the construction of a raw disk image from the "cooked" data-only
*.dsk.Z images, for the microcode to happily load the header, label and data
of sector 0 without checksum errors.

The (preliminary) layout of a raw sector is this:

/** @brief MFROBL: disk header preamble is 34 words */
#define	MFROBL		34
/** @brief MFRRDL: disk header read delay is 21 words */
#define	MFRRDL		21
/** @brief MIRRDL: interrecord read delay is 4 words */
#define	MIRRDL		4
/** @brief MIROBL: disk interrecord preamble is 3 words */
#define	MIROBL		3
/** @brief MRPAL: disk read postamble length is 3 words */
#define	MRPAL		3
/** @brief MWPAL: disk write postamble length is 5 words */
#define	MWPAL		5

uint8_t mfrdl1[2*MFRDL];		/* 21 words of sync data 0x0001 */
uint8_t header[2*(HEADER_WORDS-1)];	/* the 2nd header word (only!) */
uint8_t cksum1[2*CKSUM_WORDS];		/* 1 word checksum */
uint8_t mirrdl2[2*MIRRDL];		/* 4 words (0x0001) */
uint8_t mwpal2[2*MWPAL];		/* 5 words (0x0001) */
uint8_t label[2*LABEL_WORDS];		/* 8 words label */
uint8_t cksum2[2*CKSUM_WORDS];		/* 1 word checksum */
uint8_t mirrdl3[2*MIRRDL];		/* 4 words (0x0001) */
uint8_t mwpal3[2*MWPAL];		/* 5 words (0x0001) */
uint8_t data[2*DATA_WORDS];		/* 256 words data */
uint8_t cksum3[2*CKSUM_WORDS];		/* 1 word checksum */
uint8_t mrpal4[2*MRPAL];		/* 3 words (or more?) */

The checksum function is a simple XOR of all words of a block, where the
starting value is 0521, which is also contained in the constant PROM address
035. The microcode verifies that after reading a field and its checksum,
the XOR of all of them results in zero.

The header is only one word here, because the word before it is
synchronizing the FFO onto the bit stream, and is therefore (always) read as
0x0001. To get the correct checksum for the header, you would thus have to
XOR with 1. I may be wrong here, but the first header word doesn't seem to
be critical information.

I couldn't find a place where the page number word (first word per
sector) from the disk images would go. Maybe it's contained in the
space after the data words, the microcode doesn't tell me (yet).

The timing was difficult to grok, to say the least, and I'm still not able
to tell exactly what each part in the hardware simulation is doing at what
time. There are so many signals you can get quite confused. I got it
working after all by stupidly re-creating the schematics down to the JK
flip-flop level in software, and fixing lots of bugs of the kind
"wrong wiring". Each bit from the disk drive is now stuffed with its low and
high clock phases into the hardware simulation, which then just does what it
is supposed to do.

Now the boot code looking completely senseless to me seems to be the next
stopover on this odyssey ;-)

I hope these pieces of info are helpful for Altogether, too.

More information about the Altogether-devel mailing list