DDC.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Forrest on: March 31, 1981 8:42 AM
Russ Atkinson (RRA) February 19, 1985 3:29:55 pm PST
Doug Wyatt, February 22, 1985 5:02:48 pm PST
Definitions for the Dandelion Disk Controller.
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
DiskFace USING [Label],
SA4000Face USING [Command, Operation, Status];
DDC: DEFINITIONS
= BEGIN
Base: TYPE = LONG BASE POINTER;
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): Base RELATIVE POINTER
TO ChannelCommand,
seekCommand(34): SeekBlock,
transferCommand(52): TransferBlock,
countThisStage(66): CARDINAL, -- # pages for this stage
label(67): DiskFace.Label,
unusedLabel(77): LONG CARDINAL ← 0 -- must follow label
];
ChannelCommand: TYPE; -- never used, just something to point at
IOCBshortPtr: TYPE = 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): 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
];
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 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 |
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
];
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 |
FieldOperation: TYPE = MACHINE DEPENDENT {noop, read, write, verify};
Types of Operations allowed on each field
SeekType: TYPE = {
dummyIOCB, seek, step, findSA4000Sector0, findSA1000Sector0, plainTransfer
};
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.
TransferType: TYPE = {noStep, doStep};
One may either follow a seek operation with a step of the read/write heads to a cylinder or not.
END.