*----------------------------------------------------------- Title[DiskDefs.mc...November 23, 1982 10:08 AM...Taft]; *** Pilot-only version *** *----------------------------------------------------------- *----------------------------------------------------------- * R-register assignments *----------------------------------------------------------- SetRMRegion[DiskRegs]; RVN[KIOCB]; * IOCB address RVN[KDataLo]; * Address of end of data block RVN[KDataHi]; RVN[Sector]; * sector counter RVN[MaxSectors]; * maximum number of sectors expected RVN[KPtr]; * command block pointer RVN[KAddr]; * disk address (or parts thereof) RVN[KCmmd]; * disk command (hardware) RVN[DskMAddr]; * memory address for data RVN[KStatus]; * disk software status RVN[KSelect]; * [0..3] zero (tagDrive) * [4] one iff sectors do not evenly divide the disk * [5] unused * [6..10] zero (tagSubSector, tagLoadSubSector) * [11] one tagSelectDrive * [12..15] currently addressed drive RV[K400, 400]; * constant 400 RVN[KTemp0]; RVN[KTemp1]; RVN[KTemp2]; RVN[KTemp3]; *----------------------------------------------------------- * Device assignments *----------------------------------------------------------- Device[DiskControl, 10]; * control register (output) Device[DiskMuff, 11]; * muffler and wakeup control (output); * muffler data in bit 15 (input) Device[DiskData, 12]; * disk read/write data (input/output); * must be selected to enable WrFifoTW Device[DiskRam, 13]; * format ram (output) Device[DiskTag, 14]; * tag bus (output) *----------------------------------------------------------- * Muffler addresses, as viewed by controller. * Add 2000 to produce normal (system-wide) muffler addresses. *----------------------------------------------------------- MC[muffsState, 0]; * Group of 20 controller state mufflers * MC[muffTempSense, muffsState, 0]; MC[muffIndexTW, muffsState, 1]; MC[muffSectorTW, muffsState, 2]; MC[muffSeekTagTW, muffsState, 3]; MC[muffRdFifoTW, muffsState, 4]; MC[muffWrFifoTW, muffsState, 5]; * MC[muffReadData, muffsState, 6]; * MC[muffWriteData, muffsState, 7]; * MC[muffEnableRun, muffsState, 10]; * MC[muffDebugMode, muffsState, 11]; * MC[muffRdOnlyBlock', muffsState, 12]; * MC[muffWriteBlock', muffsState, 13]; * MC[muffCheckBlock', muffsState, 14]; * MC[muffActive, muffsState, 15]; MC[muffSelect.0, muffsState, 16]; MC[muffSelect.1, muffsState, 17]; MC[muffsStatus, 20]; * Group of 20 drive and error status mufflers * MC[muffSeekInc, muffsStatus, 0]; * MC[muffHeadOvfl, muffsStatus, 1]; * MC[muffDevCheck, muffsStatus, 2]; * MC[muffNotSelected, muffsStatus, 3]; * MC[muffNotOnLine, muffsStatus, 4]; MC[muffNotReady, muffsStatus, 5]; * MC[muffSectorOvfl, muffsStatus, 6]; MC[muffFifoUnderflow, muffsStatus, 7]; MC[muffFifoOverflow, muffsStatus, 10]; * MC[muffReadDataErr, muffsStatus, 11]; * = compare error usually * MC[muffReadOnly, muffsStatus, 12]; * MC[muffCylOffset, muffsStatus, 13]; * MC[muffIOBParityErr, muffsStatus, 14]; * MC[muffFifoParityErr, muffsStatus, 15]; MC[muffWriteError, muffsStatus, 16]; MC[muffReadError, muffsStatus, 17]; MC[muffsRam, 40]; * Format Ram address and data MC[muffsTag, 60]; * Tag bus to drive MC[muffsFifo, 100]; * Fifo control mufflers *----------------------------------------------------------- * Control bits: output to DiskMuff register *----------------------------------------------------------- MC[clearCompareErr, 20000]; * clear CompareErr flipflop MC[setCheckSumErr, 10000]; * set ReadDataErr flipflop MC[clearIndexTW, 4000]; * clear IndexTW MC[clearSectorTW, 2000]; * clear SectorTW MC[clearSeekTagTW, 1000]; * clear SeekTagTW MC[clearErrors, 400]; * clear error flipflops * MC[muffAddr, 377]; * muffler address MC[clearAllTWs, clearIndexTW, clearSectorTW, clearSeekTagTW]; MC[clearAll, clearAllTWs, clearErrors]; *----------------------------------------------------------- * Control bits: output to DiskControl register *----------------------------------------------------------- MC[clearEnableRun, 2000]; * clear EnableRun MC[debugMode, 1000]; * set DebugMode if 1, clear if 0 MC[blockTilIndex, 400]; * set BlockTilIndex if 1, clear if 0 * MC[commands, 377]; * disk commands: 4 2-bit bytes, * * one per block, indicating: MC[commandWrite, 1]; MC[commandCompare, 2]; MC[commandRead, 3]; *----------------------------------------------------------- * Control bits: output to DiskTag register *----------------------------------------------------------- MC[tagDrive, 100000]; MC[tagCylinder, 40000]; MC[tagHead, 20000]; MC[tagControl, 10000]; MC[tagBus, 7777]; * TagBus interpretation for DriveTag: * MC[tagSubSector, 1700]; * subsector count MC[tagLoadSubSector, 40]; * load subsector for currently-addressed drive MC[tagSelectDrive, 20]; * select the specified drive MC[tagDriveNumber, 17]; * drive number * TagBus interpretation for CylinderTag: * MC[tagCylinderNumber, 7777]; * TagBus interpretation for HeadTag: * MC[tagOffset, 200]; * offset head position * MC[tagOffsetDirection, 100]; * direction of offset * MC[tagHeadNumber, 77]; * TagBus interpretation for ControlTag: MC[tagAltoLeader, 4000]; * search for Alto Trident sync pattern * MC[tagStrobeEarly, 1000]; * MC[tagStrobeLate, 400]; MC[tagWrite, 200]; MC[tagRead, 100]; * MC[tagResetHAR, 20]; MC[tagDiskReset, 10]; * reset errors latched in the drive MC[tagHeadSelect, 4]; * turn on selected head for read/write MC[tagReZero, 2]; * restore disk to cylinder 0 * MC[tagHeadAdvance, 1]; * increment head address register *----------------------------------------------------------- * Pilot disk-related data structures *----------------------------------------------------------- * Note: the default initializations in the following record definitions * indicate values that must be supplied by the software. * ControllerStatusBlock: TYPE = MACHINE DEPENDENT RECORD [ * next is interpreted only if it is odd. When an error occurs, microcode * makes next even, such that (next+1) points to the IOCB that suffered * the error. Disk activity thus freezes until the software resets next. MC[CSB.next, DiskCSB, 0]; * next: POINTER TO IOCB, MC[CSB.interruptMask, DiskCSB, 1]; * interruptMask: CARDINAL, MC[CSB.drive, DiskCSB, 2]; * drive: CARDINAL, * If cylinder is negative, the next command will initiate a restore. MC[CSB.cylinder, DiskCSB, 3]; * cylinder: CARDINAL, * ... ]; -- Other stuff not used by microcode * -- IOCBs must be odd-word aligned! * IOCB: TYPE = MACHINE DEPENDENT RECORD [ MC[IOCB.next, 0]; * next: POINTER TO IOCB, * seal is zeroed when command is done; this is how software detects completion MC[IOCB.seal, 1]; * seal: CARDINAL ← 125377B, MC[IOCBSealValue, 125377]; MC[IOCB.drive, 2]; * drive: CARDINAL, -- not presently used * pageCount is decremented after each page successfully transferred. * Thus pageCount=0 upon completion indicates that no errors occurred. MC[IOCB.pageCount, 3]; * pageCount: CARDINAL, MC[IOCB.command, 4]; * command: DiskCommand: * diskAddress is incremented after each page successfully transferred, and * copied into diskHeader for checking purposes. After a header read, * diskHeader contains the header read from the disk. MC[IOCB.diskAddress, 5]; * diskAddress: DiskAddress, MC[IOCB.diskHeader, 7]; * diskHeader: DiskAddress, MC[IOCB.headerPtr, 11]; * headerPtr: LONG POINTER ← @iocb.diskHeader, MC[IOCB.headerECC, 13]; * headerECC: LONG CARDINAL, MC[IOCB.headerStatus, 15]; * headerStatus: DiskStatus, * labelPtr should point to IOCB.diskLabel when checking or writing so that * updated values are used during runs of pages. During checking, the first * 8 words of the label are checked and the last 2 are read. MC[IOCB.labelPtr, 16]; * labelPtr: LONG POINTER ← @iocb.diskLabel, MC[IOCB.labelECC, 20]; * labelECC: LONG CARDINAL, MC[IOCB.labelStatus, 22]; * labelStatus: DiskStatus, * dataPtr is incremented by 400B after each page successfully transferred, * if command.incrementDataPointer = TRUE. MC[IOCB.dataPtr, 23]; * dataPtr: LONG POINTER, MC[IOCB.dataECC, 25]; * dataECC: LONG CARDINAL, MC[IOCB.dataStatus, 27]; * dataStatus: DiskStatus, * Microcode updates this copy of the label after each page successfully * transferred. IOCB.labelPtr should point here during checking and writing. MC[IOCB.diskLabel, 30]; * diskLabel: PilotDisk.Label ]; MC[sizeIOCB, 42]; * Pilot standard disk address * DiskAddress: TYPE = MACHINE DEPENDENT RECORD [ * cylinder: CARDINAL, * head, sector: [0..377B]]; * Dorado disk command (hardware format except for incrementDataPtr) * Action: TYPE = {none, write, check, read}; * DiskCommand: TYPE = MACHINE DEPENDENT RECORD [ * incrementDataPtr: BOOLEAN, * unused: [0..177B] ← 0, * header: Action, * label: Action, * data: Action, * unused: Action ← none ]; * DiskStatus: TYPE = MACHINE DEPENDENT RECORD [ * -- following are hardware conditions reported directly from the controller: * * seekInc: BOOLEAN, * * headOvfl: BOOLEAN, * * devCheck: BOOLEAN, * * notSelected: BOOLEAN, * * notOnLine: BOOLEAN, * * notReady: BOOLEAN, MC[DS.sectorOvfl, 1000]; * sectorOvfl: BOOLEAN, * * fifoUnderflow: BOOLEAN, * * fifoOverflow: BOOLEAN, MC[DS.checkErr, 100]; * checkErr: BOOLEAN, -- = ReadDataErr * * readOnly: BOOLEAN, * * cylOffset: BOOLEAN, * * iobParityErr: BOOLEAN, * * fifoParityErr: BOOLEAN, * -- following are microcode-detected conditions: MC[DS.eccErr, 2]; * eccErr: BOOLEAN, MC[DS.sectorSearchErr, 1]; * sectorSearchErr: BOOLEAN ]; * Excerpt from Pilot Label record, showing fields that must be * modified by the microcode during runs of pages. * Label: TYPE = MACHINE DEPENDENT RECORD [ * * fileID: File.ID, MC[Lab.filePageLo, 5]; * filePageLo: CARDINAL ], -- increment this MC[Lab.filePageHi, 6]; * filePageHi: [0..177B], * * pad1: [0..77B], * * fileFlags: [0..7B], -- zero these * * type: File.type, MC[Lab.bootChainLink, 10]; * bootChainLink: DiskAddress]; MC[sizeHeader, 2]; MC[sizeLabel, 12]; MC[sizeData, 400]; % The Dorado Trident disk is formatted as 815 cylinders, 5 heads, 28 sectors. We use only 28 of the usable 29 sectors, because addressing the 29th is somewhat tricky. For compatibility with partitioning of Dorado disks for Alto emulation (one partition on each surface of the disk), we emulate a disk that has a different shape from the real disk: 4075 (=5*815) cylinders, 1 head, 28 sectors. This is so that a partition occupies a contiguous interval of virtual addresses under Pilot's virtual-to-real disk address mapping, which increments heads before cylinders. Thus: real cylinder = emulated cylinder MOD 815 real head = emulated cylinder / 815 real sector = emulated sector Note that the head number in the emulated disk address is ignored. The reason the microcode has to know about all this garbage is that it needs to be able to increment the disk address during runs of pages. % * Disk format parameters: MC[nCylinders, 1457]; * = 815 MC[nSectors, 34]; * = 28 Set[staggerSectors, 1]; * Stagger sectors on adjacent cylinders