\ \ HD-DMA MARK-II FIRMWARE \ M. STOLOWITZ 11/11/81 \ \ REVISION HISTORY \ \ E - Write ctl early for set up time \ Change constant KR3 in DELAY from \ 33h to 32h. Change Step to delay \ 30 usec minimum if 0 constant. \ \ D - Fix jump REG-HOLD to REG-ENA in seek \ \ C - Sense returns upper 3 bits set \ \ B - Step pulse duration of 11 usec \ \ A - Initial release. \ \ 8XASÍ \ ASSEMBLER VOCABULARY 0 ORG \ IN TARGET HEX 07 EQU OBUF \ DEST - LB - SC 0F EQU NEXT \ DEST - RB - SC 17 EQU IBUF \ SORC - LB 1F EQU LAST \ SORC - RB 200 EQU INTA 400 EQU HOLD_BUS 800 EQU REG_ENA 1000 EQU FPLS_ENA HOLD_BUS REG_ENA + EQU REG_HOLD HOLD_BUS FPLS_ENA + EQU FPLS_HOLD \ \ COMPLEMENTED CONSTANTS TO SEND TO NEXT REGISTER \ FC EQU 8/RAM \ K READ RAM - DMA 9C EQU 0/RAM \ K READ RAM - CHA ED EQU 0/DI \ K READ DI FE EQU 0/SR \ K READ SR 3F EQU DO/CLR/BUF \ K WRITE DO F7 EQU 8/RAM/BUF \ K WRITE RAM - DMA 97 EQU 0/RAM/BUF \ K WRITE RAM - CHA FB EQU CTL/BUF \ K WRITE CTL FF EQU CLR/BUF \ K CLEAR ATTN F3 EQU AL/ADD/BUF \ K WRITE DMA REG DA EQU RD/PR/SR \ READ, PRESET CRC D2 EQU RD/MK/PR/SR \ READ, HANG FOR DATA DE EQU RD/SR \ READ Š1E EQU RD/SR-BUS \ READ, PREV TO RAM 7F EQU LD/BUF \ SR < BUF 6B EQU WR/LD/PR/BUF \ WRT, PR, SR < BUF 67 EQU WR/LD/MK/BUF \ WRT, MK, SR < BUF 6D EQU WR/LD/DI \ WRT, SR < DI AF EQU WR/CRC/BUF \ WRT, CRC 6F EQU WR/LD/BUF \ WRT, SR < BUF \ \ C O L D \ \ Entered on RESET ( bus or via port ) \ Set command address to 43h alligning the NEXT \ pointer to 50h. Delays & size not initialized. \ LABEL COLD REG_ENA $ + 1 + JMP \ ENABLE REGISTERS FF NEXT XMIT \ SYNC 0/RAM/BUF NEXT XMIT \ WRITE NIB 0 C OBUF XMIT \ COMP OF 3 0/RAM/BUF 10 - NEXT XMIT \ WRITE NIB 1 B OBUF XMIT \ COMP OF 4 0/RAM/BUF 20 - NEXT XMIT \ WRITE NIB 2 FF OBUF XMIT \ COMP OF 0 0/RAM/BUF 30 - NEXT XMIT \ WRITE NIB 3 0/RAM/BUF 40 - NEXT XMIT \ WRITE NIB 4 0/RAM/BUF 50 - NEXT XMIT \ WRITE NIB 5 \ \ W A R M \ \ Wait for ATTN, then obtain the bus and load three bytes \ from the NEXT field in the previous command. Transfers \ these bytes to RAM as the new command address. \ LABEL WARM FF NEXT XMIT \ SYNC, CLR ATTN 0/RAM NEXT XMIT \ LAST < ATTN $ 1 - 1 LAST 5 ROT NZT \ REPEAT IF FALSE \ \ Transfer command + 12 to the address register \ LABEL WARM1 FF NEXT XMIT \ DE-SYNC ŠC R3 XMIT \ OFFSET TO NEXT POINTER 0 R11 XMIT \ RETURN INDEX FORWARD XFER_ADDR XFER_ADDR REG_HOLD + JMP \ LOAD ADDR TO DMA REG \ \ Read one byte (status). If OVER RUN, repeat from load \ address. Otherwise continue. \ LABEL WARM2 FF NEXT XMIT \ SYNC, CLEAR ATTN 0/DI NEXT XMIT \ REQUEST BYTE 0/RAM NEXT XMIT \ BUF < BYTE, ATTN < OVER RUN FF NEXT XMIT \ LAST < ATTN $ 2 + 1 LAST 5 ROT NZT \ SKIP IF FALSE WARM1 REG_HOLD + JMP \ ELSE REPEAT \ \ Load three bytes of argument \ FORWARD LOAD3 FF NEXT XMIT \ SYNC 0 R11 XMIT \ RETURN INDEX 0/DI NEXT XMIT \ REQ FIRST BYTE LOAD3 REG_HOLD + JMP \ THE CALL \ \ Xfer arguments to RAM as current command \ LABEL WARM3 0/RAM/BUF R1 XMIT \ RAM ADDRESS 0 R11 XMIT \ RETURN INDEX FORWARD ARGS>RAM ARGS>RAM REG_HOLD + JMP \ THE CALL \ \ S E E K \ \ Relative to the start of the current command structure, \ load the first three bytes. If the count is zero, skip \ to MAIN without releasing the bus. Otherwise, \ release the bus and step the indicated number of tracks \ with STEP-DLY from RAM. If stepping out and TRACK-0 \ then quit. Wait for SEEK-COMPLETE. Wait for HEAD-DLY. \ Obtain bus and enter MAIN. \ \ LABEL SEEK \ \ Transfer command + 0 to the address register \ Š0 R3 XMIT \ BYTE 0 RELATIVE 1 R11 XMIT \ RETURN INDEX XFER_ADDR REG_HOLD + JMP \ XFER ADDR FROM RAM \ \ Load three bytes of argument \ LABEL SEEK1 FF NEXT XMIT \ SYNC 1 R11 XMIT \ RETURN INDEX 0/DI NEXT XMIT \ REQ FIRST BYTE LOAD3 REG_HOLD + JMP \ LOAD THREE BYTES \ \ Complement step count to non-inverted. \ Skip to MAIN if zero steps. \ LABEL SEEK2 FF AUX XMIT \ COMP R5 0 R5 XOR \ INVERT LOW R6 0 R6 XOR \ AND HIGH BYTES $ 3 + R5 NZT \ LOW <> 0 $ 2 + R6 NZT \ HIGH <> 0 FORWARD MAIN MAIN REG_HOLD + JMP \ ELSE MAIN \ \ Mask out STEP bit and store CTL byte. \ DF AUX XMIT \ MASK BIT 5 $ 1 + REG_ENA + JMP \ RELEASE BUS R4 0 R4 AND \ OF CTL BYTE \ \ Decrement, quit if no carry \ LABEL SEEK3 -1 AUX XMIT \ DECR R5 0 R5 ADD \ DECR LOW BYTE $ 4 + OVR NZT \ CONTINUE IF CARRY R6 0 R6 ADD \ DECR HIGH BYTE $ 2 + OVR NZT \ CONTINUE IF CARRY FORWARD SEEK5 SEEK5 REG_ENA + JMP \ STEP COMPLETED \ \ Quit if direction is out and TRACK0 \ 1 AUX XMIT \ MASK AUX 4 R4 AND \ TAKE DIR BIT FORWARD SEEK4 SEEK4 REG_ENA + R0 NZT \ SKIP IF SEEK IN R0 1 LAST MOVE \ IF ON TRACK 0 SEEK5 REG_ENA + R0 NZT \ ENOUGH STEPS \ \ Send a STEP pulse. Fetch step delay from RAM Š\ and wait required number of milliseconds. \ LABEL SEEK4 FF NEXT XMIT \ SYNC CTL/BUF NEXT XMIT \ SET UP OBUF 0 R4 MOVE \ SEND SELECT BYTE CTL/BUF NEXT XMIT \ CTL < SELECT 20 AUX XMIT \ TOGGLE FOR STEP OBUF 0 R4 XOR \ STEP LOW CTL/BUF NEXT XMIT \ CTL < LOW, WRITE CTL CTL/BUF NEXT XMIT \ CTL < LOW, 2ND TIME OBUF 0 R4 MOVE \ STEP HIGH 8/RAM 10 - NEXT XMIT \ CTL < HIGH, REQ HIGH NIB 8/RAM NEXT XMIT \ REQ LOW NIB, BUF < LOW R0 3 IBUF MOVE \ MASK LOW NIBBLE R0 4 R0 MOVE \ SWAP NIBBLES FF NEXT XMIT \ BUF < HIGH, DE-SYNC FORWARD DELAY R1 4 IBUF ADD \ MERGE NIBBLES 0 R11 XMIT \ RETURN INDEX DELAY R1 NZT \ CALL FOR MSEC 1 R1 XMIT \ 30 USEC CONSTANT 7 R2 XMIT \ 30 USEC CONSTANT FF AUX XMIT DELAY REG_ENA + 4 + JMP \ \ \ Wait for SEEK-COMPLETE if drive is READY. \ LABEL SEEK5 1 AUX XMIT \ COMP LOW BIT FF NEXT XMIT \ SYNC R1 1 LAST 2 ROT MOVE \ TEST READY $ 3 + R1 NZT \ SKIP IF TRUE FE R6 XMIT \ STATUS OF 1 FORWARD STATUS STATUS REG_HOLD + JMP \ SEND STATUS & ABORT R1 1 LAST 3 ROT XOR \ TEST SEEK COMPLETE SEEK5 R1 NZT \ SKIP IF TRUE \ \ Fetch the head settle delay from the RAM and \ wait the required number of milliseconds. \ 8/RAM 20 - NEXT XMIT \ REQ LOW NIB OF HDLY 8/RAM 30 - NEXT XMIT \ BUF < LOW, REQ HIGH Š R0 4 IBUF MOVE \ MASK LOW NIBBLE R0 4 R0 MOVE \ SWAP NIBS FF NEXT XMIT \ BUF < HIGH R0 4 IBUF ADD \ OR NIBS R1 4 R0 MOVE \ SWAP NIBS > R3 1 R11 XMIT \ RETURN INDEX DELAY REG_ENA + JMP \ DELAY \ \ M A I N \ \ Relative to the start of the current command, load bytes \ four through twelve. Byte four goes to the control \ register, bytes five through seven will be left in the \ DMA address register. Bytes eight through eleven will \ be left in registers R3-R6 as arguments and byte twelve \ will be interpreted as the command. Routine is entered \ with the bus held and starting address in the DMA reg. \ LABEL MAIN \ \ Load command + 3 to the address register \ 3 R3 XMIT \ RELATIVE TO START 3 R11 XMIT \ RETURN INDEX XFER_ADDR REG_HOLD + JMP \ CALL FOR ADDRESS \ \ Read CTL byte and test for OVER-RUN. If true, \ go back and refetch the address. Otherwise, \ store the byte received in CTL \ LABEL MAIN1 FF NEXT XMIT \ SYNC 0/DI NEXT XMIT \ REQ BYTE3 0/RAM NEXT XMIT \ BUF < CTL, ATTN < OVER-RUN R0 0 IBUF MOVE \ TAKE DATA FF NEXT XMIT \ LAST < ATTN R1 1 LAST 5 ROT MOVE \ TEST FOR OVER-RUN $ 2 + R1 NZT \ SKIP IF FALSE MAIN REG_HOLD + JMP \ ELSE REPEAT DF R1 XMIT \ MASK STEP OUT CTL/BUF NEXT XMIT \ OF DATA AND SENT OBUF 0 R1 AND \ TO CTL REG \ \ Load 7 bytes of arguments to R0-R7 \ FORWARD LOAD7 2 R11 XMIT \ RETURN INDEX Š0/DI NEXT XMIT \ REQ FIRST BYTE LOAD7 REG_HOLD + JMP \ AND 6 MORE \ \ Read one more byte, the Op code, to R11 \ LABEL MAIN2 0/DI NEXT XMIT \ REQ ONE MORE! FF NEXT XMIT \ BUF < BYTE R11 0 IBUF MOVE \ OP CODE TO R11 \ \ Store R0-R3, the DMA address in the address \ register \ AL/ADD/BUF NEXT XMIT \ STORE OBUF 0 R0 MOVE \ BYTE1 AL/ADD/BUF 40 - NEXT XMIT \ STORE OBUF 0 R1 MOVE \ BYTE2 AL/ADD/BUF 80 - NEXT XMIT \ STORE OBUF 0 R2 MOVE \ BYTE3 FF NEXT XMIT \ ADD < BYTE3, DE-SYNC \ \ Complement the Op code. \ FF AUX XMIT \ COMP R11 0 R11 XOR \ THE OP \ \ Test for illegal Op \ F8 AUX XMIT \ MASK > 7 R0 0 R11 AND \ TEST OP $ 10 + R0 NZT \ SKIP IF BAD \ \ Skip read write if drive is not ready. \ 04 AUX XMIT \ BIT 2 R0 0 R11 AND \ TEST OP $ 5 + R0 NZT \ EXECUTE OPS > 4 R0 1 LAST 2 ROT MOVE \ TEST DRIVE READY $ 3 + R0 NZT \ IF READY EXEC OP FE R6 XMIT \ STATUS 01 STATUS REG_HOLD + JMP \ RETURN STATUS \ \ Interpret the command \ FORWARD FIND_HEAD FORWARD WRITE_HEADS FORWARD READ_HEAD FORWARD SET_CONSTANTS FORWARD STATUS-OK ŠFORWARD SENSE FORWARD ILLEGAL $ 1 + R11 XEC \ INTERPRET COMMAND FIND_HEAD REG_ENA + JMP \ READ-DATA FIND_HEAD REG_ENA + JMP \ WRITE-DATA READ_HEAD FPLS_HOLD + JMP \ READ-HEAD WRITE_HEADS REG_ENA + JMP \ WRITE-HEADS SET_CONSTANTS REG_HOLD + JMP \ STEP,HEAD AND SIZE SENSE REG_HOLD + JMP \ RETURN LAST STATUS-OK REG_HOLD + JMP \ NOOP ILLEGAL REG_HOLD + JMP \ ILLEGAL OP CODE \ \ S E N S E \ \ Enter contents of LAST register as STATUS. \ LABEL SENSE 1F AUX XMIT \ SET HIGH BITS R6 5 LAST AND \ FORCE 3 UPPER BITS HIGH STATUS REG_HOLD + JMP \ RETURN AS STATUS \ \ S T A T U S \ \ Enter with status in R6. Store the status in the 13th \ byte of the current command and return to WARM. Set \ interrupt if enabled. \ \ CODE CAUSE \ \ 00 BUSY \ 01 NOT RDY \ 04 HEAD NOT FOUND \ 05 DATA NOT FOUND \ 06 DATA OVER-RUN \ 07 DATA CRC \ 08 WRITE FAULT \ 09 HEAD CRC \ 0A ILLEGAL OP CODE \ FF OK COMPLETION \ LABEL ILLEGAL \ \ Illegal Op Code. \ F5 R6 XMIT \ STATUS 0A STATUS REG_HOLD + JMP \ SEND STATUS LABEL STATUS-OK \ \ Shared entry for OK status. \ 00 R6 XMIT \ LOAD OK STATUS LABEL STATUS \ Š\ Enter with status in R6. \ Load command + 11 to the address register \ B R3 XMIT \ RELATIVE TO START 2 R11 XMIT \ RETURN INDEX XFER_ADDR REG_HOLD + JMP \ CALL FOR ADDRESS \ \ Read byte 12. If not over-run, write status to \ byte 13. Otherwise, repeat from XFER_ADDR. \ LABEL STATUS1 FF NEXT XMIT \ SYNC, CLR ATTN 0/DI NEXT XMIT \ REQ BYTE12 0/RAM NEXT XMIT \ BUF < CTL, ATTN < OVER-RUN FF NEXT XMIT \ LAST < ATTN, DE-SYNC $ 2 + 1 LAST 5 ROT NZT \ SKIP IF FALSE STATUS REG_HOLD + JMP \ ELSE REPEAT OBUF 0 R6 MOVE \ DATA TO BUFFER DO/CLR/BUF NEXT XMIT \ SEND STATUS TO MEMORY FF NEXT XMIT \ KEEP WRITE HIGH \ \ High order bit of step delay byte in RAM indicates \ interrupt is desired. \ 8/RAM 10 - NEXT XMIT \ RAM < BUF, READ INTR-FLG FF NEXT XMIT \ BUF < FLG R0 1 IBUF 3 ROT MOVE \ TEST FOR INTR ENA $ 2 + R0 NZT \ SKIP IF SET WARM REG_ENA + JMP \ WARM, NO INTERRUPT WARM REG_ENA + INTA + JMP \ WARM, WITH INTERRUPT \ \ F U N C T I O N X F E R - A D D R \ \ Loads the DMA register with the effective address \ equal to the some of the command pointer in RAM \ plus the contents of R3 ( relative addressing ). \ \ R0 WORKING \ R1 RAM POINTER \ R2 DMA POINTER \ R3 OFFSET \ LABEL XFER_ADDR 0/RAM R1 XMIT \ RAM ADDRES AL/ADD/BUF R2 XMIT \ DMA REG ADDR ŠFF NEXT XMIT \ SYNC LABEL XFER_ADDR1 NEXT 0 R1 MOVE \ REQ LOW NIBBLE -10 AUX XMIT \ INCR R1 0 R1 ADD \ BUMP ADDR NEXT 0 R1 MOVE \ REQ HIGH NIBBLE R1 0 R1 ADD \ BUMP ADDR R0 4 IBUF MOVE \ MASK LOW NIB R0 4 R0 MOVE \ SWAP NIBS FF NEXT XMIT \ BUF < RAM R0 4 IBUF ADD \ MERGE NIBBLES R0 4 R0 MOVE \ SWAP NIBS R0 0 R3 ADD \ OFFSET FF NEXT XMIT \ SYNC R3 0 OVR MOVE \ SAVE OVF FF OBUF XMIT \ COMPLEMENT NEXT 0 R2 MOVE \ SEND TO DMA OBUF 0 IBUF XOR \ INVERT TO BUF -40 AUX XMIT \ AND INCR R2 0 R2 ADD \ DMA ADDR FF NEXT XMIT \ DE-SYNC 33 AUX XMIT \ ADDR END CNT R0 0 R2 XOR \ TEST FOR END XFER_ADDR1 R0 NZT \ LOOP THREE TIMES $ 1 + R11 XEC \ RETURN WARM2 REG_HOLD + JMP \ WARM SEEK1 REG_HOLD + JMP \ SEEK STATUS1 REG_HOLD + JMP \ STATUS MAIN1 REG_HOLD + JMP \ MAIN \ \ F U N C T I O N A R G S > R A M \ \ Transfers three bytes of data from R4 - R6 to \ the RAM starting at the location indicated by R1. \ Assumes bus held and address register is loaded. \ \ R0 WORKING \ R1 RAM POINTER \ R2 COUNT \ R4 LSB \ R5 \ R6 MSB \ R11 RETURN INDEX \ LABEL ARGS>RAM FF NEXT XMIT \ SYNC Š -10 AUX XMIT \ DECR NEXT 0 R1 MOVE \ NEXT < LOW, RAM < HIGH R1 0 R1 ADD \ BUMP ADDR OBUF 0 R4 MOVE \ BUF < R4 NEXT 0 R1 MOVE \ NEXT < HIGH, RAM < LOW OBUF 0 IBUF 4 ROT MOVE \ SWAP NIBS R1 0 R1 ADD \ BUMP ADDR NEXT 0 R1 MOVE \ NEXT < LOW, RAM < HIGH R1 0 R1 ADD \ BUMP ADDR OBUF 0 R5 MOVE \ BUF < R5 NEXT 0 R1 MOVE \ NEXT < HIGH, RAM < LOW OBUF 0 IBUF 4 ROT MOVE \ SWAP NIBS R1 0 R1 ADD \ BUMP ADDR NEXT 0 R1 MOVE \ NEXT < LOW, RAM < HIGH R1 0 R1 ADD \ BUMP ADDR OBUF 0 R6 MOVE \ BUF < R6 NEXT 0 R1 MOVE \ NEXT < HIGH, RAM < LOW OBUF 0 IBUF 4 ROT MOVE \ SWAP NIBS FF NEXT XMIT \ RAM < HIGH, DE-SYNC $ 1 + R11 XEC \ RETURN SEEK REG_HOLD + JMP \ WARM STATUS-OK REG_HOLD + JMP \ SET_CONSTANTS \ \ S E T - C O N S T A N T S \ \ Transfer arguments from R4-R6 to RAM at byte 8. \ \ R4 Interrupt Enable/Step Delay \ R5 Head Settle Delay \ R6 Sector Size \ R11 RETURN \ LABEL SET_CONSTANTS 8/RAM/BUF R1 XMIT \ RAM ADDRESS 1 R11 XMIT \ RETURN INDEX ARGS>RAM REG_HOLD + JMP \ THE CALL \ \ F U N C T I O N D E L A Y \ \ R1 contains delay in 100 usec increments. \ Instructions execute in 2 x ( 1 / 7.159 MHz ). \ Inner two loops take KR2 ( 3 + 2 * KR3 ) + 1 instructions. \ 100 usec / 279.3 nsec = 300 instructions. Let KR3 = 2 \ and KR2 = 42. Range is 0..25.5 milliseconds. Š\ R4 - R6 are saved. \ LABEL DELAY $ 2 + R1 NZT \ SKIP NOT ZERO $ B + R11 XEC \ RETURN FF AUX XMIT \ DECR 33 R2 XMIT \ INDEX J 2 R3 XMIT \ INDEX I R3 0 R3 ADD \ BUMP I $ 1 - R3 NZT \ UNTIL 0 R2 0 R2 ADD \ BUMP J $ 4 - R2 NZT \ UNTIL 0 R1 0 R1 ADD \ BUMP K $ 7 - R1 NZT \ UNTIL 0 $ 1 + R11 XEC \ RETURN SEEK3 REG_ENA + JMP \ SEEK MAIN REG_HOLD + JMP \ MAIN LOOP \ \ F U N C T I O N L O A D _ A R G \ \ Loads up to seven bytes of arguments into registers \ R(7-N) - R6. Other registers are not affected. Returns \ via R11. Calling routine issues first 0/DI NEXT. \ LABEL LOAD7 0/DI NEXT XMIT \ BUF < ARGN-6, REQ ARGN-5 R0 0 IBUF MOVE \ R0 < /ARGN-6 0/DI NEXT XMIT \ BUF < ARGN-5, REQ ARGN-4 R1 0 IBUF MOVE \ R1 < /ARGN-5 0/DI NEXT XMIT \ BUF < ARGN-4, REQ ARGN-3 R2 0 IBUF MOVE \ R2 < /ARGN-4 0/DI NEXT XMIT \ BUF < ARGN-3, REQ ARGN-2 R3 0 IBUF MOVE \ R3 < /ARGN-3 LABEL LOAD3 0/DI NEXT XMIT \ BUF < ARGN-2, REQ ARGN-1 R4 0 IBUF MOVE \ R4 < /ARGN-2 0/DI NEXT XMIT \ BUF < ARGN-1, REQ ARGN R5 0 IBUF MOVE \ R5 < /ARGN-1 FF NEXT XMIT \ BUF < ARGN, DE-SYNC R6 0 IBUF MOVE \ R6 < /ARGN $ 1 + R11 XEC \ THE RETURN WARM3 REG_HOLD + JMP \ WARM SEEK2 REG_HOLD + JMP \ SEEK MAIN2 REG_HOLD + JMP \ MAIN Š100 ORG \ \ F U N C T I O N F I N D - H E A D \ \ Find a header matching R3-R6. If A1* and FE do \ not match, a header was not found. Resync. If \ A1* and FE are ok but R3-R6 do not match, a head \ was found, but the wrong one. Bump retries and quit \ if zero ( wrong track ). Fetch the sector size from \ the RAM and procede to READ or WRITE. \ \ R0 WORKING \ R1 WORKING \ R2 RETRYS \ R3 CYLINDER1 \ R4 CYLINDER2 \ R5 HEAD \ R6 SECTOR \ R11 RETURN \ LABEL FIND_HEAD FPLS_ENA $ + 1 + JMP \ ENABLE FPLS 80 R2 XMIT \ INIT RETRIES LABEL HEAD1 FF NEXT XMIT \ SYNC RD/PR/SR NEXT XMIT \ READ SYNC RD/MK/PR/SR NEXT XMIT \ READ, HANG FOR DATA 5E AUX XMIT \ COMP A1 RD/SR NEXT XMIT \ REQ A1 RD/SR NEXT XMIT \ BUF < A1, REQ FE R0 0 IBUF XOR \ TEST A1 R1 1 LAST 7 ROT MOVE \ CAPTURE MARK-CLK HEAD1 R0 NZT \ IF NOT A1 RD/SR NEXT XMIT \ BUF < FE, REQ CYL 01 AUX XMIT \ COMP FE R0 0 IBUF XOR \ TEST FE HEAD1 R0 NZT \ IF NOT FE RD/SR NEXT XMIT \ BUF < CYL1, REQ CYL2 R0 0 R3 MOVE \ CYLINER1 R0 0 IBUF XOR \ TEST FORWARD HEAD2 HEAD2 R0 NZT \ IF WRONG CYL RD/SR NEXT XMIT \ BUF < CYL2, REQ HD R0 0 R4 MOVE \ CYLINDER2 R0 0 IBUF XOR \ TEST ŠHEAD2 R0 NZT \ IF WRONG CYL RD/SR NEXT XMIT \ BUF < HD, REQ SEC R0 0 R5 MOVE \ HEAD R0 0 IBUF XOR \ TEST HEAD2 R0 NZT \ IF WRONG HEAD RD/SR NEXT XMIT \ BUF < SEC, REQ CRC1 R0 0 R6 MOVE \ SECTOR R0 0 IBUF XOR \ TEST HEAD2 R0 NZT \ IF WRONG SECTOR RD/SR NEXT XMIT \ ERROR < CRC1, REQ CRC2 HEAD1 R1 NZT \ IF NOT MARK-CLK FF NEXT XMIT \ ERROR < CRC2, POST1 R0 1 LAST 6 ROT MOVE \ TEST ERROR $ 2 + R0 NZT \ IF NOT CRC ERROR HEAD2 FPLS_ENA + JMP \ ELSE TRY AGAIN \ \ Need the sector size nibble \ $ 1 + REG_ENA + JMP \ ENABLE REGISTERS 8/RAM 40 - NEXT XMIT \ REQ THE SIZE, POST2 FF NEXT XMIT \ DE-SYNC, POST3 R3 0 IBUF MOVE \ SECTOR SIZE $ 1 + R11 XEC \ TO READ OR WRITE FORWARD READ_DATA FORWARD WRITE_DATA READ_DATA FPLS_HOLD + JMP \ READ WRITE_DATA FPLS_HOLD + JMP \ WRITE \ \ Header found, but wrong one. Decrement retries. \ Quit if retrys are down to zero. \ LABEL HEAD2 -1 AUX XMIT \ DECR R2 0 R2 ADD \ RETRIES HEAD1 R2 NZT \ CONT IF MORE FB R6 XMIT \ ELSE NOT FOUND STATUS REG_HOLD + JMP \ RETURN STATUS 04 \ \ C O M M A N D R E A D \ \ DMA address is setup, a header has been found \ and the sector size is in register R3. Exit \ to ?OVER-RUN. \ LABEL READ_DATA FF NEXT XMIT \ SYNC ŠRD/PR/SR NEXT XMIT \ READ SYNC RD/MK/PR/SR NEXT XMIT \ READ, HANG FOR DATA RD/SR NEXT XMIT \ REQ A1 5E AUX XMIT \ COMP OF A1 RD/SR NEXT XMIT \ BUF < A1, REQ F8 R1 0 IBUF XOR \ COMP & TEST A1 R2 1 LAST 7 ROT MOVE \ SAVE MARK CLK STATUS 07 AUX XMIT \ COMP OF F8 RD/SR-BUS NEXT XMIT \ BUF < F8, REQ BD0 FORWARD READ1 READ1 R1 NZT \ IF NOT A1 READ1 R2 NZT \ IF NOT MARK CLK R1 0 IBUF XOR \ TEST F8 RD/SR-BUS NEXT XMIT \ RAM < BD0, REQ BD1 READ1 R1 NZT \ IF NOT F8 -1 AUX XMIT \ DECR LABEL READ4 7D R2 XMIT \ 125 BTYES TO GO LABEL READ2 RD/SR-BUS NEXT XMIT \ REQ BDN - BDXFE, REQ BD2 FORWARD READ3 R2 0 R2 ADD \ BUMP COUNT READ2 R2 NZT \ IF MORE BYTES READ3 R3 NZT \ IF MORE NBYTES RD/SR-BUS NEXT XMIT \ REQ BDXFF RD/SR NEXT XMIT \ RAM < BDXFF, RD CRC1 RD/SR NEXT XMIT \ ERROR < CRC1, RD CRC2 0/RAM NEXT XMIT \ ERROR < CRC2, LEAVE ATTN FORWARD CHECK R0 1 LAST 6 ROT MOVE \ TEST ERROR CHECK R0 NZT \ IF NOT CRC ERROR F8 R6 XMIT \ CRC ERR 07 STATUS REG_HOLD + JMP \ RETURN RESULT LABEL READ3 RD/SR-BUS NEXT XMIT \ REQ BYTE - XFF R3 0 R3 ADD \ BUMP NBYTES 7F R2 XMIT \ REPEAT FOR READ2 FPLS_HOLD + JMP \ 127 MORE BYTES LABEL READ1 FA R6 XMIT \ NOT FOUND ERR 05 STATUS REG_HOLD + JMP \ RETURN STATUS Š \ \ C O M M A N D # 9 W R I T E \ \ DMA address is setup, a header has been found \ and the sector size is in register R3. Exit \ to ?OVER-RUN. \ LABEL WRITE_DATA LD/BUF NEXT XMIT \ SYNC, POST3 \ \ Write preamble of 12 bytes 00 \ FF OBUF XMIT \ 00 DATA D R1 XMIT \ COUNT FF AUX XMIT \ DECR WR/LD/PR/BUF NEXT XMIT \ PREAM1 R1 0 R1 ADD \ DECR COUNT $ 2 - R1 NZT \ CONT IF MORE \ \ Write A1* \ 5E OBUF XMIT \ BUF < A1 WR/LD/MK/BUF NEXT XMIT \ SR < A1* \ \ Write F8 \ 07 OBUF XMIT \ BUF < F8 80 R2 XMIT \ 128 BYTES $ 2 + R2 NZT \ ENTER DATA LOOP LABEL WRITE1 7F R2 XMIT \ 127 BYTES TO GO LABEL WRITE2 WR/LD/DI NEXT XMIT \ REQ BD01 - BDFE, SR < F8 FORWARD WRITE3 R2 0 R2 ADD \ BUMP COUNT WRITE2 R2 NZT \ IF MORE BYTES WRITE3 R3 NZT \ IF MORE NBYTES WR/CRC/BUF NEXT XMIT \ REQ BDXFF, REQ CRC1 WR/CRC/BUF NEXT XMIT \ SR < CRC1, REQ CRC2 WR/LD/BUF NEXT XMIT \ SR < CRC2, REQ POST1 FF OBUF XMIT \ BUF < 00 DATA WR/LD/BUF NEXT XMIT \ SR < 00, REQ POST2 WR/LD/BUF NEXT XMIT \ SR < 00, REQ POST3 WR/LD/BUF NEXT XMIT \ SR < 00, REQ POST4 ŠCHECK FPLS_HOLD + JMP \ TEST OVER_RUN \ \ Decrement sector size ( number of 128 byte blocks ) \ and continue. \ LABEL WRITE3 WR/LD/DI NEXT XMIT \ REQ BDFF R3 0 R3 ADD \ DECR NBYTES WRITE1 FPLS_HOLD + JMP \ CONTINUE \ \ C O M M A N D R E A D H E A D E R \ \ DMA address is setup. Exit to ?OVER-RUN. \ LABEL READ_HEAD FF NEXT XMIT \ SYNC, CLR RD RD/PR/SR NEXT XMIT \ READ SYNC RD/MK/PR/SR NEXT XMIT \ READ, HANG FOR DATA RD/SR-BUS NEXT XMIT \ REQ A1 RD/SR-BUS NEXT XMIT \ RAM < A1, BUF < A1, REQ FE RD/SR-BUS NEXT XMIT \ RAM < FE, BUF < FE, REQ CYL1 RD/SR-BUS NEXT XMIT \ RAM < CYL1, REQ CYL2 RD/SR-BUS NEXT XMIT \ RAM < CYL2, REQ HD RD/SR-BUS NEXT XMIT \ RAM < HD, REQ SEC RD/SR-BUS NEXT XMIT \ RAM < SEC, REQ CRC1 RD/SR-BUS NEXT XMIT \ RAM