-- DDC.mesa (last edited by: Forrest on: March 31, 1981 8:42 AM)
-- Things to do:
-- Some bit fields within the IOCB are set with BITOR. They need
-- to be explicitly named and set correctly within mesa constructs.
-- Use enumerated’s for the commands.
DIRECTORY
Environment USING [Base],
PilotDisk USING [Label],
SA4000Face USING [Command, Operation, Status];
DDC: DEFINITIONS =
BEGIN
-- Dandelion Disk Controller I/O Command Block (IOCB)
-- 16 word aligned, and MUST NOT CROSS A PAGE!
IOCB: TYPE = MACHINE DEPENDENT RECORD [
operation(0): SA4000Face.Operation,
savedIOCBCmd(13:0..4): SA4000Face.Command, -- for label fixup.
savedError(13:5..8): SA4000Face.Status,
unused(13:9..11): [0..8) ← NULL,
iocbState(13:12..15): ProcessingState,
presentCylinder(14): CARDINAL, -- cyl after this stage
destCylinder(15): CARDINAL, -- when we’re done....
-- TRANSFER PARM MUST BE ON 16 WORD BOUNDARY
transferParm(16): ParameterBlock,
nextIOCB(33): Environment.Base RELATIVE POINTER
TO ChannelCommand,
seekCommand(34): SeekBlock,
transferCommand(52): TransferBlock,
countThisStage(66): CARDINAL, -- # pages for this stage
label(67): PilotDisk.Label,
unusedLabel(77): LONG UNSPECIFIED←0]; -- must follow label
ChannelCommand: TYPE; -- never used, just something to point at
IOCBshortPtr: TYPE = Environment.Base RELATIVE POINTER TO IOCB;
IOCBlongPtr: TYPE = LONG POINTER TO IOCB;
-- states used to specify the stage of an IOCB. Note various sections of
-- code depend on the ordering of the values within this type.
ProcessingState: TYPE = MACHINE DEPENDENT {
startRecal, recalSeek, recalStepIn, recalStepOut, startSeek, doSeek,
startTransfer, eraseSA1000Track, transfer, transferFinish, labelRead};
-- parameter block specifies commands, fields length, masks, etc
-- used to transfer a run of pages
ParameterBlock: TYPE = MACHINE DEPENDENT RECORD [
sectorCount(0): CARDINAL, -- number of sectors to transfer
failCount(1): CARDINAL, -- sectors/fields to skip when
-- looking for header
headerOp(2:0..79): HeaderBlock, -- block of words used to specify
-- the header op
labelOp(7:0..63): LabelBlock, -- block of words used to specify
-- the Label op
dataOp(11:0..63): DataBlock, -- block of words used to specify
-- the data op
miscCmds(15:0..31): MiscCommandBlock]; -- stop the hardware between
-- fields/find next sector mark.
HeaderBlock: TYPE = MACHINE DEPENDENT RECORD [
headerCmd(0): WORD, -- command word specifying header op
headerCnt(1): CARDINAL, -- word count for header field
headerAddr(2): CARDINAL, -- lo 16 bits of clientHeader if verify
-- or write, diskHeader if read
headerQuitMsk(3): WORD, -- mask used to decide to quit after
-- header op
headerLoopMsk(4): WORD]; -- mask used to decide to loop looking
-- for more headers after the
-- header operation
LabelBlock: TYPE = MACHINE DEPENDENT RECORD [
labelCmd(0): WORD, -- control word specifying operation
-- on label field
labelCnt(1): CARDINAL, -- word count for label field
labelAddr(2): CARDINAL, -- lo 16 physical addr of IOCB’s
-- label field
labelMsk(3): WORD]; -- mask used to decide whether to
-- quit after label field
DataBlock: TYPE = MACHINE DEPENDENT RECORD [
dataCmd(0): WORD, -- control word specifying operation
-- on data field
dataCnt(1): CARDINAL, -- word count for data field
dataPgNum(2): CARDINAL, -- virtual page number of data
-- buffer for this op
dataMsk(3): WORD]; -- mask used to decide to quit
-- after data field
MiscCommandBlock: TYPE = MACHINE DEPENDENT RECORD [
freezeCmd(0): WORD, -- reset hardware after each
-- field transferred
findSectMkCmd(1): WORD]; -- find the next sector mark, if any
-- the following block is used both the send seek command and also
-- to formulate a series of commands used to find sector 0 of the disk.
-- The latter is done by finding the index mark, then counting 27 sectors
-- marks on the SA4000, simply by finding the index mark on the SA1000.
SeekBlock: TYPE = MACHINE DEPENDENT RECORD [
negDistance(0): INTEGER, -- negative number step pulses
-- to send/sector pulses to count
sendWaitCmd(1): WORD, -- tells disk uCode to send command
-- that forces it to wait for
-- SeekComplete before proceeding
waitCmd(2): WORD, -- this the control word sent
sendCtl1(3): WORD, -- tells disk uCode to sent next word
controlWd1(4): WORD, -- raises the step line, direction bit
-- is set when command is set or
-- waits for index mark
sendCtl2(5): WORD, -- tells disk uCode to sent next word
-- to hardware
controlWd2(6): WORD, -- lowers the step line (may also be
-- set so disk uCode service request
-- is turned off until SeekComplete
-- arrives back from the drive)
-- or waits for sector mark
inrNegDistance(7): WORD, -- have disk uCode increment neg
-- distance or sector count and skip
negDistanceAddr(8): WORD, -- the next two words if it is zero
jumpToStep(9): WORD, -- if count is zero, jump back to the
-- loop point (sendCtl1 if this is
-- a seek command or sendCtl2 if this
-- is counting sectors until sector 0)
sendCtlAddr(10): WORD, -- physical address of proper send
-- control word
initRegsCmd(11): WORD, -- test the controller status against
-- a mask of 0 (next word). This has
-- the desirable side effect of
-- clearing the microcode’s UStatus
-- register of spurious error flag bits
initRegsParm(12): WORD, -- dummy parameter containing zero
finishSeek(13): FinishBlock]; -- end of seek command or contains
-- a jump if this found the index
-- mark for The find sector 0 command
FinishBlock: TYPE = MACHINE DEPENDENT RECORD [
finishCmd(0): WORD, -- tells uCode to finish up CSB
nextIOCB(1): Environment.Base RELATIVE POINTER TO ChannelCommand,
-- lohalf virt address of the next IOCB
-- in chain or 0 if there is another
-- stage to this IOCB
transferMask(2): WORD, -- word used to set mesa interrupt flags
-- signalling the end of the IOCB stage
stopCmd(3): WORD, -- command word used to turn off
-- hardware and disk
-- service requests after end of IOCB
statusAddr(4): WORD]; -- lo 16 bits of deviceStatus physical
-- addr in IOCB
TransferBlock: TYPE = MACHINE DEPENDENT RECORD [
loadParmsCmd(0): WORD, -- tells disk uCode to load the
-- transfer parameters
parmBlockAddr(1): WORD, -- lo 16 bits of parameter block
-- physical address of
-- in IOCB and 16 word aligned
transferCmd(2): WORD, -- tells disk uCode to do the transfer
jumpFinishCmd(3): WORD, -- tells disk uCode to jump to
-- the finish if there was an error
-- in the transfer
finishAddr(4): WORD, -- physical address of finish command
-- in this IOCB
sendStepCmd1(5): WORD, -- used to send post-step pulse
-- if necessary
stepCmdWd1(6): WORD,
sendStepCmd2(7): WORD, -- lowers step line to complete
-- step pulse
stepCmdWd2(8): WORD,
finishTransfer(9): FinishBlock]; -- end the transfer command
-- specification of hardware status
--| head |seek|track00|firmware|index|sector|SA1000|not |write|over|CRC|verify|
--| select |done| | busy |found|found | |ready|fault| run| |error |
--| 8421|8 4 2 1 | 8 4 2 1 | 8 4 2 1 |
--| 1|421|4 2 1 | 4 2 1 | 4 2 1 | 4 2 1 |
--| head |seek|track00|firmware|index|sector|SA1000|not |write|over|CRC|verify|
--| select |done| | busy |found|found | |ready|fault| run| |error |
DDCHardwareBits: TYPE = MACHINE DEPENDENT RECORD [
nHeadSelected(0:0..4): [0..32), -- inverted version of head selected
seekComplete (0:5..5): BOOLEAN,
track00 (0:6..6): BOOLEAN,
firmwareBusy (0:7..7): BOOLEAN,
indexFound (0:8..8): BOOLEAN,
sectorFoundOrLabelDataTag (0:9..9): BOOLEAN,
driveIsSA1000(0:10..10): BOOLEAN,
driveNotReady(0:11..11): BOOLEAN,
writeFault (0:12..12): BOOLEAN,
overrun (0:13..13): BOOLEAN,
CRCError (0:14..14): BOOLEAN,
verifyError (0:15..15): BOOLEAN];
-- specification of device status
-- | last |----|seek|track00|firmware|index|sector|memory|not |write|over|CRC|verify|
-- | field| |done| | busy |found|found | fault|ready|fault| run| |error |
-- | 84 21|8 4 2 1 | 8 4 2 1 | 8 4 2 1 |
-- | 1|4 21|4 2 1 | 4 2 1 | 4 2 1 | 4 2 1 |
-- | last |----|seek|track00|firmware|index|sector|memory|not |write|over|CRC|verify|
-- | field| |done| | busy |found|found | fault|ready|fault| run| |error |
DDCStatusBits: TYPE = MACHINE DEPENDENT RECORD [
lastField (0:0..1): [0..4), -- = number of last field processed
unused2To4 (0:2..4),
seekComplete (0:5..5): BOOLEAN,
track00 (0:6..6): BOOLEAN,
firmwareBusy (0:7..7): BOOLEAN,
indexFound (0:8..8): BOOLEAN,
sectorFoundOrLabelDataTag (0:9..9): BOOLEAN,
memoryFault (0:10..10): BOOLEAN,
driveNotReady(0:11..11): BOOLEAN,
writeFault (0:12..12): BOOLEAN,
overrun (0:13..13): BOOLEAN,
CRCError (0:14..14): BOOLEAN,
verifyError (0:15..15): BOOLEAN];
-- Types of Operations allowed on each field
FieldOperation: TYPE = MACHINE DEPENDENT {noop, read, write, verify};
-- types of seek blocks used. One may either do nothing in the IOCB (used if there
-- is nothing to do or had a client error), perform a Seek but not wait for Seek
-- complete, send one step pulse and wait for SeekComplete before returning or
-- do no Seek at all, find sector zero on the present track instead.
SeekType: TYPE = {
dummyIOCB, seek, step, findSA4000Sector0, findSA1000Sector0, plainTransfer};
-- One may either follow a seek operation with a step of the read/write heads to
-- a cylinder or not.
TransferType: TYPE = {noStep, doStep};
END....