; DDTapeWriteTask.mu -- Tape Microcode for the Alto Double Density Tape Controller ; Copyright Xerox Corporation 1980 ; Body of Tape Controller write task microcode -- requires definitions in DDTapeDefs.mu ; ; Last modified by Tim Diebert, March 4, 1981 11:32 AM ; ; Branch Conditionals !1, 2, EraseDataOp, WriteData; !1, 2, WriteByte, WriteAlmostLastByte; !1, 2, WriteTwo, WriteOne; !1, 2, EraseData, EraseDone; !1, 2, Write, Write1; ; Write loop ; Task 5 ; ; Write expects the following registers to be loaded. ; ByteCnt should contain the number of bytes to be written. ; WordCnt must not contain any usefull data. ; WrtPtr points to the first word to be transfered - 1. WriteTask: NOP; Write: GoCmd_ ZeroCmd; Tell the read task we understand and are reset. TASK; NOP; THIS IS WHERE THE WRITE TASK SHOULD BE AFTER THE RESET. T_ ResetWriteTask; Wait for write task to reset. L_ TStatus AND T; TASK, SH=0; :Write; [Write, Write1] Write1: T_ IErase; L_ Command AND T; L_ WriteByteCnt, SH=0; Build the word count and the low order bit of the byte count. WriteWordCnt_ LRSH1, :EraseDataOp; [EraseDataOp, WriteData] WriteData: T_ ByteCountOffset; MAR_ TCBBase + T; TASK; MD_ WriteByteCnt; T_ WriteByteCnt; L_ WriteWordCnt - 1; Decrement the word count by 1. WriteWordCnt_ L; L_ 1 AND T; WriteByteCnt_ L; ; The write loop works as follows. The main loop is executed until 4 or 5 bytes ; remain. Then WriteAlmostLastByte is entered. The last word known not to contain the ; last byte is written. The first byte of the word that may contain the last byte is written ; while a check for odd byte is done. At this point the last byte is written or the last 2 ; bytes are written so the hardware can be told when to send LastWord to the formatter. WriteLoop: T_ MAR_ WritePtr + 1; Start memory reference L_ WriteWordCnt - 1; Decrement the byte count WriteWordCnt_ L, L_ T, SH=0; WritePtr_ L, :WriteByte; [WriteByte, WriteAlmostLastByte] WriteByte: L_ TWrite_ MD, TASK; WriteTapeData_ LLCY8; TWrite_ WriteTapeData, TASK; :WriteLoop; WriteAlmostLastByte: L_ TWrite_ MD, TASK; Write byte n-4 or n-3 WriteTapeData_ LLCY8; TWrite_ WriteTapeData, TASK; NOP; L_ MAR_ WritePtr + 1; Start memory reference WritePtr_ L; SINK_ WriteByteCnt, BUS=0; L_ TWrite_ MD, :WriteTwo; [WriteTwo, WriteOne] Write byte n-2 or n-1 WriteOne: TASK; WriteTapeData_ LLCY8; TLastByte_ WriteTapeData; Write byte n. :WriteDone; WriteTwo: TASK; WriteTapeData_ LLCY8; TWrite_ WriteTapeData, TASK; NOP; L_ MAR_ WritePtr + 1; Start memory reference NOP; TLastByte_ MD; Write byte n. L_ ALLONES; MAR_ TCBBase; TASK; MD_ M, :WriteDone; EraseDataOp: WriteTapeData_ 0; EraseData: TASK; NOP; L_ WriteByteCnt - 1; WriteByteCnt_ L, SH=0; TWrite_ WriteTapeData, :EraseData; [EraseData, EraseDone] EraseDone: TASK; NOP; TLastByte_ WriteTapeData; :WriteDone; WriteDone: :Write;