I'm working on putting a diskette on my SOL
and getting CP/M running on it. Anyway, from
what I can tell, it seems that a NorthStar
MDS-AD3 is a controller commonly found in a
SOL. I've acquired one and I'm in the process
of checking it out. I dumped the boot ROM and
it doesn't look anything like what's on Jim
Battle's page. So I have hand disassembled it
(see below) and it does make sense, it is all
8080 instructions. I don't know the history of
this board, so it may have come out of a
Northstar Horizon.
I have two questions:
1) Does this disassembly look reasonable?
2) Will this run on a 2MHz 8080 (SOL) as opposed
to a 4MHz Z80 (Horizon)?
Slightly odd format disassembly follows:
; NOTES: 1) The address/hex values are correct
; (columns 0-15)
; 2) I think the instructions are correct
; (columns 17-29)
; 3) The comments are my best guess
;
; I'm particularly concerned about the timing loops
; around addresses E86A and E897.
; Also, will the read loops at E8B5 and E8BF be fast
; enough?
E800 0E 0A MVI C, 0AH ; total number of retries (10)
E802 3A 15 EB LDA EB15 ; controller command 15H:
; get A status, turn on motors
E805 16 30 MVI D, 30H ; parameter to function call:
; number of sectors to wait (48)
E807 21 0D E8 LXI H, E80D ; store return address in H, L
E80A C3 D3 E8 JMP E8D3 ; "call" function to wait for D sectors
E80D 3A 01 EA LDA EA01 ; controller order 01H:
; single density,
; side 0,
; step direction out,
; head step signal low,
; select drive 1
E810 21 16 E8 LXI H, E816 ; store return address in H, L
E813 C3 4D E8 JMP E84D ; "call" function to wait for 2 sectors
E816 06 0C MVI B, 0CH ; loop counter, loop 12 times
E818 21 1E E8 LXI H, E81E ; store return address in H, L
E81B C3 D1 E8 JMP E8D1 ; "call" function to wait for 1 sector
E81E 3A 10 EB LDA EB10 ; controller command 10H:
; get A status, no command
E821 E6 40 ANI 40H ; is the index flag bit set?
E823 C2 2D E8 JNZ E82D ; jump if we got the index flag
E826 05 DCR B ; decrement the loop count
E827 C2 18 E8 JNZ E818 ; try again if there are tries remaining
E82A C3 2A E8 JMP E82A ; STOP HERE!!!! loop here forever
; the following three instructions step the head in one track
E82D 3A 21 EA LDA EA21 ; controller order 21H
; single density,
; side 0,
; step direction in,
; head step signal low,
; select drive 1
E830 3A 31 EA LDA EA31 ; controller order 21H
; single density,
; side 0,
; step direction in,
; head step signal high,
; select drive 1
E833 3A 21 EA LDA EA21 ; controller order 21H
; single density,
; side 0,
; step direction in,
; head step signal low,
; select drive 1
E836 C3 4A E8 JMP E84A ; jump to loop bottom
E839 3A 20 EB LDA EB20 ; controller command 20H:
; get B status, no operation
E83C E6 01 ANI 01H ; is the track zero flag bit set
E83E C2 52 E8 JNZ E852 ; if we're on track zero,
; jump out of the step out loop
; the following three instructions step the head out one track
E841 3A 01 EA LDA EA01 ; controller order 01H
; single density,
; side 0,
; step direction out,
; head step signal low,
; select drive 1
E844 3A 11 EA LDA EA11 ; controller order 01H
; single density,
; side 0,
; step direction out,
; head step signal high,
; select drive 1
E847 3A 01 EA LDA EA01 ; controller order 01H
; single density,
; side 0,
; step direction out,
; head step signal low,
; select drive 1
E84A 21 39 E8 LXI H, E839 ; load return address to above address
; (pretty funky, implements loop)
E84D 16 02 MVI D, 02H ; parameter to function call:
; number of sectors to wait (2)
E84F C3 D3 E8 JMP E8D3 ; "call" function to wait for D sectors
; we're now on track zero
E852 21 58 E8 LXI H, E858 ; load return address in H, L
E855 C3 D1 E8 JMP E8D1 ; "call" function to wait for 1 sector
E858 3A 35 EB LDA EB35 ; controller command 35H:
; get C status, turn on motors
E85B E6 0F ANI 0FH ; mask off the sector counter
E85D FE 04 CPI 04H ; are we on sector 4?
E85F C2 52 E8 JNZ E852 ; loop to look for sector 4
E862 3A 10 EB LDA EB10 ; controller command 10H:
; get A status, no operation
E865 E6 04 ANI 04H ; see if read enabled (phase locked loop?)
E867 CA 62 E8 JZ E862 ; loop while we can't read
E86A 3E 09 MVI A, 09H ; timing loop counter
E86C 3D DCR A ; decrement timing loop counter
E86D C2 6C E8 JNZ E86C ; timing loop jump
E870 3A 10 EB LDA EB10 ; controller command 10H:
; get A status, no operation
E873 E6 20 ANI 20H ; is the double density flag bit set
E875 C2 97 E8 JNZ E897 ; jump if we're double density
; the following three instructions step the head in one track
E878 3A 21 EA LDA EA21
E87B 3A 31 EA LDA EA31
E87E 3A 21 EA LDA EA21
E881 21 87 E8 LXI H, E887 ; set the return address
E884 C3 4D E8 JMP E84D ; "call" the function to wait for two sectors
E887 21 8D E8 LXI H, E88D ; set the return address
E88A C3 D1 E8 JMP E8D1 ; "call" the function to wait for 1 sector
E88D 3A 35 EB LDA EB35 ; controller command 35H:
; get C status, turn on motors
E890 E6 0F ANI 0FH ; mask off the sector counter
E892 FE 08 CPI 08H ; are we on sector 8?
E894 C2 87 E8 JNZ E887 ; loop to look for sector 8
E897 06 8C MVI B, 8CH ; loop count to skip header block (140)
E899 11 40 EB LXI D, EB40 ; load D and E with controller command 40H:
; read data, no operation
E89C 3A 10 EB LDA EB10 ; controller command 10H:
; get A status, no operation
E89F 0F RRC ; rotate the body flag bit into the carry flag
E8A0 DA AE E8 JC E8AE ; jump if we're in the body
E8A3 05 DCR B ; decrement loop counter
E8A4 C2 9C E8 JNZ E89C ; check for the body again
E8A7 0D DCR C ; decrement the number of major retries and...
E8A8 C2 2D E8 JNZ E82D ; start the whole thing again if we have any
retries left
E8AB C3 AB E8 JMP E8AB ; STOP HERE!!!! loop here forever
E8AE 1A LDAX D ; read a byte into A (read command loaded into
D, E above)
E8AF 67 MOV H, A ; move the read byte into H
E8B0 2E 01 MVI L, 01H : set L to 1
E8B2 77 MOV M, A ; store the read byte into <byte>01H
(overwritten by E8B6)
E8B3 07 RLC ; start calculating the check character
E8B4 47 MOV B, A ; store the check character in B
E8B5 1A LDAX D ; read the next byte
E8B6 77 MOV M, A ; store the byte
E8B7 A8 XRA B ; continue check character calc
E8B8 07 RLC ; continue check character calc
E8B9 47 MOV B, A ; store the check character in B
E8BA 2C INR L ; increment memory address
E8BB C2 B5 E8 JNZ E8B5 ; reading all 256 bytes (loop if more)
E8BE 24 INR H ; next 256 bytes...
E8BF 1A LDAX D ; read the next byte
E8C0 77 MOV M, A ; store the byte
E8C1 A8 XRA B ; continue check character calc
E8C2 07 RLC ; continue check character calc
E8C3 47 MOV B, A ; store the check character in B
E8C4 2C INR L ; increment memory address
E8C5 C2 BF E8 JNZ E8BF ; reading all 256 bytes (loop if more)
E8C8 1A LDAX D ; read the check character
E8C9 A8 XRA B ; compare to what we calculated
E8CA C2 A7 E8 JNZ E8A7 ; retry the whole thing if we fail
; read success, jump into the code
E8CD 25 DCR H ; back to the first 256 bytes
E8CE 2E 0A MVI L, 0AH ; offset 10
E8D0 E9 PCHL ; jump to the read code
; the following code watches sectors go by
E8D1 16 01 MVI D, 01H ; wait for 1 sector
E8D3 3A 11 EB LDA EB11 ; controller command 11H: get A status, reset
sector flag
E8D6 3A 10 EB LDA EB10 ; controller command 10H: get A status, no
operation
E8D9 B7 ORA A ; set flags
E8DA F2 D6 E8 JP E8D6 ; loop if the sector flag status bit is not
set
E8DD 15 DCR D ; decrement the loop count
E8DE 3A 11 EB LDA EB11 ; controller command 11H: get A status, reset
sector flag
E8E1 C2 D3 E8 JNZ E8D3 ; loop if the loop count is not zero
E8E4 E9 PCHL ; return (sort of)
; extra?
E8E5 00 00 00 00 00 00 00 00 00 00 00
E8F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E1 E9