A list of files in a makefile goes stale the moment somebody adds a program and forgets to name it, and what they forgot is invisible until they go looking for it on the machine. So SplitDisk gained a mirror command and the disk rule is one line: putting a file where the others live is now the whole of putting it on the disk. EVERY FILE GOES THROUGH put AND EVERY DIRECTORY THROUGH mkdir. That is the point of it - mirror adds a walk and no filesystem code at all, so anything the format refuses here it refuses everywhere, in the same words. What is new is the walk, and the walk is what the six checks in Tests/disk.sh are about: that it goes all the way down, that it leaves dotfiles and named directories behind, and that a name too long stops it. REFUSED RATHER THAN SKIPPED, because a disk quietly missing a file is the exact failure a mirror exists to prevent. Which meant four sources had to be renamed - a directory entry holds 22 characters and they were 23, 23, 24 and 29: 16bitSegmentedSieve.asm -> 16bitSieve.asm 16bitSegmentedSieveModern.asm -> 16bitSieveModern.asm consoleInterruptTest.asm -> consoleInterrupt.asm controllerWriteTest.asm -> controllerWrite.asm The test names in the manifest are unchanged, since those are identifiers and every recorded result is filed under them. Only where the source lives has moved. The entries are sorted before anything is written. readdir hands them back in whatever order the host filesystem feels like, and a disk image that comes out different from one run to the next is an image no test could compare against another. The disk grew from one megabyte to four and from 192 directory entries to 1,024. The sources are 2,850 blocks and the mirror filled the old directory on its first run, which is a thing that should not need thinking about again. The Tests fixture disk is deliberately NOT mirrored. It is a controlled fixture with known contents, and the shipped disk is the one meant to be useful; they want different things. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
162 lines
3.9 KiB
NASM
162 lines
3.9 KiB
NASM
; Tests interrupt on input: the console asking for attention instead of being asked.
|
|
;
|
|
; The control port has two bits and they are independent of one another. Bit 0 puts the
|
|
; console in key mode; bit 1 says to put the interrupt line up when a byte arrives. The
|
|
; console is on port 0x00, so that is the vector a key comes through - a device raises its
|
|
; line on its base port, and the status and control ports belong to the same device as the
|
|
; data port.
|
|
;
|
|
; The main program does nothing at all but wait to be told it is finished. It never looks
|
|
; at the console, which is the whole point: every byte is dealt with by the handler.
|
|
;
|
|
; What the status bits mean:
|
|
; bit 0 READY reading the data port will not have to wait
|
|
; bit 1 ENDED input has run out for good
|
|
; bit 2 KEYMODE the console is in key mode
|
|
; bit 3 INTERRUPTS the console is set to raise its line when a byte arrives
|
|
;
|
|
; This runs with input from a file rather than a terminal, so key mode has no terminal to
|
|
; put into another state and nothing here depends on one. A pipe with bytes in it is a
|
|
; console with keys waiting as far as the console is concerned.
|
|
|
|
#Include console.asm
|
|
|
|
#Program
|
|
|
|
start:
|
|
CIF ; Nothing gets through until there is something to catch it.
|
|
|
|
SETD.0 Banner
|
|
CALL printString
|
|
CALL newLine
|
|
|
|
; Key mode and interrupt on input, asked for in one write. Neither bit depends on the
|
|
; other, so there is no order to get wrong.
|
|
INIA 0x03
|
|
OUTA 0x02
|
|
SETD.0 AskedLabel
|
|
CALL printString
|
|
CALL showStatus
|
|
|
|
SETD.0 ArrivedLabel
|
|
CALL printString
|
|
CALL newLine
|
|
|
|
SIF ; From here a byte arriving runs keyHandler.
|
|
|
|
waitLoop:
|
|
; Waiting without looking. Nothing in this loop touches the console, so every byte that
|
|
; comes out below was put there by something that interrupted this.
|
|
SETD.3 Finished
|
|
LDA.3
|
|
RSTB
|
|
OR ; Q is the flag, so this is a test for zero.
|
|
BRQ waitLoop
|
|
|
|
CALL newLine
|
|
RSTA
|
|
OUTA 0x02 ; Line mode and no interrupts, the way it was found.
|
|
SETD.0 DoneLabel
|
|
CALL printString
|
|
CALL showStatus
|
|
HALT
|
|
|
|
; Entered because the console had something to say. It is never called.
|
|
;
|
|
; DP3 is used freely here: an interrupt saves all four Data Pointers and RETI puts them
|
|
; back, so a handler cannot disturb what it interrupted no matter what it touches.
|
|
keyHandler:
|
|
INA 0x01
|
|
INIB 0x02 ; ENDED
|
|
AND
|
|
BNQ keyEnded
|
|
INA 0x00 ; The byte this interrupt was about.
|
|
OUTA 0x00 ; Nothing echoes in key mode, so the program does it.
|
|
RETI
|
|
|
|
keyEnded:
|
|
; The end of input raises the line once, so a program driven entirely by interrupts
|
|
; still finds out that nothing more is coming. Without it this would wait forever for a
|
|
; key that cannot arrive.
|
|
SETD.3 Finished
|
|
INIA 0x01
|
|
STA.3
|
|
RETI
|
|
|
|
; Prints the status byte as hex and then names the bits that are up, so a change in the
|
|
; output says which bit moved rather than only that the number is different.
|
|
showStatus:
|
|
INA 0x01
|
|
PSHA
|
|
CALL printByteHex
|
|
INIA 0x20
|
|
OUTA 0x00
|
|
POPA
|
|
PSHA
|
|
|
|
INIB 0x01
|
|
AND
|
|
BRQ showNotReady
|
|
SETD.0 ReadyWord
|
|
CALL printString
|
|
showNotReady:
|
|
POPA
|
|
PSHA
|
|
|
|
INIB 0x02
|
|
AND
|
|
BRQ showNotEnded
|
|
SETD.0 EndedWord
|
|
CALL printString
|
|
showNotEnded:
|
|
POPA
|
|
PSHA
|
|
|
|
INIB 0x04
|
|
AND
|
|
BRQ showNotKeys
|
|
SETD.0 KeysWord
|
|
CALL printString
|
|
showNotKeys:
|
|
POPA
|
|
|
|
INIB 0x08
|
|
AND
|
|
BRQ showNotInterrupts
|
|
SETD.0 InterruptsWord
|
|
CALL printString
|
|
showNotInterrupts:
|
|
CALL newLine
|
|
RET
|
|
|
|
#Data
|
|
|
|
Banner:
|
|
"console input interrupts"
|
|
|
|
AskedLabel:
|
|
"asked for: "
|
|
ArrivedLabel:
|
|
"what arrived:"
|
|
DoneLabel:
|
|
"at the end: "
|
|
|
|
ReadyWord:
|
|
"ready "
|
|
EndedWord:
|
|
"ended "
|
|
KeysWord:
|
|
"keys "
|
|
InterruptsWord:
|
|
"interrupts "
|
|
|
|
; Set by the handler when the console says there will be no more bytes. It is the only
|
|
; thing the handler and the program it interrupts have to say to each other.
|
|
Finished:
|
|
0x00
|
|
|
|
#Vectors
|
|
|
|
Boot start
|
|
Device 0x00 keyHandler
|