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
 
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
 
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.