subject "N* MDS-AD3 disassembly (LONG!)" Bill Sudbrink posted Sun Feb 3 2002 in cctalk email list 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 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