Unfortunately, things aren't quite that simple...
The disk (and tape units) contain 129 WORDS per block whereas the memory is divided into 128 WORD 'blocks'.
Unfortunately, the disk/tape units can only read/write the words sequentially from a specific start address within core.
The first 128 WORDS of the disk/tape block are stored into (or retrieved from) core. However, the 129th word has to be inserted in there as well for the disk/tape controller to process it. This would (if not handled correctly) corrupt the first word of the next memory 'block'.
This is the purpose of the LINK word stored within the disk/tape parameter block (supplied to the SYSIO call) and a temporary memory location within the disk/tape driver.
On a disk/tape write the following action is taken:
1. Store the 129th word in memory into the drivers local store to prevent it from being corrupted.
2. Copy the LINK word from the disk/tape parameter block into the 129th word in memory.
3. Perform the disk/tape write operation. This will write out 129 contiguous words from memory to the disk/tape block.
4. Restore the 129th word that was stored away in step 1 back into memory.
On a disk/tape read the following action is taken:
1. Store the 129th word in memory into the drivers local store to prevent it from being corrupted.
2. Perform the disk/tape read operation. This will read in 129 words from the disk/tape block into memory.
3. Copy the 129th word from memory into the LINK word of the disk/tape parameter block.
4. Restore the 129th word that was stored away in step 1 back into memory.
You can now see the problem with an indirect return from a disk/tape read identified within step 3. If the transfer overwrote the JMS instruction and the disk/tape parameter block, storing the LINK word would corrupt what was just read. The DEC driver(s) appear (under these circumstances) to still transfer the LINK word - but they point the address it will be transferred to at a safe/unused memory location within the driver itself. Basically, they dump the word to somewhere safe...
That's my understanding anyhow.
Within my serial implementation, I don't have any such limitation of course. The driver is responsible for 'shovelling' 128 words to/from core and the LINK word directly from the disk/tape parameter block to/from the serial port. The only additional thing I had to incorporate was finding a suitable location to 'dump' the LINK word into on an indirect read operation.
Now, I just have to obfuscate the code a bit to recover some space and make it all fit within 128 words...
I suppose the thing is (now I have found a problem with my serial port read routine) is to identify whether it is robust for 'real world' PDP-8 serial ports or not. Would some kind PDP-8 owners be able to identify a few things for me?
1. Serial port module number.
2. What octal values to you observe in the serial port receive buffer when you type various characters on the terminal device connected to the serial port for a given sequence of characters (e.g. ABCDEF XYZ 123 789).
Does what you receive vary depending upon whether you have parity enabled or not - and whether it is odd or even parity?
My code assumes that the only bits I get back relate to the ASCII value of the character itself. The code I currently have is:
Code:
GETNUM, 0 // Get a number from the server into AC.
// This code assumes that the server only sends 6 valid bits in the byte through and
// the serial port hardware doesn't set any 'mysterious' bits in the value returned
// (e.g. parity or start bits etc.).
SKCC // Clear AC and flag.
// Wait for a character to be received...
SKSF // Skip the next instruction if the flag is set.
JMP .-1 // Loop on last instruction until the flag is set.
SKRB // Read buffer to AC.
CLL // Make sure the L register is clear before rotating! TODO: Combine with the RTL instruction to save a word...
RTL // Rotate AC twice left. Making 2 rotates in total.
RTL // Rotate AC twice left. Making 4 rotates in total.
RTL // Rotate AC twice left. Making 6 rotates in total.
// Wait for another character to be received...
SKSF // Skip the next instruction if the flag is set.
JMP .-1 // Loop on last instruction until the flag is set.
SKRS // OR AC with what is in the receive buffer.
JMP I GETNUM // Return to caller.
My concern is this will not work under all circumstances unless I start performing some masking.
In the meantime, I will look around for other examples on the internet... I think I used Kyle's SerialDisk as the basis of my code in the first place (but missed the CLL out in the process :-().
Dave