%RDCDefs.mcinserted by both RDC.Mc (PilotD0 and Initial) and
SA4000Loader.Mc (Initial)

Ed Fiala 3 June 1983: Replace RecalSeekLimitHi/Lo by the integer
RecalSeekLimit; remove Bravo formatting; use RV2 and RV4.
Ev Neely October 24, 1980: Fix RecalSeekLimit.
Ev Neely 10 July 1980: Put definition of RdcIOCBclientLabel back in defs and
restore original name of RdcIOCBdisk because SA4000Loader.mc uses them.
Ev Neely 30 June 1980: Changes in support of 48 bit processor-ID and
miscellaneous IOCB format changes.
Ev Neely 19 June 1980: Added constant in support of counting servicelates
for test purposes.
Ev Neely 13 June 1980: Fix for AR4320 uses previously unused register for
RdcRecalSeekCount, defines RdcRecalSeekLimit and RdcRecalError.
Jim Frandeen 16 February 1980: Use two banks of registers to improve
performance.
Jim Frandeen 20 January 1980: for new D0Lang.
Jim Frandeen 25 December 25 1979: for runs of pages and Version5 of D0Lang.
%
SetTask[RdcTask];
*currently 10b = 8d

*Register definitions for the RDC task.
Set[RdcRegBase,And[60,LShift[RdcTask,4]]];

*Registers 0 and 1 are destroyed by NotifyInterrupt on sector wakeups.

RV[RdcTemp,Add[RdcRegBase,0]];
*HeadSettleCount counts sectors until the heads settle after a seek.
RV[RdcHeadSettleCount,Add[RdcRegBase,1]];

*The next two registers are loaded together from the CSB. NextIOCB points to
*the IOCB of the current command. Deferring will be -1 if an error has been
*reported that has not yet been processed by the client. We stop processing
*IOCBs until Poll sets this back to zero.
RV2[RdcNextIOCB,RdcDeferring,Add[RdcRegBase,2]];

*These four are loaded-from/stored-in the IOCB together. DataPtr (in x and x)
*points to the data specified in the IOCB. IncrementDataPtrFlag is loaded
*from the operation-command word of the IOCB. If negative, DataPtr must be
*incremented after each page transferred. PageCount contains the number of
*pages in the run.
RV4[RdcDataPtr,RdcDataPtr1,RdcIncrementDataPtrFlag,RdcPageCount,Add[RdcRegBase,4]];

*The following two registers must be together and QUADWORD aligned. They are
*loaded together from the IOCB and stored into the IOCB with a PStore4.
*Cylinder contains the cylinder address for the current command. HeadSector
*contains the head and sector address of the current command.
RV2[RdcCylinder,RdcHeadSector,Add[RdcRegBase,10]];

*Command is the command to be executed.
RV[RdcCommand,Add[RdcRegBase,12]];
*RecalSeekCount limits the number of seeks during Recals.
RV[RdcRecalSeekCount,Add[RdcRegBase,13]];

*These four are loaded together from the IOCB. RdcFileFlags contains 3 flag
*bits which must be cleared in computing the next page label for runs of
*pages. FilePageLo is used to increment the file page number in the label
*when one IOCB is used for multiple page accesses. RdcPackedLabel7 and
*RdcPackedLabel8 are loaded from the packed label to permit a PStore4 at
*RdGoodCompletion.
RV4[RdcFileFlags,RdcFilePageLo,RdcPackedLabel7,RdcPackedLabel8,Add[RdcRegBase,14]];

*IOCBptr points to the IOCB of the current command. It is used with ZeroBase
*as a base register to address the first 16 words of the IOCB.
*ZeroBase is used for memory commands to fetch and store data in the CSB and
*the IOCB. Since these control blocks are always in low memory, T is used as
*the address. Since this is an odd base register, ZeroBase OR 1 is the same
*register.
RV2[RdcIOCBptr,RdcZeroBase,Add[RdcRegBase,20]];

*IOCB16Ptr is used with the next register as a base register to address the
*second 16 word block of the IOCB.
RV2[RdcIOCB16Ptr,RdcIOCB16ZeroBase,Add[RdcRegBase,22]];

*DiskAddressPtr points to CSB.diskAddress[current drive]. It is used to
*update CSB.diskAddress when the drive changes and also to see if the drive
*has changed since the last command. It is used as a base register with the
*next register.
RV2[RdcDiskAddressPtr,RdcDiskAddressZeroBase,Add[RdcRegBase,24]];

*CSBptr points to the Controller Status Block.
RV2[RdcCSBptr,RdcCSBzeroBase,Add[RdcRegBase,26]];

*These two are stored together into the IOCB. RdcDiskStatus contains the
*state of the Controller. It is Input at each sector wakeup and when an
*error is detected. CompletionCode is one of the IOCB states described below.
*At RdStoreErrorStatus they are formed into a single word in RdcDiskStatus
*and RdcCompletionCode is set to 0 to convert it into the two word status
*needed by the head.
RV2[RdcDiskStatus,RdcCompletionCode,Add[RdcRegBase,30]];

*CurrentCylinder contains the cylinder address of the selected drive; -1
*means this drive must be recalibrated.
RV[RdcCurrentCylinder,Add[RdcRegBase,32]];

*DriveHead is used to select the drive and head of the current drive.
RV[RdcDriveHead,Add[RdcRegBase,33]];

*SectorTimeOutCount is used to count sectors until timeout for states
*DriveChange, SeekWait, and SectorWait.
RV[RdcSectorTimeOutCount,Add[RdcRegBase,34]];

*NewCylinder will be -1 if we have to seek one cylinder after a page transfer
*during a run of pages; otherwise it will be zero.
RV[RdcNewCylinder,Add[RdcRegBase,35]];

*CurrentSector contains the current sector number of the current drive
*selected. It is updated at each sector wakeup.
RV[RdcCurrentSector,Add[RdcRegBase,36]];

*SeekCommand is only used to contain the command for seeking.
RV[RdcSeekCommand,Add[RdcRegBase,37]];

*Constants

MC[RdcAllowTask,100000];
*To allow task when returning from NotifyInterrupt
MC[RdcBit0,100000];
MC[RdcHead7,3400];
*Head 7 in disk address
MC[RdcSectorsPerTrack,33];

*The following definitions are for the Controller registers:
Set[RdcAddr,LShift[RdcTask,4]];
*The device address of the RDC

Set[RdcGeneralReset,0];
*General Reset
Set[RdcStatus,1];
*Controller and drive status
Set[RdcInputBuffer,17];
*This register presents Buffer[RdcMemBuffAdr].
Set[RdcInput,Add[RdcAddr,17]];
*Complete device address for above.
Set[RdcDrive/Head,1];
*Drive in bits 12-13 (10-11D), Head in bits 14-17 (12-15D)
Set[RdcErrorReset,2];
*Error Reset (data is ignored)
Set[RdcDevOp,3];
*Disk commands and allow wake bit
Set[RdcOutputBuffer,4];
*Data loaded into Buffer[RdcMemBufAddr].
Set[RdcOutput,Add[RdcAddr,4]];
*Complete device address for above.
Set[RdcMemBuffAdr,6];
*Current pointer into the RDC’s data buffer.
Set[RdcPrimeIData,7];
*This register must be accessed by OUTPUT before
*reading the first word of each sector from the
*RdcBuffer.

*The following definitions are for the DevOpReg:
MC[RdcAllowWake,4000];
*Allow wake bit must be set at each Output if wakeups
*are to be enabled.
MC[RdcAllowWakeAndSeekDirection,5000];
MC[RdcSeekBits,3000];
*Seek command bits 5-6
MC[RdcReadWriteBits,377];
*Read-write bits 10-17
MC[RdcSeek-D,6000];
*Seek command in negative direction (outward toward
*lower track numbers) plus allow wake.
MC[RdcSeek+D,7000];
*Seek command in positive direction (inward toward
*higher track numbers) plus allow wake.
MC[RdcWriteHeader,200];
*Write header
MC[RdcDataWriteOrVerify,5];
MC[RdcLabelReadOrVerify,30];
MC[RdcReadData,2];

*The following definitions are for the RdcStatus word:
MC[RdcDevSelOK,20];
*Device is selected and ready.
MC[RdcSeekComplete,40];
MC[RdcTrack0,100];
MC[RdcServiceLate,2000];
MC[RdcRateError,400];
MC[RdcSector0,200];
*Physical sector 0
MC[RdcErrorBitsHigh,400];
*RateError
MC[RdcErrorBitsLow,17];
*BufErr, RdErr, WriteFault, Ofault

*The following definitions are for offsets in the IOCB:
*Microcode needs the IOCB to be on a 16 word boundary:
*Microcode needs this to be first in the IOCB:
*Beginning of operation within IOCB:

*Disk address specified by client used for the initial seek address. It
*almost always duplicates RdcIOCBClientHeader below, which is sent to the
*disk for verification. The head sometimes makes them different during an
*attempt to clarify the nature of errors.
MC[RdcIOCBoperationClientHeader,0];
MC[RdcIOCBLabelPtr,2];
*Ptr to label
*Microcode needs these together and on a quadword boundary:
MC[RdcIOCBdataPtr,4];
*dataPtr: LONG POINTER
MC[RdcIOCBdataPtr1,5];
*dataPtr: LONG POINTER, high order
MC[RdcIOCBoperationCommand,6];
*enumerated Command and incrementDataPtr flag specified by client
MC[RdcIOCBpageCount,7];
*Number of pages this IOCB.
*Microcode needs these together and on a quadword boundary:
MC[RdcIOCBdeviceStatus,10];
*completion: Status 2 words
MC[RdcIOCBdiskHeader,12];
*header read from the disk
MC[RdcIOCBdisk,14];
*disk handle. Cleared by SA4000Loader.
*End of operation within IOCB:
MC[RdcIOCBserviceLateRetryCount,15];
*retries to be executed by microcode
MC[RdcIOCBcontrollerCommand,16];
*Command in the format needed by the controller.
MC[RdcIOCBnext,17];
*next: IOCBLink

*Microcode needs this on a 16 word boundary:
MC[RdcIOCBClientHeader,20];
*client disk address, sent to the disk for
*verification; updated during runs-of-pages.
MC[RdcIOCBClientLabel,24];
*packed label formed from client’s label and
*sent to the disk for verification.
*Microcode needs these on a quadword boundary:
MC[RdcIOCBFileFlags,30];
*file flags. Must be zeroed on runs-of-pages.
MC[RdcIOCBFilePageLo,31];
*filePageLo. Must be incremented on runs-of-pages.
*Microcode needs these on a quadword boundary:
MC[RdcIOCBdiskLabel,34];
*label read from the disk
MC[RdcIOCBdiskLabel+4,40];
*label read from the disk
MC[RdcIOCBrateErrorRetryCount,44];
*retries to be executed by microcode

*The following definition specifies the mask for the IOCB file flags which
*must be cleared in the label of subsequent pagesd in a run-of-pages:
MC[RdcMaskFileFlags,7];
*Mask for file flags.

*The following definitions are for offsets in the CSB (Controller Status Block):
MC[RdcCSBdiskAddress,0];
*diskAddress: ARRAY[0..3] contains cylinder
*address only. -1 is for recalibrate.
MC[RdcCSBnext,4];
*next IOCB to process.
MC[RdcCSBdeferring,5];
*-1 if error encountered. Stop processing
*IOCBs until Poll sets this back to zero.
MC[RdcCSBtail,6];
*Points to last IOCB in the queue. Used only
*by Initiate procedure in Head.
MC[RdcCSBtransferMask,7];
*Transfer mask to schedule Mesa processes at
*end of operation.
MC[RdcCSBserviceLateCount,10];
*This supports counting ServiceLates during
*performance testing.

*The following are times (in sector wakeups) loaded into SectorTimeOutCount:
MC[RdcHeadSettlingTimeWakeUps,37];
*No. wakeups for head to settle after
*seek complete (20 msec or 1 disk revolution).

MC[RdcSeekTimeOutWakeUps,1000];
*No. wakeups until seek time out.
MC[RdcDriveChangeTimeWakeUps,2];
*No. wakeups after drive change.
MC[RdcSectorTimeOutWakeUps,100];
*No. wakeups until sector timeout
*in state SectorWait.

*No. negative one track seeks to try before giving up on trying to find track0
*during a Recal must be loaded into the RdcRecalSeekCount register. 300d
*(454B) is comfortably more than the maximum seeks. Unfortunately, it
*doesn’t fit into 8 bits.
Set[RdcRecalSeekLimit,454];

*The following definitions are for the CompletionCode:
MC[RdcGoodCompletion,1];

*Enter this state from state DataTransfer if any error is detected.
*Bits in the Status word indicate the problem.
MC[RdcDataError,2];

*IOAtten while reading the label field; error bits indicate problem.
MC[RdcLabelError,3];

*IOAtten occurred while reading the label field, and no error bits are set.
MC[RdcLabelCheck,4];

MC[RdcSeekTimeOut,5];
*A time out occurred while doing a seek.
MC[RdcSectorTimeOut,6];
*The sector was not found on the track.
MC[RdcNotReady,7];
*When changing drives, timed out before drive ready.
MC[RdcHeaderError,10];
*IOAtten in the Header field. This could be
*wrongSector, wrongCylinder, or wrongHead. TheFace
*will have to figure out which it is. HeaderError
*corresponds to code wrongSector.
MC[RdcRecalError,5];
*Unable to reach or see track0 while doing a Recal.
*Note: on 11 June 1980, same as a seek timeout.
*Soon a new set of codes from Paul McJones will
*include a recalibrate error.