SA4000HeadDLionConstants.mesa - Prototype IOCBs, etc.
Copyright © 1985 by Xerox Corporation. All rights reserved.
DDavies: June 18, 1980 12:55 PM
Forrest: February 11, 1981 2:12 PM
Russ Atkinson (RRA) February 19, 1985 3:31:00 pm PST
Doug Wyatt, February 22, 1985 5:06:27 pm PST
DIRECTORY
DDC USING [Base, DataBlock, FieldOperation, FinishBlock, HeaderBlock, IOCB, LabelBlock, MiscCommandBlock, ParameterBlock, SeekBlock, SeekType, TransferBlock, TransferType],
SA4000Face USING [Command, Operation];
SA4000HeadDLionConstants: DEFINITIONS
= BEGIN OPEN DDC;
nil: DDC.Base RELATIVE POINTER = LOOPHOLE[0];
various offsets into the IOCB's are needed
zeroIOCB is used to caculate them
The offsets have to be caculated in two stages due to a compiler bug.
zeroIOCB: PRIVATE POINTER TO IOCB = LOOPHOLE[0];
zeroOp: PRIVATE POINTER TO SA4000Face.Operation = @zeroIOCB.operation;
clientHeaderOffset: PRIVATE CARDINAL = LOOPHOLE[@zeroOp.clientHeader];
diskHeaderOffset: PRIVATE CARDINAL = LOOPHOLE[@zeroOp.diskHeader];
statusAddr: PRIVATE WORD = LOOPHOLE[@zeroOp.deviceStatus--.a--];
Note; deviceStatus.b is set to GetHardwareBits[] during Poll
zeroSB: PRIVATE POINTER TO SeekBlock = @zeroIOCB.seekCommand;
entryOffset: PUBLIC CARDINAL = LOOPHOLE[@zeroSB.sendWaitCmd];
negDistanceAddr: PRIVATE CARDINAL = LOOPHOLE[@zeroSB.negDistance];
sendCtl1Addr: PRIVATE CARDINAL = LOOPHOLE[@zeroSB.sendCtl1];
sendCtl2Addr: PRIVATE CARDINAL = LOOPHOLE[@zeroSB.sendCtl2];
zeroTC: PRIVATE POINTER TO TransferBlock = @zeroIOCB.transferCommand;
finishTransferAddr: PRIVATE CARDINAL = LOOPHOLE[@zeroTC.finishTransfer];
loadParmsCmdAddr: PRIVATE CARDINAL = LOOPHOLE[@zeroTC.loadParmsCmd];
zeroTP: PRIVATE POINTER TO ParameterBlock = @zeroIOCB.transferParm;
sectorCountAddr: PRIVATE CARDINAL = LOOPHOLE[@zeroTP.sectorCount];
labelOffset: PRIVATE CARDINAL = LOOPHOLE[@zeroIOCB.label];
IOCBDone: PRIVATE FinishBlock = [
finishCmd: 6, nextIOCB: nil, transferMask: 0, stopCmd: 2000B, statusAddr: statusAddr];
Array Constants
used to find the header operation in the command given in the IOCB
(packing this increases the code size)
HeaderOperation: ARRAY SA4000Face.Command OF FieldOperation = [
verify, -- vv
verify, -- vvr
verify, -- vvw
verify, -- vvv
verify, -- vw
verify, -- vww
verify, -- vr
verify, -- vrr
verify, -- vrw
verify, -- vrv
read, -- rv
read, -- rvr
read, -- rvw - illegal
read, -- rvv
read, -- rw - illegal
read, -- rww - illegal
read, -- rr
read, -- rrr
read, -- rrw - illegal
read, -- rrv
write, -- w
write  -- www
];
used to find the label operation in the command given in the IOCB
LabelOperation: ARRAY SA4000Face.Command OF FieldOperation = [
verify, -- vv
verify, -- vvr
verify, -- vvw
verify, -- vvv
write, -- vw
write, -- vww
read, -- vr
read, -- vrr
read, -- vrw
read, -- vrv
verify, -- rv
verify, -- rvr
verify, -- rvw - illegal
verify, -- rvv
write, -- rw - illegal
write, -- rww - illegal
read, -- rr
read, -- rrr
read, -- rrw - illegal
read, -- rrv
write, -- w
write  -- www
];
used to find the data operation in the command given in the IOCB
DataOperation: PACKED ARRAY SA4000Face.Command OF FieldOperation = [
noop, -- vv
read, -- vvr
write, -- vvw
verify, -- vvv
noop, -- vw
write, -- vww
noop, -- vr
read, -- vrr
write, -- vrw
verify, -- vrv
noop, -- rv
read, -- rvr
write, -- rvw - illegal
verify, -- rvv
noop, -- rw - illegal
write, -- rww - illegal
noop, -- rr
read, -- rrr
write, -- rrw - illegal
verify, -- rrv
write, -- w
write  -- www
];
used to compose the header portion of the IOCB parameter block
headerOpBlock: ARRAY FieldOperation OF HeaderBlock = [
noop the header = read, ignore errors
[headerCmd: 2060B, headerCnt: 1, headerAddr: clientHeaderOffset,
headerQuitMsk: 0, headerLoopMsk: 0],
read the header
[headerCmd: 2060B, headerCnt: 2, headerAddr: diskHeaderOffset,
headerQuitMsk: 36B, headerLoopMsk: 0],
write the header
[headerCmd: 2073B, headerCnt: 2, headerAddr: clientHeaderOffset,
headerQuitMsk: 34B, headerLoopMsk: 0],
verify the header
[headerCmd: 2062B, headerCnt: 1, headerAddr: clientHeaderOffset,
headerQuitMsk: 34B, headerLoopMsk: 3]];
used to compose the label portion of the IOCB parameter block
labelOpBlock: ARRAY FieldOperation OF LabelBlock = [
noop the label = verify, ignore errors
[labelCmd: 2062B, labelCnt: 11, labelAddr: labelOffset, labelMsk: 0],
read the label
[labelCmd: 2060B, labelCnt: 12, labelAddr: labelOffset, labelMsk: 36B],
write the label
[labelCmd: 2073B, labelCnt: 12, labelAddr: labelOffset, labelMsk: 34B],
verify the label
[labelCmd: 2062B, labelCnt: 11, labelAddr: labelOffset, labelMsk: 37B]];
used to compose the data portion of the IOCB parameter block
dataOpBlock: ARRAY FieldOperation OF DataBlock = [
noop the data = verify, ignore errors
[dataCmd: 2062B, dataCnt: 255, dataPgNum: 0, dataMsk: 0],
read the data
[dataCmd: 2060B, dataCnt: 256, dataPgNum: 0, dataMsk: 36B],
write the data
[dataCmd: 2073B, dataCnt: 256, dataPgNum: 0, dataMsk: 34B],
verify the data
[dataCmd: 2062B, dataCnt: 255, dataPgNum: 0, dataMsk: 37B]];
stop controller between fields, leave directionIn set in case a post-step is needed
miscCmdBlock: ARRAY BOOLEAN OF MiscCommandBlock = [
[freezeCmd: 2140B, findSectMkCmd: 2046B], -- find sector mark on SA400x type drive
[freezeCmd: 2140B, findSectMkCmd: 2040B]]; -- no sector mark on SA100x type drive
seekCmdBlock: ARRAY SeekType OF SeekBlock = [
dummyIOCB - This is needed if there is nothing to do in this IOCB except send an interrupt back to the calling mesa process. For uniformity, we make this like a step IOCB except the control words sent cause no action in the controller. A benefit of this is that both the Incr-Skip-if-zero and TstStatus op codes are executed. The first has the needed side effect of clearing the microcode's UField status register which both initializes it and clears any old field numbers. The second has the side effect of clearing the UStatus register of old error flags. In this way, the final deviceStatus posted will reflect the status of this operation only.
[negDistance: -1,
sendWaitCmd: 100000B, -- send control word op code
waitCmd: 2042B, -- wait for Seek complete
sendCtl1: 100000B, -- send control word op code
controlWd1: 2040B, -- controller just keeps FirmwareEnable
and service request on
sendCtl2: 100000B, -- send control word op code
controlWd2: 2040B,
inrNegDistance: 0,
negDistanceAddr: negDistanceAddr,
jumpToStep: 2,
sendCtlAddr: 0, -- should never take this branch since -1 +1=0
initRegsCmd: 7, -- puts ICOBDone bit into UField and clears UStatus
initRegsParm: 0, -- a dummy parameter
finishSeek: IOCBDone],
IOCB to do a real seek command
[negDistance: 0, -- negative of number of cylinders to cross,
filled in when built
sendWaitCmd: 100000B, -- send control word op code
waitCmd: 2042B, -- wait for Seek complete
sendCtl1: 100000B, -- send control word op code
controlWd1: 2240B, -- word to raise step line, direction filled in later
sendCtl2: 100000B, -- send control word op code
controlWd2: 2040B, -- word to lower step line, direction filled in later
inrNegDistance: 0, -- incr and skip if zero op code
negDistanceAddr: negDistanceAddr, -- this distance filled in later (when IOCB built)
jumpToStep: 2, -- jump op code, only used when more step pulses
to be sent
sendCtlAddr: sendCtl1Addr, -- address of sendCtl1 word
initRegsCmd: 7, -- puts ICOBDone bit into UField and clears UStatus
initRegsParm: 0, -- a dummy parameter
finishSeek: IOCBDone], -- all pulses sent, so finish up
step over one cylinder, used when recalibrating
[negDistance: -1, -- negative of number of cylinders to cross
sendWaitCmd: 100000B, -- send control word op code
waitCmd: 2042B, -- wait for Seek complete
sendCtl1: 100000B, -- send control word op code
controlWd1: 2240B, -- word to raise step line, direction filled in later
sendCtl2: 100000B, -- send control word op code
controlWd2: 2042B, -- word to lower step line and wait for
SeekComplete, direction filled in later
inrNegDistance: 0, -- incr and skip if zero op code
negDistanceAddr: negDistanceAddr, -- this distance filled in later (when IOCB built)
jumpToStep: 2, -- jump op code, only used when more step pulses
to be sent
sendCtlAddr: sendCtl1Addr, -- address of sendCtl1 word
initRegsCmd: 7, -- puts ICOBDone bit into UField and clears UStatus
initRegsParm: 0, -- a dummy parameter
finishSeek: IOCBDone], -- all pulses sent, so finish up
series of commands used to find sector zero for the SA4000. It finds the index
mark, then counts 27 sectors from there.
The 28th sector coming up next will be sector zero. The SA1000 version just
finds the index mark.
[negDistance: -27, -- negative of number of cylinders to cross
sendWaitCmd: 100000B, -- send control word op code
waitCmd: 2042B, -- wait for Seek complete
sendCtl1: 100000B, -- send control word op code
controlWd1: 2044B, -- word to find index mark
sendCtl2: 100000B, -- send control word op code
controlWd2: 2046B, -- word to find the next sector mark
inrNegDistance: 0, -- incr and skip if zero op code
negDistanceAddr: negDistanceAddr, -- this count initialized above to -27
jumpToStep: 2, -- jump op code, only used when more sectors
to be found
sendCtlAddr: sendCtl2Addr, -- address of sendCtl2 word
initRegsCmd: 2, -- has side effect of clearing UStatus
initRegsParm: loadParmsCmdAddr, -- jump to start of transfer block of instructions
finishSeek: [0, nil, 0, 0, 0]],
find sector zero for the SA1000. This is quite simple in that we simply
find the index mark and return. This is not sufficient for the SA4000 since
its index and sector marks are coincident
[negDistance: 0, -- not used
sendWaitCmd: 100000B, -- send control word op code
waitCmd: 2042B, -- wait for Seek complete
sendCtl1: 100000B, -- send control word op code
controlWd1: 2044B, -- word to find index mark
sendCtl2: 2, -- jump op code
controlWd2: loadParmsCmdAddr, -- jump to start of transfer block now
inrNegDistance: 0, negDistanceAddr: 0, jumpToStep: 0, sendCtlAddr: 0, initRegsCmd: 0, initRegsParm: 0, finishSeek: [0, nil, 0, 0, 0]],
this is the seek command used when only a transfer is to be done. It does nothing
but wait for a SeekComplete before starting the transfer
[negDistance: 0, -- not used
sendWaitCmd: 100000B, -- send control word op code
waitCmd: 2042B, -- wait for Seek complete
sendCtl1: 2, -- jump op code
controlWd1: loadParmsCmdAddr, -- jump to start of transfer block now
sendCtl2: 0, controlWd2: 0, inrNegDistance: 0, negDistanceAddr: 0, jumpToStep: 0, sendCtlAddr: 0, initRegsCmd: 0, initRegsParm: 0, finishSeek: [0, nil, 0, 0, 0]]];
this are the two types of generic transfer blocks. The first is used when a run of pages continues on the next cylinder and a step command is needed. The second is used when either this transfer completes the run or the the run continues on this cylinder (it may have been broken because of file page label boundry).
transferCmdBlock: ARRAY TransferType OF TransferBlock = [ -- postStep/noPostStep
[loadParmsCmd: 5, -- load transfer paramters from parameter block
parmBlockAddr: sectorCountAddr, -- base of parameter block, must be 16 word aligned
transferCmd: 4000B, -- transfer run of pages op code
jumpFinishCmd: 2, -- jump op code
finishAddr: finishTransferAddr, -- finish command addr, execute this when error
sendStepCmd1: 2, -- jump op code
stepCmdWd1: finishTransferAddr, -- finish command addr, execute when xfr flawless
sendStepCmd2: 0, stepCmdWd2: 0,
finishTransfer: IOCBDone],
this type of transfer block is used when the heads must be moved after the transfer to
set up the next transfer (the run crossed a cylinder boundry)
[loadParmsCmd: 5, -- load transfer paramters from parameter block
parmBlockAddr: sectorCountAddr, -- base of parameter block, must be 16 word aligned
transferCmd: 4000B, -- transfer run of pages op code
jumpFinishCmd: 2, -- jump op code
finishAddr: finishTransferAddr, -- address of finish command
sendStepCmd1: 100000B, -- send control word op code
stepCmdWd1: 2340B, -- raise the step line, direction=In
sendStepCmd2: 100000B, -- send control word op code
stepCmdWd2: 2140B, -- lower the step line, direction=In
finishTransfer: IOCBDone]];
Sector counts to use when formatting SA4000's
Only tracks can be formated on the SA1000, but on 4000 individual pages can be done.
The command sets up a wait for index mark, then counts n-1 sector marks.
To format sector 0 or 1 one has to go all the way around
SA4000SectorDistance: ARRAY [0..28) OF INTEGER = [
-27, -28, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15,
-16, -17, -18, -19, -20, -21, -22, -23, -24, -25, -26];
END.