% *** *** *** *** *** *** *** Revision 1 March 26, 1980 *** *** *** *** *** *** *** **************************************************************************************** *** EDRDCD.mc : Rigid Disk Controller Diagnostic microcode *** Purpose : This test exercises the Rigid Disk Controller and the Rigid Disk. *** Minimum Hardware : Standard 4 CPU boards, one 96K Storage Module, an RDC disk drive and a RDC Controller Module. *** Approximate Run Time : One hour if default parameters are used. *** Written by Jim Katsiroumbas, Obtained March 14, 1980 *** Modified by : T. Henning, March 26, 1980 Added title page and reformated for readability. Renamed R registers to delete the RDC prefix so that names on Midas are more readable. However, those R registers are doubly defined so that they can still be referred to by the RDC prefix. Added the Extract routine to extract the last IOCB cylinder, head, and sector info. *** WARNING: EDRDCD is not compatible with Super which runs three controllers at once. To run Super, it is necessary to get RDCD, not EDRDCD. *** NOTE: EDRDCD assembly procedure: 1) micro/o/u EDRDC 2) micro/o/u EDRDCD 3) microd EDRDC EDRDCD **************************************************************************************** **************************************************************************************** * Phases Description: * Phase 0: Seek only phase. Seek all selected sectors, heads, cylinders, and disks. * Phase 1: Header verify, label write, data write. Do this for all selected sectors, heads, cylinders, disks. * Phase 2: Header verify, label read, data read. Do this for all selected sectors, heads, cylinders, disks. * Phase 3: Header verify, label write, data write, then do command pointed to by command pointer. Do this for all selected sectors, heads, cylinders, disks. * Phase 4: Do command in PHASE4COMMAND register. Do this for all selected sectors, heads, cylinders, disks. * Phase 5: Header write, label nop, data nop. Do this for all selected sectors, heads, cylinders, disks. * Phase 6: Header verify, label nop, data nop. Do this for all selected sectors, heads, cylinders, disks. **************************************************************************************** **************************************************************************************** * Special Midas Screen Feature: * * The EDRDCD test has many parameters useful to the operator at different stages of * testing. Since they would clutter up the Midas screen if they all appeared at the * same time, the screen is controlled to give the more important data as it is needed. * * Essentially, there are two screens available: the DEBUG screen and the SET screen. * * 1) The DEBUG screen will display the last disk, cylinder, head, and sector * as specified in the last IOCB that was involved in an error breakpoint. * To get this screen, bug Read-Cmds, then bug RDCDEBUG. * * 2) The SET screen displays parameters for running the EDRDCD test. * To get this screen, bug Read-Cmds, then bug RDCSET. * **************************************************************************************** **************************************************************************************** * Theory of Operation: * * The D(0) rigid disk is the Shugart SA4000 rigid disk. It has 312 cylinders, 8 heads, * and 28 sectors per track. Each sector has 2 words of Header, 8 words of Label, * and 256 words of Data. The EDRDCD diagnostic code controls the RDC task through * the use of Controller Status Blocks (CSB's) and Input Output Controller Blocks (IOCB's). * The command and status blocks are executed by the EDRDC firmware driver which has * control of the rigid disk drive. * **************************************************************************************** **************************************************************************************** * SPECIAL FEATURES: * Data Generation: Data generation and checking are controlled by 'DTYPE' and 'SEED'. If DTYPE=0, then the data pattern will be SEED, 2 times SEED, 3 times SEED, 4 times SEED, 5 times SEED, etc. Example: SEED=0 generates all zeros pattern; SEED=1 generates 1,2,3,4,5...; SEED=5 generates 5,10,15,20,15... If DTYPE=1, then the data pattern will be SEED, 0, SEED, 0, SEED, 0, etc. As data blocks are being generated, the first block uses 'SEED' for data generation, but the second block uses the two's complement of 'SEED' for data generation, the third block uses 'SEED' for data generation, the fourth block uses the two's complement of 'SEED' for data generation, etc. The data starts at VM 10000. * The cylinders to be ignored in the test may be written into VM 310, 311, 312, and 313. * PHASE4COMD: The special command as indicated in PHASE4COMD is executed in phase 4. A 3 digit code is to be entered: The most significant digit controls the Header: 2 for write, 1 for read and verify The middle digit controls the Label: 4 for write, 2 for read, 1 for verify, 0 for nop The least significant digit controls the Data: 4 for write, 2 for read, 1 for verify, 0 for nop Thus a 112 is verify Header, verify Label, and read Data. It is not possible to execute all combinations of 3 digits, the user is responsible for putting in a correct and logical code. * RANDOMC: In each phase, the operation is done on random cylinders, then the phase is done sequentially to all selected cylinders. RANDOMC is the number of random operations to be done. A zero in RANDOMC indicates no random operations. The register RANDOM indicates how many random operations are left. **************************************************************************************** **************************************************************************************** * BREAKPOINTS TABLE: * DATAERROR: THIS IS A DIAGNOSTIC DETECTED ERROR WITH NO ERROR REPORTED FROM THE CONTROLLER OR THE FIRMWARE.A REG 'EXPECTED' HAS THE EXPECTED DATA,'OBSERVED' HAS THE BAD DATA,AND 'ADDRESS' HAS THE ADDRESS OF THE BAD DATA.THIS CAN BE EITHER IN THE IOCB OR THE MEMORY BLOCK.THE REG 'BLOCK' POINTS TO THE FIRST WORD OF THE BLOCK.TO GO ON TO CHECK THE NEXT BLOCK, BUG 'CONTINUE'. * DEVICEERROR: THIS IS A CONTROLLER ERROR DETECTED BY THE CONTROLLER OR THE FIRMWARE. A REG 'ERRORF' CONTAINS THE STATUS AND OPS WORD OF THE CSB CONTAINS THE ERROR CODE. THE 'OLD IOCB LINK' OF THE CSB POINTS TO THE IOCB.TO RETRY THE CHAIN OF IOCB'S, BUG 'CONTINUE'. * TIMERHALT: A DISK OPERATION WAS STARTED BUT NEVER COMPLETED.BUG 'CONTINUE' AND THE PROGRAM WILL HALT AT 'DEVICEERROR'.BUG 'CONTINUE' AGAIN AND THE OPERATION WILL BE RETRYED. * NOIDHERE: THE ID FOR THE DEVICE WAS NOT FOUND.IF THE DEVICE IS THE FIRST ONE IN THE CHAIN THEN A REGISTER 'EXPECTED' CONTAINS WHAT YOU SHOULD HAVE RECEIVED AND 'OBSERVED' CONTAINS WHAT YOU DID RECEIVE. TO RETRY, BUG 'CONTINUE'. * IDER: THE ID FOUND WAS NOT THE SAME AS THE ONE EXPECTED. TO RETRY, BUG 'CONTINUE'. * NOPHASE: THE VALUE IN 'RUNPHASE' IS NOT IN THE VALID RANGE. SET 'RUNPHASE' AGAIN. * BADPHASE: THE VALUE IN 'PHASE' IS NOT IN THE VALID RANGE AFTER IOCB'S HAVE EXECUTED. * PASSED-EDRDCD-TEST: ALL PHASES SELECTED WERE RUN FOR THE NUMBER OF PASSES SPECIFIED IN 'PASSCOUNT'. BUG 'CONTINUE' TO START ANOTHER PASS. * SETPARAMETERS: THIS IS TO ALLOW YOU TO CHANGE PARAMETERS.THEN BUG 'CONTINUE'. **************************************************************************************** **************************************************************************************** * CONTROLLER STATUS BLOCK (CSB) DEFINITIONS: * * NOTE: The CSB block begins at virtual memory address 300 in EDRDCD. VM 300, WORD 00: IOCB LINK VM 301, WORD 01: SYNCH VM 302, WORD 02: CURRENT STATUS VM 303, WORD 03: OPERATIONAL STATUS WORD (bits 14-17, get STP error code on error) VM 304, WORD 04: OLDDISK ADDRESS, DISK 1, (-1, RECAL NECESSARY) (bit 0, seek in progress, sip) VM 305, WORD 05: OLDDISK ADDRESS, DISK 2, (-1, RECAL NECESSARY) (bit 0, seek in progress, sip) VM 306, WORD 06: OLDDISK ADDRESS, DISK 3, (-1, RECAL NECESSARY) (bit 0, seek in progress, sip) VM 307, WORD 07: OLDDISK ADDRESS, DISK 4, (-1, RECAL NECESSARY) (bit 0, seek in progress, sip) VM 310, WORD 10: FLAW CYLINDER, put in DISK(4MSB)/CYLINDER(8LSB) to be flawed VM 311, WORD 11: FLAW CYLINDER, put in DISK(4MSB)/CYLINDER(8LSB) to be flawed VM 312, WORD 12: FLAW CYLINDER, put in DISK(4MSB)/CYLINDER(8LSB) to be flawed VM 313, WORD 13: FLAW CYLINDER, put in DISK(4MSB)/CYLINDER(8LSB) to be flawed VM 317, WORD 17: OLD IOCB LINK **************************************************************************************** **************************************************************************************** * INPUT OUTPUT CONTROLLER BLOCK (IOCB) DEFINITIONS: * * NOTE: The first IOCB block begins at virtual memory address 3000 in EDRDCD. * Subsequent IOCB blocks follow every 40 locations. Thus the second IOCB * block starts at VM 3040. The last IOCB block executed is pointed by * CSB word 00 if it is nonzero. Otherwise, it is pointed to by CSB word 17, * if CSB word 00 is zero. WORD 00: DISK/CYCL ADDRESS SENT TO CONTROLLER (disk: 4 MSB, cylinder: 8 LSB) WORD 01: HEAD/SECTOR ADDRESS SENT TO CONTROLLER (head: 8 MSB, sector: 8 LSB) WORD 02: DISK/CYCL ADDRESS RECEIVED FROM CONTROLLER (disk: 4 MSB, cylinder: 8 LSB) WORD 03: HEAD/SECTOR ADDRESS RECEIVED FROM CONTROLLER (head: 8 MSB, sector: 8 LSB) WORD 04: LABEL START WORD 05: LABEL WORD 06: LABEL WORD 07: LABEL WORD 10: LABEL WORD 11: LABEL WORD 12: LABEL WORD 13: LABEL END WORD 14: IOCBLINK WORD 15: COMMAND WORD 16: DATA POINTER WORD 17: DATA POINTER WORD 20: STATUS WORD 21: SYNCH WORD 22: SYNDROME WORD 23: SYNDROME **************************************************************************************** **************************************************************************************** * REGISTER DEFINITIONS (Alphabetical): * ADDRESS: ADDRESS OF DATA. * BLOCK: POINTER TO CURRENT DATA BLOCK. * CHAIN: A ONE MEANS CHAIN IOCB'S. A ZERO MEANS USE ONLY ONE IOCB. * CMDPOINTER: A RING POINTER FOR PHASE3 WHICH POINTS TO A COMMAND LIST OF ALL THE DIFFERENT TYPES OF COMMANDS FOR THE DISK. THIS POINTER GETS BUMPED AFTER EACH PASS. * COMMAND: SHOWS YOU THE CURRENT COMMAND THE FIRMWARE HAS. * CYLE: ENDING CYCL ADDRESS RANGE 0 TO 311.(HAS TO BE>=TO STARTING.) * CYLINDERERROR: THE CYLINDER INVOLVED IN THE LAST IOCB THAT CAUSED AN ERROR BREAKPOINT. * CYLS: STARTING CYCL ADDRESS RANGE 0 TO 311. * DISKE: ENDING DISK ADDRESS RANGE 0 TO 3.(HAS TO BE>=TO STARTING.) * DISKERROR: THE DISK DRIVE INVOLVED IN THE LAST IOCB THAT CAUSED AN ERROR BREAKPOINT. * DISKS: STARTING DISK ADDRESS RANGE 0 TO 3. * DISKSAVE: IF NOT CHAINING, THIS HAS THE DISK/CYL ADDRESS OF THE CURRENT OPERATION. IF CHAINING, HAS THE DISK/CYL ADDRESS OF THE LAST IOCB IN THE CHAIN. * DISKSTATUS: SHOWS YOU CURRENT DISK STATUS. * DTYPE: USED FOR GENERATING AND CHECKING DATA BLOCKS. * ERRORF: CONTAINS THE DISK STATUS ON A DEVICE ERROR FOR THE FAILURE. * EXPECTED: DATA YOU EXPECTED. * HEADE: ENDING HEAD ADDRESS RANGE 0 TO 7.(HAS TO BE>=TO STARTING.) * HEADERROR: THE HEAD INVOLVED IN THE LAST IOCB THAT CAUSED AN ERROR BREAKPOINT. * HEADS: STARTING HEAD ADDRESS RANGE 0 TO 7. * HEADSAVE: IF NOT CHAINING, THIS HAS THE HEAD/SECTOR ADDRESS OF THE CURRENT OPERATION. IF CHAINING, HAS THE HEAD/SECTOR ADDRESS OF THE LAST IOCB IN THE CHAIN. * IOCBERROR: THE IOCB THAT WAS BEING EXECUTED WHEN AN ERROR BREAKPOINT OCCURRED. * MENDL: LOWER 16 BITS OF ENDING ADDRESS (HOW MUCH MEMORY TO USE FOR DATA BLOCKS.) * MSTARTL: LOWER 16 BITS OF STARTING ADDRESS OF MAIN MEMORY TO USE FOR DATA BLOCKS. THIS IS NORMALLY HEX ALIGNED BUT MAY BE QUAD ALIGNED. IF NOT, PROGRAM WILL NOT RUN!!!!! * MSTARTU: UPPER 8 BIT OF STARTING ADDRESS OF MAIN MEMORY TO USE FOR DATA BLOCKS. * NEWDISKADD: FOR DEBUGING PURPOSE. * NEWSECTOR: FOR DEBUGING PURPOSE. * NOCMDINC: A ONE IN HERE STOPS THE COMMAND POINTER FROM BEING BUMPED. * NODATAINC: A ONE IN HERE STOPS THE PROGRAM FROM CHANGING DATATYPE AND DATASEED AFTER EACH PASS. * NOHALT: A ONE MEANS DON'T HALT ON ANY BREAKPOINT EXCEPT FOR DEVICETIMEOUT. * NORATERR: A ONE MEANS DON'T HALT ON ANY RATE ERROR. * NORETRY: A ONE MEANS NO RETRY FOR READ, BUT RETRY WRITES FOREVER. A ZERO MEANS FOUR RETRIES FOR READS AND WRITES. * OBSERVED: DATA YOU OBSERVED. * OLDDISKADD: FOR DEBUGING PURPOSE. * OLDHEADSECTOR: FOR DEBUGING PURPOSE. * PASSCOUNT: COUNT OF HOW MANY PASSES TO RUN BEFORE STOPING AT 'PASSDONE'. * PHASE: SHOWS YOU WHICH PHASE IS RUNNING. * PHASE4COMD: USED IN PHASE4 TO RUN A SPECIAL COMMAND.(SUCH AS '111' WHICH IS HEADER VERIFY,LABLE VERIFY,DATA VERIFY). * PHASEDONE: FOR DEBUGING.TO FORCE PHASE TO TERMINATE, PUT A ONE IN HERE. * RANDOM: SHOWS YOU HOW MANY RANDOM OPERATIONS THAT ARE LEFT FOR THIS PHASE. * RANDOMC: SET THIS FOR HOW MANY RANDOM OPERATIONS TO RUN PER PHASE. * RUNPHASES: WHERE YOU SELECT WHICH PHASES TO RUN. * SECTORE: ENDING SECTOR ADDRESS RANGE 0 TO 33.(HAS TO BE>=TO STARTING.) * SECTORERROR: THE SECTOR INVOLVED IN THE LAST IOCB THAT CAUSED AN ERROR BREAKPOINT. * SECTORS: STARTING SECTOR ADDRESS RANGE 0 TO 33. * SEED: USED FOR GENERATING AND CHECKING DATA BLOCKS. * STP: SHOWS YOU STATE POINTER FOR FIRMWARE. * SUNKUP: USED FOR DEBUGGING. IF #0 THEN DON'T ISSUE COMMAND TO CONTROLLER UNLESS WE ARE ON SECTOR TO USE, SET A ONE IN REG THEN TYPE START2 AND BUG 'GO'. **************************************************************************************** **************************************************************************************** * Subroutine Description: * * CHKCMD: CHKCMD finds out if all commands are done. * CHKPHASE: CHKPHASE checks for phase completed. * DATAVFY: DATAVFY verifies the data and label depending on the current phase. * EXTRACT: EXTRACT finds the last IOCB and extracts the disk, cylinder, head, * and sector information. * HANDSHAKE: HANDSHAKE reads R register EXPECTED written by the RDC task saves it in NWW, * reset bits 15 and 17, then writes it back to EXPECTED. * INITIOCB: INITIOCB initializes the memory dedicated to IOCB's. * INITNEWPHASE: INITNEWPHASE reinitializes the IOCB's and the data buffer area in memory. * ISSUEBLK: ISSUEBLK issues RDC Data Blocks. * FILDATA: FILDATA fills the IOCB memory buffer area with the data pattern to be used. * MEMPUT: MEMPUT puts RDC Data into memory. * NEWPHASE: NEWPHASE selects the next phase to run. * RDCINIT: RDCINIT saves return link in SAVE2 and notifies the RDC Task code to initialize. * RDCINTR: RDCINTR uses SAVE2 return address to return to the RDCD Task (Task 0). * SETMAINT: SETMAINT set the maintenance panel to display the phase. * SRCADDR: SRCADDR shifts out 16 task numbers to the controller boards. * UPDTIOCB: UPDTIOCB updates the IOCB block. * UPDTCSB: UPDTCSB updates the CSB block with the new IOCB pointer, clears status, * and sets process wakeup. * WAKEUPWAIT: WAKEUPWAIT waits until the RDC responds or until it is timed out. **************************************************************************************** % **************************************************************************************** * INITIALIZATION: BUILTIN[INSRT,24]; INSRT[D0LANG]; NOMIDASINIT; TITLE[EDRDC DIAG PROGRAM March 26, 1980]; ********** Macros and Set Values: ********** SET[DIAGTASK,0]; SET[DISK,1]; SET[DISK1,2]; SET[DISK2,3]; SET[DISK3,4]; SET[DISK4,5]; SET[DISK5,10]; SET[DISK.1,LSHIFT[DISK,10]]; SET[DISK1.1,LSHIFT[DISK1,10]]; SET[DISK4.1,LSHIFT[DISK4,10]]; SET[RDCTASK,4]; SET[RPAGE,6]; SET[RPAGE1,7]; SET[RPAGE.1,LSHIFT[RPAGE,10]]; SET[RPAGE1.1,LSHIFT[RPAGE1,10]]; SET[DRUN0,LSHIFT[RDCTASK,4]]; SET TASK[DIAGTASK]; MC[MYIDU,1400]; *DISK ID IS 1407 MC[MYIDL,0]; *DISK ID IS 1407 MC[DIAGTASK.1,LSHIFT[DIAGTASK,14]]; MC[DISK.2,DISK.1]; MC[RPAGE1.2,RPAGE1.1]; MC[RDCSTASK,RDCTASK]; MC[RDCTASK.1,LSHIFT[RDCTASK,14]]; MC[RDCDTASK.1,LSHIFT[RDCTASK,14]]; MC[PMSTARTL,10000]; MC[PMSTARTU,0]; MC[PMENDL,70000]; MC[PDISKS,0]; MC[PDISKE,0]; MC[PHEADS,0]; MC[PHEADE,7]; MC[PCYLS,0]; MC[PCYLE,311]; MC[PSECTORS,0]; MC[PSECTORE,33]; MC[PDTYPE,1]; MC[PPHASE,0]; MC[PPHASEDONE,1]; MC[PDATAINC,0]; MC[PIODONE,0]; MC[PIOERROR,0]; MC[PSEED,400]; MC[DBSIZE,400]; MC[PCMDPOINTER,340]; MC[PRUNPHASES,17]; MC[PNORATERR,0]; MC[PCMDINC,0]; MC[PNOHALT,0]; MC[PERRORC,0]; MC[PERRORF,0]; MC[PIOCBA,3000]; *DISK CONTROL BLOCK MC[IOCBAE,7000]; *DISK CONTROL BLOCK END MC[CSBA,300]; *POINTER TO NEXT COMMAND BLOCK MC[PRETRYC,3]; MC[HEADERW,200]; MC[HEAERR,100]; MC[DATAW,4]; MC[DATAC,1]; MC[DATAR,2]; MC[LABELW,40]; MC[LABELC,10]; MC[LABELR,20]; ********** R-Registers: ********** RV[MSTARTL,0]; RV[MSTARTU,1]; RV[MENDL,2]; RV[RETRYC,3]; RV[DISKS,4]; RV[DISKE,5]; RV[HEADS,6]; RV[HEADE,7]; RV[EXPECTED,10]; RV[OBSERVED,11]; RV[ADDRESS,12]; RV[ERRORF,13]; RV[BLOCK,14]; RV[CMDPOINTER,15]; RV[DTYPE,16]; RV[PHASEDONE,17]; RV[SECTORE,20]; RV[SAVE1,21]; RV[SAVE2,22]; RV[NODATAINC,23]; RV[IODONE,24]; RV[IOERROR,25]; RV[IOCBA,26]; RV[IOCBA1,27]; RV[LDISKSAVE,30]; RV[LHEADSAVE,31]; RV[CHAIN,32]; RV[RANDOMC,33]; RV[PHASE4COMD,34]; RV[SUNKUP,35]; RV[NORETRY,36]; RV[RANDOMD,37]; RV[NWW,40]; RV[RUNPHASES,41]; RV[SEED,42]; RV[NORATERR,43]; RV[NOHALT,44]; RV[RANDOM,45]; RV[ERRORC,46]; RV[PASSCOUNT,47]; RV[DISKSAVE,50]; RV[HEADSAVE,51]; RV[SAVE,52]; RV[NOCMDINC,53]; RV[CYLS,54]; RV[CYLE,55]; RV[SECTORS,56]; RV[PHASE,57]; RV[RDC0,60]; RV[RDC1,61]; RV[RDC2,62]; RV[RDC3,63]; RV[RDC4,64]; RV[RDC5,65]; RV[RDC6,66]; RV[RDC7,67]; RV[RDC10,70]; RV[RDC11,71]; RV[RDC12,72]; RV[RDC13,73]; RV[RDC14,74]; RV[RDC15,75]; RV[RDC16,76]; RV[RDC17,77]; RV[PASSES-TO-RUN,47,1]; SetTask[7]; RV[CSBL,60]; RV[CSBH,61,0]; RV[IOCB0,62]; RV[IOCB1,63]; RV[IOCBERROR,64]; RV[IOCBH,65,0]; RV[DiskError,66]; RV[CylinderError,67]; RV[HeadError,70]; RV[SectorError,71]; RV[Temp7,72]; RV[REVISION,73,1]; ** double define registers to enable Midas to address ** the registers with or without the RDC prefix SetTask[0]; RV[RDCMSTARTL,0]; RV[RDCMSTARTU,1]; RV[RDCMENDL,2]; RV[RDCRETRYC,3]; RV[RDCDISKS,4]; RV[RDCDISKE,5]; RV[RDCHEADS,6]; RV[RDCHEADE,7]; RV[RDCEXPECTED,10]; RV[RDCOBSERVED,11]; RV[ADDRESS,12]; RV[ERRORF,13]; RV[RDCBLOCK,14]; RV[RDCCMDPOINTER,15]; RV[RDCDTYPE,16]; RV[RDCPHASEDONE,17]; RV[RDCSECTORE,20]; RV[RDCSAVE1,21]; RV[RDCSAVE2,22]; RV[RDCNODATAINC,23]; RV[RDCIODONE,24]; RV[RDCIOERROR,25]; RV[RDCIOCBA,26]; RV[RDCIOCBA1,27]; RV[RDCLDISKSAVE,30]; RV[RDCLHEADSAVE,31]; RV[RDCCHAIN,32]; RV[RDCRANDOMC,33]; RV[RDCPHASE4COMD,34]; RV[RDCSUNKUP,35]; RV[RDCNORETRY,36]; RV[RDCRANDOMD,37]; RV[RDCNWW,40]; RV[RUNPHASES,41]; RV[RDCSEED,42]; RV[RDCNORATERR,43]; RV[RDCNOHALT,44]; RV[RDCRANDOM,45]; RV[ERRORC,46]; RV[RDCPASSCOUNT,47]; RV[DISKSAVE,50]; RV[RDCHEADSAVE,51]; RV[RDCSAVE,52]; RV[RDCNOCMDINC,53]; RV[RDCCYLS,54]; RV[RDCCYLE,55]; RV[RDCSECTORS,56]; RV[RDCPHASE,57]; **************************************************************************************** *** MAIN routine: ON PAGE[DISK]; GOTO[RDCINTR],AT[DISK.1,0]; GOTO[START],AT[DISK.1,377]; GO: START:LOADPAGE[DISK5]; GOTOP[ADD0]; START1:RDC1_0C; *START TO START2 PUTS DEFAULT PARAMARTERS MSTARTU_PMSTARTU; MSTARTU_(MSTARTU)OR(1C); MSTARTL_PMSTARTL; RETRYC_PRETRYC; NORETRY_0C; MENDL_PMENDL; DISKS_PDISKS; TASK,DISKE_PDISKE; HEADS_PHEADS; HEADE_PHEADE; CYLS_PCYLS; CYLE_PCYLE; SECTORS_PSECTORS; SECTORE_PSECTORE; DTYPE_PDTYPE; TASK,CHAIN_1C; SEED_1C; T_PSEED; T_(SEED)+(T); SEED_(SEED)-(T); CMDPOINTER_PCMDPOINTER; NOCMDINC_PCMDINC; NODATAINC_PDATAINC; RUNPHASES_PRUNPHASES; TASK,NORATERR_PNORATERR; NOHALT_PNOHALT; RANDOMC_100C; RANDOMD_0C; RDC10_110C; RDC11_120C; RDC12_140C; RDC13_111C; RDC14_112C; RDC15_114C; RDC16_120C; RDC17_121C; RDC0_PCMDPOINTER; TASK; PSTORE4[RDC0,RDC10,0]; PSTORE4[RDC0,RDC14,4]; RDC10_112C; RDC11_124C; RDC12_140C; RDC13_122C; PHASE4COMD_111C; SUNKUP_0C; TASK,RANDOM_0C; PSTORE4[RDC0,RDC10,10]; RDC0_CSBA; RDC10_(ZERO)-1; RDC11_(ZERO)-1; RDC12_(ZERO)-1; RDC13_(ZERO)-1; TASK; PSTORE4[RDC0,RDC10,10]; IOCBA1_0C; IOCBA_PCMDPOINTER; IOCBA_(IOCBA)+(17C); PASSCOUNT_12C; PSTORE1[IOCBA,SUNKUP,0]; PHASE_PPHASE; IOCBA_PIOCBA; ERRORC_PERRORC; TASK,ERRORF_PERRORF; BLOCK_(ZERO)-1; PHASEDONE_PPHASEDONE,GOTO[SETPARAMETERS]; START2:IOCBA1_0C; IOCBA_PCMDPOINTER; IOCBA_(IOCBA)+(17C); PASSCOUNT_1C; TASK,PSTORE1[IOCBA,SUNKUP,0]; PHASE_PPHASE; IOCBA_PIOCBA; ERRORC_PERRORC; ERRORF_PERRORF; BLOCK_(ZERO)-1; PHASEDONE_PPHASEDONE; SETPARAMETERS:BREAKPOINT; *HALT TO DISPLAY PARAMATERS RDC0_CSBA; RDC1_0C; RDC10_0C; RDC11_0C; RDC12_0C; RDC13_0C; TASK; PSTORE4[RDC0,RDC10,0]; PSTORE4[RDC0,RDC10,4]; PSTORE4[RDC0,RDC10,14]; *CLEAR RDCCSB WORDS RDC10_0C; TASK; PSTORE1[RDC0,RDC10,1]; *RDCCSB WAKEUPMASK RDC10_(ZERO)-1; NOP; PSTORE1[RDC0,RDC10,4]; *FORCE A RECAL FIRST OPERATION TASK,PSTORE1[RDC0,RDC10,5]; *FORCE A RECAL FIRST OPERATION PSTORE1[RDC0,RDC10,6]; *FORCE A RECAL FIRST OPERATION PSTORE1[RDC0,RDC10,7]; *FORCE A RECAL FIRST OPERATION T_MENDL; TASK,RDC2_T; T_MSTARTL; T_RDC0_T; RDC2_(RDC2)-T; RDC2_(RDC2)+1; RDC3_0C; T_MSTARTU; TASK,RDC1_T; RDC3_0C; RDC4_0C; LOADPAGE[DISK5]; CALLP[MEMPUT],RDC5_0C; *CLEAR MEMORY NOP; CALL[RDCINIT]; LOADPAGE[DISK4]; GOTOP[RUNLIST]; ON PAGE[DISK4]; RUNLIST:LOADPAGE[DISK]; CALLP[INITIOCB]; LOADPAGE[DISK]; CALLP[FILDATA]; RUNLIST1:LOADPAGE[DISK1]; CALLP[NEWPHASE]; T_DISKSAVE; TASK,LDISKSAVE_T; T_HEADSAVE; LHEADSAVE_T; RUNLIST2:LOADPAGE[DISK]; CALLP[ISSUEBLK]; NOP; RUNLIST3:LOADPAGE[DISK1]; CALLP[UPDTIOCB]; T_CHAIN; GOTO[RUN1,ALU=0]; IOCBA_(IOCBA)+(40C); LU_(IOCBA)-(IOCBAE); GOTO[RUN2,ALU<0]; IOCBA_PIOCBA; RUNLIST4:LOADPAGE[DISK1]; CALLP[UPDTCSB]; RUNLIST5:NOP; CALL[WAKEUPWAIT]; T_IOERROR; GOTO[RUN0,ALU#0]; NOERROR:LU_(PHASE)AND(43C); *DISK OPPERATION COMPLETE WITH NO ERROR GOTO[RUN6,ALU#0],LU_(PHASE)AND(124C); GOTO[RUNLIST7,ALU#0],LU_(PHASE)AND(10C); GOTO[RUNLIST6,ALU#0]; BADPHASE:BREAKPOINT; LOADPAGE[DISK]; GOTOP[START1]; RUNLIST6:NOP; CALL[CHKCMD]; NOP; RUNLIST7:LOADPAGE[DISK2]; CALLP[DATAVFY]; RETRYC_PRETRYC; RUNLIST10:LOADPAGE[DISK1]; CALLP[CHKPHASE]; LU_RANDOMD; GOTO[RUNLIST100,ALU=0],RANDOMD_0C; DISKSAVE_(ZERO)-1; HEADSAVE_(ZERO)-1; RUNLIST100:GOTO[RUNLIST1]; RUN0: LOADPAGE[DISK3]; GOTOP[ERROR0]; RUN1: GOTO[RUNLIST4]; RUN2: GOTO[RUNLIST2]; RUN6: RETRYC_PRETRYC,GOTO[RUNLIST10]; ON PAGE[DISK3]; ERROR13:OBSERVED_T; EXPECTED_0C; TASK,T_IOCBA; ADDRESS_T; RDC7_13C,GOTO[ERROR]; ERROR12:T_RDC3; EXPECTED_T; T_RDC10; TASK,OBSERVED_T; T_RDC0; ADDRESS_T; ADDRESS_(ADDRESS)-(1C); RDC7_12C,GOTO[ERROR]; ERROR11:T_RDC3; EXPECTED_T; T_RDC13; TASK,OBSERVED_T; T_RDC0; ADDRESS_T; ADDRESS_(ADDRESS)-(1C); RDC7_11C,GOTO[ERROR]; ERROR10:T_RDC3; EXPECTED_T; T_RDC12; TASK,OBSERVED_T; T_RDC0; ADDRESS_T; ADDRESS_(ADDRESS)-(2C); RDC7_10C,GOTO[ERROR]; ERROR7:T_RDC3; EXPECTED_T; T_RDC11; TASK,OBSERVED_T; T_RDC0; ADDRESS_T; ADDRESS_(ADDRESS)-(3C); RDC7_7C,GOTO[ERROR]; ERROR6:T_RDC3; EXPECTED_T; TASK,T_RDC10; OBSERVED_T; T_RDC0; ADDRESS_T; ADDRESS_(ADDRESS)-(4C); RDC7_6C,GOTO[ERROR]; ERROR5:T_RDC3; EXPECTED_T; T_RDC13; TASK,OBSERVED_T; T_RDC0; ADDRESS_T; ADDRESS_(ADDRESS)-(1C); RDC7_5C,GOTO[ERROR]; ERROR4:T_RDC3; EXPECTED_T; T_RDC12; TASK,OBSERVED_T; T_RDC0; ADDRESS_T; ADDRESS_(ADDRESS)-(2C); RDC7_4C,GOTO[ERROR]; ERROR3:T_RDC3; EXPECTED_T; T_RDC11; TASK,OBSERVED_T; T_RDC0; ADDRESS_T; ADDRESS_(ADDRESS)-(3C); RDC7_3C,GOTO[ERROR]; ERROR2:T_RDC3; EXPECTED_T; T_RDC10; TASK,OBSERVED_T; T_RDC0; ADDRESS_T; ADDRESS_(ADDRESS)-(4C); RDC7_2C,GOTO[ERROR]; ERROR0:RDC7_0C,GOTO[ERR]; ERROR: LU_NOHALT; *THIS IS A DATA ERROR HALT GOTO[ERR10,ALU#0]; *CHECK IF NOSTOP=1 LOADPAGE[DISK5]; CALLP[EXTRACT]; DATAERROR:BREAKPOINT; ERR10: LOADPAGE[DISK]; CALLP[RDCINIT]; IOCBA_PIOCBA; LU_NORETRY; GOTO[NORETRYERROR,ALU#0]; RETRYC_(RETRYC)-1; GOTO[NOTNEXT,ALU>=0]; NOP; NORETRYERROR:T_DISKSAVE; TASK,LDISKSAVE_T; T_HEADSAVE; LHEADSAVE_T; NOTNEXT:NOP; CALL[INITNEWPHASE]; T_LDISKSAVE; DISKSAVE_T; TASK,T_LHEADSAVE; HEADSAVE_T; LOADPAGE[DISK4]; GOTOP[RUNLIST10]; ERR:RDC1_0C; *THIS IS A DISK STATUS ERROR HALT RDC0_CSBA; TASK; PFETCH1[RDC0,RDC0,17]; RDC0_RDC0; RDC1_0C; TASK,T_20C; PFETCH1[RDC0,RDC14]; *GET RDCIOCB STATUS RDC14_RDC14; LU_(RDC0)XOR(PIOCBA); GOTO[ERR6,ALU=0];*,ALU=0 RDC0_(RDC0)-(40C); TASK; PFETCH2[RDC0,LDISKSAVE,0]; *GET LAST GOOD HEADER LDISKSAVE_LDISKSAVE; ERR6:RDC0_CSBA; NOP; TASK,PFETCH1[RDC0,RDC15,2]; *GET RDCCSB STATUS T_RDC15; RDC14_(RDC14)ORT; *OR RDCIOCB AND RDCCSB T_RDC14; ERRORF_T; LU_NORATERR; GOTO[ERR5,ALU=0],T_(ERRORF)AND(400C); GOTO[ERR7,ALU#0]; NOP; ERR5:LU_NOHALT; GOTO[DEVICEERROR1,ALU=0]; *CHECK IF NOSTOP=1 NOP; ERR4: LOADPAGE[DISK]; CALLP[RDCINIT]; NOP; ERR7:NOP; CALL[INITNEWPHASE]; T_LDISKSAVE; DISKSAVE_T; TASK,T_LHEADSAVE; HEADSAVE_T; LOADPAGE[DISK4]; GOTOP[RUNLIST2],IOCBA_PIOCBA; *SET RDCCSB SAME DISK ADD AND BLOCK DEVICEERROR1: LOADPAGE[DISK5]; CALLP[EXTRACT]; DEVICEERROR: BREAKPOINT; GOTO[ERR4]; ON PAGE[DISK5]; ADD0: EXPECTED_MYIDU; T_MYIDL; EXPECTED_(EXPECTED)+T; ADDRESS_20C; ADD1: ADDRESS_(ADDRESS)-1; *SHIFT OUT 17 TASK#'S CALL[SRCADDR]; *CALL TO SHIFT OUT TASK# LU_ADDRESS; GOTO[ADD1,ALU#0]; *GO GET ANOTHER TASK# TO TRY ADDRESS_20C; ADD2: ADDRESS_(ADDRESS)-1; *SHIFT OUT 17 TASK#'S T_LSH[ADDRESS,4]; INPUT[OBSERVED]; OBSERVED_(OBSERVED)AND(177400C); T_EXPECTED; LU_(OBSERVED)XORT; GOTO[ADD3,ALU=0],LU_ADDRESS; GOTO[ADD2,ALU#0]; *GO GET ANOTHER TASK# TO TRY NOIDHERE:BREAKPOINT; *NO CONTROLER HAD MY ID GOTO[ADD1],ADDRESS_20C; ADD3: T_ADDRESS; *FOUND MY ID IN POSITION SAVED IN RDC17 RDC17_T; *RDC17_(RDC17)XOR(17C); RDC15_20C; ADD4: RDC15_(RDC15)-1; *RDC15=MY SOFT ID # FROM 17 TO 0 ADD5: RDC16_20C; ADD6: T_RDC16_(RDC16)-1; *RDC16= CURRENT POSITION TO BE SHIFTED OUT LU_(RDC17)XOR(T); *DOES CURRENT POSITION= MY POSITION GOTO[ADD7,ALU#0]; T_RDC15; ADDRESS_T,GOTO[ADD10]; ADD7: T_RDC15; ADDRESS_T; ADDRESS_(ADDRESS)XOR(17C); ADD10:CALL[SRCADDR]; LU_RDC16; GOTO[ADD6,ALU#0]; *GO SHIFT ANOTHER TASK# OUT T_LSH[RDC15,4]; *WE SHIFTED ALL 17 OUT NOW CHECK MY ID INPUT[OBSERVED]; OBSERVED_(OBSERVED)AND(177400C); T_EXPECTED; LU_(OBSERVED)XORT; GOTO[IDER1,ALU#0],LU_RDC15; GOTO[ADD4,ALU#0]; ADD25: RDC16_20C; ADD26: T_RDC16_(RDC16)-1; *RDC16= CURRENT POSITION TO BE SHIFTED OUT LU_(RDC17)XOR(T); *DOES CURRENT POSITION= MY POSITION GOTO[ADD27,ALU#0]; T_RDCSTASK; ADDRESS_T,GOTO[ADD20]; ADD27: ADDRESS_0C; ADD20:CALL[SRCADDR]; LU_RDC16; GOTO[ADD26,ALU#0]; *GO SHIFT ANOTHER TASK# OUT LOADPAGE[DISK]; GOTOP[START1]; IDER1: T_RDC15; ADDRESS_T; IDER: BREAKPOINT; GOTO[ADD0]; ********** SUBROUTINE: CHKCMD ********** * * CHKCMD finds out if all commands are done. * ON PAGE[DISK4]; CHKCMD: USECTASK; T_GETRSPEC[143]; TASK,SAVE_T; T_CMDPOINTER; *THISE ROUTINE WILL RUN COMMD LIST FOR PHASE3 RDC0_T; NOP; TASK,PFETCH1[RDC0,RDC14,0]; *GET NEW CMMD NOP; PFETCH1[IOCBA,RDC16,15]; *GET LAST RDCCMD T_RDC14; LU_(RDC16)XOR(T); GOTO[CHKCMD1,ALU=0]; RETRYC_PRETRYC; RDC15_0C; CHKCMDSPIN:PSTORE1[IOCBA,RDC14,15]; TASK,T_20C; PSTORE1[IOCBA,RDC15]; LU_CHAIN; GOTO[CHKCMD2,ALU=0]; IOCBA_(IOCBA)+(40C); LU_(IOCBA)-(IOCBAE); GOTO[CHKCMDSPIN,ALU<0]; NOP; CHKCMD2: IOCBA_PIOCBA,GOTO[RUNLIST4]; *GOTO SET RDCCSB CHKCMD1: APCTASK&APC_SAVE; RETURN; *GOTO CHECK BLOCK ********** SUBROUTINE: CHKPHASE ********** * * CHKPHASE checks for phase completed. * ON PAGE[DISK1]; CHKPHASE: USECTASK; T_GETRSPEC[143]; TASK; SAVE_T; LU_RANDOM; GOTO[CHKPHASE2,ALU=0]; GOTO[CHKPHASE1]; CHKPHASE2: T_LSH[DISKE,14]; T_(CYLE)OR(T); T_(DISKSAVE)XOR(T); GOTO[CHKPHASE1,ALU#0];T_LSH[HEADE,10]; T_(SECTORE)OR(T); T_(HEADSAVE)XOR(T); GOTO[CHKPHASE1$,ALU#0]; PHASEDONE_1C; *SET PHASE DONE TASK,DISKSAVE_(ZERO)-1; HEADSAVE_(ZERO)-1; T_NOCMDINC; GOTO[CHKPHASE31,ALU#0]; LU_(PHASE)AND(10C); GOTO[CHKPHASE30,ALU=0]; CMDPOINTER_(CMDPOINTER)+1; CHKPHASE31: NOP; CHKPHASE30: NOP; CHKPHASE1$: NOP; CHKPHASE1: APCTASK&APC_SAVE; RETURN; ********** SUBROUTINE: DATAVFY ********** * * DATAVFY verifies the data and label * depending on the current phase. * ON PAGE[DISK2]; DATAVFY: USECTASK; T_GETRSPEC[143]; SAVE_T; IOCBA_PIOCBA; *CHECK THE HEADER DATAVFYSPIN:NOP; TASK,PFETCH1[IOCBA,BLOCK,16]; PFETCH4[IOCBA,RDC10,0]; *GET 4 WORDS T_RDC10; T_(RDC12)XOR(T); T_(RDC11)XOR(T); T_(RDC13)XOR(T); GOTO[ERROR13L,ALU#0]; RDC17_1C; *ZERO=RDCDATA ,ONE = RDCLABLE TASK,RDC2_10C; *THIS ROUTINE CHECKS THE LABLE/DATA IN THE IOCB/BLOCK T_IOCBA; RDC0_T; RDC1_0C; RDC0_(RDC0)+(4C); *RDC0=IOCBLABLEADD,RDC2=DBSIZE NOP; DATAVFY10:PFETCH1[RDC0,RDC3,0]; *RDC3=NEXT SEED WORD T_(PHASE)XOR(100C); *CHECK FOR PHASE6 GOTO[DATAVFY30,ALU=0]; DATAVFY0: T_RDC3; TASK; RDC4_T; *RDC4=MODIFIER DATAVFY1: PFETCH4[RDC0,RDC10,0]; *GET 4 WORDS TASK,RDC2_(RDC2)-(4C); *DECREASE WORD COUNT RDC0_(RDC0)+(4C); *INCREASE WORD ADDRESS LU_DTYPE; GOTO[DATAVFY2,ALU#0]; *CHECK RDCDATA DTYPE T_RDC3; LU_(RDC10)XORT; GOTO[ERROR2L,ALU#0]; *CHECK FIRST WORD NOP; TASK,T_RDC4; T_RDC3_(RDC3)+T; *RDC3=NEXT WORD LU_(RDC11)XORT; GOTO[ERROR3L,ALU#0]; *CHECK SECOND WORD T_RDC4; T_RDC3_(RDC3)+T; *RDC3=NEXT WORD LU_(RDC12)XORT; GOTO[ERROR4L,ALU#0]; *CHECK THIRD WORD NOP; TASK,T_RDC4; T_RDC3_(RDC3)+T; *RDC3=NEXT WORD LU_(RDC13)XORT; GOTO[ERROR5L,ALU#0]; *CHECK FOURTH WORD DATAVFY3: T_RDC4; TASK; RDC3_(RDC3)+T; *RDC3=NEXT WORD GOTO[DATAVFY5]; DATAVFY2: T_RDC3; TASK; NOP; LU_(RDC10)XORT; GOTO[ERROR6L,ALU#0],T_RDC4; *CHECK FIRST WORD T_RDC3_(RDC3)XORT; *RDC3=NEXT WORD LU_(RDC11)XORT; GOTO[ERROR7L,ALU#0],T_RDC4; *CHECK SECOND WORD T_RDC3_(RDC3)XORT; *RDC3=NEXT WORD LU_(RDC12)XORT; GOTO[ERROR10L,ALU#0],T_RDC4; *CHECK THIRD WORD T_RDC3_(RDC3)XORT; *RDC3=NEXT WORD LU_(RDC13)XORT; GOTO[ERROR11L,ALU#0]; *CHECK FOURTH WORD DATAVFY4: T_RDC4; TASK; RDC3_(RDC3)XORT; *RDC3=NEXT WORD GOTO[DATAVFY5]; DATAVFY5: LU_RDC2; GOTO[DATAVFY6,ALU=0]; GOTO[DATAVFY1]; DATAVFY6: RDC17_(RDC17)-1,GOTO[DATAVFY7,R<0]; NOP; TASK,PFETCH2[IOCBA,RDC0,16]; RDC0_RDC0; RDC2_DBSIZE,GOTO[DATAVFY10]; DATAVFY7: LU_CHAIN; GOTO[DATAVFY11,ALU=0]; IOCBA_(IOCBA)+(40C); LU_(IOCBA)-(IOCBAE); GOTO[DATAVFYSPIN,ALU<0]; IOCBA_PIOCBA; DATAVFY11:APCTASK&APC_SAVE; RETURN; DATAVFY30:GOTO[DATAVFY7]; ERROR13L:LOADPAGE[DISK3]; GOTOP[ERROR13]; ERROR12L:LOADPAGE[DISK3]; GOTOP[ERROR12]; ERROR11L:LOADPAGE[DISK3]; GOTOP[ERROR11]; ERROR10L:LOADPAGE[DISK3]; GOTOP[ERROR10]; ERROR7L:LOADPAGE[DISK3]; GOTOP[ERROR7]; ERROR6L:LOADPAGE[DISK3]; GOTOP[ERROR6]; ERROR5L:LOADPAGE[DISK3]; GOTOP[ERROR5]; ERROR4L:LOADPAGE[DISK3]; GOTOP[ERROR4]; ERROR3L:LOADPAGE[DISK3]; GOTOP[ERROR3]; ERROR2L:LOADPAGE[DISK3]; GOTOP[ERROR2]; ********** SUBROUTINE: EXTRACT ********** * * Extract finds the last IOCB and extracts * the disk, cylinder, head, and sector information. * SetTask[0]; ON PAGE[DISK5]; EXTRACT: PassCount _ 4000C; PassCount _ (PassCount) OR (70000C); APC&APCTASK _ (PassCount); PassCount _ 1C, Return; *use task 7 R registers SetTask[7]; FIOCB: CSBL _ 300C, AT[4000]; CSBH _ 0C; PFetch1[CSBL,IOCBERROR,0]; *look at CSB word 0 lu _ IOCBERROR; *test for zero goto[New, alu#0]; *use CSB0 as IOCB pointer if none zero Old: PFetch1[CSBL,IOCBERROR,17]; *get old IOCB pointer (word 17) IOCBERROR _ IOCBERROR; *interlock IOCBH _ 0C; New: PFetch2[IOCBERROR,IOCB0,0]; *get IOCB word0 and word1 t _ LDF[IOCB0,0,4]; DiskError _ t; *extract disk drive number t _ LDF[IOCB0,10,10]; CylinderError _ t; *extract cylinder number t _ LDF[IOCB1,0,10]; HeadError _ t; *extract head number t _ LDF[IOCB1,10,10]; SectorError _ t; *extract sector number Temp7 _ 4000C; Temp7 _ (Temp7) OR (40C); APC&APCTASK _ (Temp7); Return; *get back to task 0 SetTask[0]; ExtractDone: Return, AT[4040]; ********** SUBROUTINE: HANDSHAKE ********** * * HANDSHAKE reads R register EXPECTED written by the * RDC task, saves it in NWW, reset bits 15 and 17, * then writes it back to EXPECTED. * ON PAGE[DISK4]; HANDSHAKE: USECTASK; TASK,T_GETRSPEC[143]; SAVE1_T; RDC6 _ 10C; *load address of NWW T _ (GETRSPEC[103]) XOR (377C); *save STKP, right side up STKP _ RDC6, RDC6 _ T; *set STKP to NWW, save old STKP in RDC6 T _ STACK; NWW_ T; T_(NWW)AND NOT(5C); STACK _ T; *set NWW TO ZERO TASK,STKP _ RDC6; NOP; APCTASK&APC_SAVE1; RETURN; ********** SUBROUTINE: INITIOCB ********** * * INITIOCB initializes the memory * dedicated to IOCB's. * ON PAGE[DISK]; INITIOCB: USECTASK; T_GETRSPEC[143]; SAVE2_T; TASK,IOCBA_PIOCBA; DISKSAVE_(ZERO)-1; HEADSAVE_(ZERO)-1; ASPIN:RDC10_0C; RDC11_0C; RDC12_0C; RDC13_0C; TASK; PSTORE4[IOCBA,RDC10,0]; *INITIALIZE ALL RDCIOCB WORDS PSTORE4[IOCBA,RDC10,4]; TASK,PSTORE4[IOCBA,RDC10,10]; PSTORE4[IOCBA,RDC10,14]; T_20C; TASK,PSTORE4[IOCBA,RDC10]; RDC0_4C; T_21C; PSTORE1[IOCBA,RDC0]; LU_CHAIN; GOTO[INITIOCB1,ALU=0]; T_(IOCBA)+(40C); RDC0_T; TASK; PSTORE1[IOCBA,RDC0,14]; IOCBA_(IOCBA)+(40C); LU_(IOCBA)-(IOCBAE); GOTO[ASPIN,ALU<0]; IOCBA_(IOCBA)-(40C); RDC0_0C; TASK; PSTORE1[IOCBA,RDC0,14]; NOP; INITIOCB1: IOCBA_PIOCBA; APCTASK&APC_SAVE2; RETURN; ********** SUBROUTINE: INITNEWPHASE ********** * * INITNEWPHASE reinitializes the IOCB's * and the data buffer area in memory. * ON PAGE[DISK3]; INITNEWPHASE:USECTASK; T_GETRSPEC[143]; TASK,SAVE1_T; BLOCK_(ZERO)-1; LOADPAGE[DISK]; CALLP[INITIOCB]; LOADPAGE[DISK]; CALLP[FILDATA]; T_MENDL; RDC2_T; T_MSTARTL; TASK,RDC0_T; RDC2_(RDC2)-(T); RDC2_(RDC2)+1; *RDC2=COUNT T_MSTARTU; RDC1_T; TASK,RDC3_0C; RDC4_0C; LU_(PHASE)AND(4C); GOTO[NEWPHASE21,ALU=0]; LOADPAGE[DISK5]; CALLP[MEMPUT],RDC5_0C; *CLEAR MEMORY NOP; NEWPHASE21:APCTASK&APC_SAVE1; RETURN; ********** SUBROUTINE: ISSUEBLK ********** * * ISSUEBLK issues RDC Data Blocks. * ON PAGE[DISK]; ISSUEBLK: USECTASK; T_GETRSPEC[143]; TASK,SAVE_T; T_RDC7_DBSIZE; *TRUE DBSIZE T_BLOCK_(BLOCK)+T; *OLD DB+DBSIZE=NEW DB T_RDC7_(RDC7)+T; *T=NEW DB+DBSIZE T_(MENDL)-T; *MENDL-(NEW DB+DBSIZE) GOTO[ISSUEBLK1,ALU>=0]; GOTO[ISSUEBLK2]; ISSUEBLK1: T_MSTARTL; T_(BLOCK)-T; *NEW DB-RDCMSTART GOTO[ISSUEBLK2,ALU<0]; APCTASK&APC_SAVE; RETURN; ISSUEBLK2: T_MSTARTL; GOTO[ISSUEBLK1],BLOCK_T; *NEW DB=RDCMSTART ********** SUBROUTINE: FILDATA ********** * * FILDATA fills the IOCB memory buffer area * with the data pattern to be used in the test. * ON PAGE[DISK]; FILDATA: USECTASK; T_GETRSPEC[143]; SAVE2_T; T_MSTARTL; *THIS ROUTINE FILLS MEMORY BY BLOCKS WITH PATTERNS TASK,RDC0_T; *START ADDRESS T_MSTARTU; RDC1_T; *START ADDRESSU T_SEED; RDC3_T; *SEED WORD RDC4_T; *SEED WORD=MODIFIER T_MENDL; TASK,RDC7_T; T_DTYPE; RDC5_T; *DTYPE FILDATA1: LOADPAGE[DISK5]; CALLP[MEMPUT],RDC2_DBSIZE; *START+BLSIZE LU_(PHASE)AND(30C); GOTO[FILDATA2,ALU#0]; RDC3_(RDC3)+1; T_177400C; RDC3_(RDC3)XOR(T); T_377C; T_RDC3_(RDC3)XOR(T); RDC4_T; FILDATA2:T_DBSIZE; TASK; T_(RDC0)+T; *NEXT+DBSIZE T_(MENDL)-T; *DRDCMEND-NEXT+DBSIZE GOTO[FILDATA1,ALU>=0]; APCTASK&APC_SAVE2; RETURN; ********** SUBROUTINE: MEMPUT ********** * * MEMPUT puts RDC Data into memory. * RDC0: Low Address * RDC1: High Address * RDC2: Word Count * RDC3: RDCDATA to be stored * RDC4: Modifier to be applied to every word * RDC5: Function * ON PAGE[DISK5]; MEMPUT: USECTASK; T_GETRSPEC[143]; TASK,RDC17_T; T_RDC3; RDC10_T; *SET FIRST RDCDATA TO MEMORY LU_RDC5; GOTO[MEMPUTLOG,ALU#0]; T_RDC4; RDC10_(RDC10)-T; TASK; NOP; MEMPUT0$: NOP; *DUMMY ENTRY MEMPUT0: RDC2_RDC2; *WORD COUNT <=0 WE ARE DONE GOTO[MEMPUTOUT,ALU=0],FREEZERESULT; GOTO[MEMPUTOUT$,ALU<0]; LU_RDC5; GOTO[MEMPUTLOG1,ALU#0]; T_RDC4; TASK,T_RDC10_(RDC10)+T; *FIRST RDCDATA WORD READY TO GO T_(RDC4)+T; RDC11_T; T_(RDC4)+T; RDC12_T; TASK,T_(RDC4)+T; RDC13_T; MEMPUTCON: T_RSH[RDC2,2]; *SET OF FOUR RDCDATA, QUAD ALIGN AND ARITH MODIFIED GOTO[MEMPUT1,ALU=0]; *IF WORD COUNT LESS THAN 4 DO ONE RDCPUT T_LSH[RDC0,16]; *IS MEMORY ADD QUAD ALINE IF NOT DO ONE RDCPUT GOTO[MEMPUT4,ALU=0]; T_T; MEMPUT1: PSTORE1[RDC0,RDC10,0]; *RDCDATA TO MEMORY TASK; NOP; RDC0_(RDC0)+1; *UP COUNT MEMORY ADD GOTO[MEMPUT10,NOCARRY]; RDC1_(RDC1)+(400C)+1; *CARRY ONE INTO UPPER ADDRESS MEMPUT10: RDC2_(RDC2)-1,GOTO[MEMPUT0]; *DOWN COUNT WORD COUNT MEMPUT4: PSTORE4[RDC0,RDC10,0]; *COUNT>=TO 4 ADDRESS IS QUAD, RDCPUT 4 INTO MEMORY TASK,T_(RDC13); RDC10_T; T_4C; RDC2_(RDC2)-T; *DOWN COUNT WORD COUNT BY 4 RDC0_(RDC0)+T; *UP COUNT MEMORY ADDRESS BY 4 GOTO[MEMPUT40,NOCARRY]; RDC1_(RDC1)+(400C)+1; *CARRY 1 INTO UPPER ADDRESS MEMPUT40: GOTO[MEMPUT0]; MEMPUTOUT: T_T; MEMPUTOUT$:APCTASK&APC_RDC17; RETURN; MEMPUTLOG: T_RDC4; RDC10_(RDC10)XORT,GOTO[MEMPUT0$]; MEMPUTLOG1: T_RDC4; TASK,T_RDC10_(RDC10)XORT; *FIRST RDCDATA WORD READY TO GO T_(RDC4)XORT; RDC11_T; T_(RDC4)XORT; RDC12_T; T_(RDC4)XORT; GOTO[MEMPUTCON],RDC13_T; *SET OF FOUR RDCDATA WORDS QUAD ALIGN & LOGICAL MODIFIED ********** SUBROUTINE: NEWPHASE ********** * * NEWPHASE selects the next phase to run. * ON PAGE[DISK1]; NEWPHASE:USECTASK; T_GETRSPEC[143]; TASK; SAVE_T; LU _ RUNPHASES; GOTO[.+2, ALU#0]; PHASE _ 0C, GOTO[NEWPHASE10]; T_PHASEDONE; GOTO[NEWPHASE10,ALU=0]; NOP; NEWPHASE1:PHASE_LSH[PHASE,1]; *//=NEXT PHASE NEWPHASE2:T_PHASE; GOTO[NEWPHASE4,ALU=0]; *CHECK FOR LAST PHASE NEWPHASE3:T_PHASE; TASK; NOP; T_(RUNPHASES)ANDT; *SEE IF PHASE CONT HAS THIS BIT GOTO[NEWPHASE1,ALU=0]; LOADPAGE[DISK5]; CALLP[SETMAINT]; NOP; NEWPHASE7:LOADPAGE[DISK3]; CALLP[INITNEWPHASE]; RDC0_PCMDPOINTER; TASK,T_12C; T_RDC0_(RDC0)+(T); LU_(CMDPOINTER)-(T); GOTO[NEWPHASE24,ALU>=0]; NOP; TASK,T_RANDOMC; RANDOM_T; NOP; NEWPHASE10:PHASEDONE_0C; APCTASK&APC_SAVE; RETURN; NEWPHASE4:LU_NODATAINC; GOTO[NEWPHASE6,ALU=0]; NEWPHASE40:PHASE_1C; TASK; NOP; PASSCOUNT_(PASSCOUNT)-1; GOTO[NEWPHASE5,ALU<0]; GOTO[NEWPHASE2]; NEWPHASE5: PASSCOUNT_0C; LU_NOHALT; GOTO[NEWPHASE11,ALU#0]; *CHECK IF NOSTOP=1 PASSED-EDRDCD-TEST:BREAKPOINT; NEWPHASE11:LOADPAGE[DISK]; CALLP[RDCINIT]; GOTO[NEWPHASE2]; NEWPHASE6:T_1C; DTYPE_(DTYPE)XOR(T); TASK,SEED_(SEED)+(T); SEED_(SEED)+(400C); GOTO[NEWPHASE40]; NEWPHASE24: CMDPOINTER_PCMDPOINTER; GOTO[NEWPHASE10]; ********** SUBROUTINE: RDCINIT ********** * * RDCINIT saves return link in SAVE2 and notifies * the RDC Task code to initialize. * ON PAGE[DISK]; RDCINIT: USECTASK; T_GETRSPEC[143]; SAVE2_T; TASK,RDC0_RDCDTASK.1; T_RPAGE1.2; RDC0_(RDC0)+T; RDC0_(RDC0)OR(74C); APCTASK&APC_RDC0; *LINK TO TASK CODE TO INITIALIZE RETURN; ********** SUBROUTINE: RDCINTR ********** * * RDCINTR uses SAVE2 return address * to return to the RDCD Task (Task 0). * ON PAGE[DISK]; RDCINTR: APCTASK&APC_SAVE2; RETURN; ********** SUBROUTINE: SETMAINT ********** * * SETMAINT set the maintenance panel * to display the phase. * ON PAGE[DISK5]; SETMAINT: USECTASK; T_GETRSPEC[143]; *THIS ROUTINE SETS UP THE MAINTANCE PANEL TASK,SAVE1_T; CLEARMPANEL; RDC7_7C; T_LSH[PHASE,10]; RDC6_T; RDC6 _ RDC6, GOTO[SETMAINT2$, ALU = 0]; SETMAINT3:GOTO[SETMAINT1,ALU<0]; RDC7_(RDC7)-1; GOTO[SETMAINT3],RDC6_LSH[RDC6,1]; SETMAINT1:RDC7_(RDC7)-1; GOTO[SETMAINT2,ALU<0]; INCMPANEL; TASK; NOP; GOTO[SETMAINT1]; SETMAINT2$:NOP; SETMAINT2:APCTASK&APC_SAVE1; RETURN; ********** SUBROUTINE: SRCADDR ********** * * SRCADDR shifts out 16 task numbers * to the controller boards. * ON PAGE[DISK5]; SRCADDR: USECTASK; T_GETRSPEC[143]; SAVE1_T; OBSERVED_4C; *PUT TASK# INTO T AND SHIFT IT OUT T_(ADDRESS)XOR(17C); RDC14_T; SRCADDR1: GENSRCLOCK; TASK,T_RDC14_RSH[RDC14,1]; NOP; OBSERVED_(OBSERVED)-1; GOTO[SRCADDR1,ALU#0]; APCTASK&APC_SAVE1; RETURN; *QUIT WHEN YOU SHIFT FOUR TIMES ********** SUBROUTINE: UPDTIOCB ********** * * UPDTIOCB updates the IOCB block. * ON PAGE[DISK1]; UPDTIOCB: USECTASK; T_GETRSPEC[143]; TASK,SAVE_T; RDC16_2000C; DISPATCH[PHASE,14,4]; DISP[UPDTIOCB0]; UPDTIOCB0: GOTO[RDCDISP],AT[DISK1.1,100]; *NO PHASE GOTO[UPDTIOCB20],AT[DISK1.1,101]; *PHASE0 GOTO[UPDTIOCB11],AT[DISK1.1,102]; *PHASE1 GOTO[UPDTIOCB12],AT[DISK1.1,104]; *PHASE2 GOTO[UPDTIOCB11],AT[DISK1.1,110]; *PHASE3 RDCDISP:DISPATCH[PHASE,10,4]; DISP[UPDTIOCBD0]; UPDTIOCBD0: GOTO[NOPHASE],AT[DISK1.1,200]; *NO PHASE GOTO[UPDTIOCB122],T_PHASE4COMD,AT[DISK1.1,201]; *PHASE4 GOTO[UPDTIOCB11],AT[DISK1.1,202]; *PHASE5 GOTO[UPDTIOCB12],AT[DISK1.1,204]; *PHASE6 GOTO[NOPHASE],AT[DISK1.1,210]; *PHASE7 NOPHASE:BREAKPOINT; LOADPAGE[DISK]; GOTO[START2]; UPDTIOCB11: LU_(PHASE)AND(40C); GOTO[UPDTIOCB111,ALU=0],RDC16_HEAERR; *PHASE1 OR PHASE3 OR PHASE5 GOTO[UPDTIOCB20],RDC16_HEADERW; UPDTIOCB111:T_LABELW; *BUILD WRITE COMMD TASK,RDC16_(RDC16)OR(T); T_DATAW; GOTO[UPDTIOCB20],RDC16_(RDC16)OR(T); UPDTIOCB122:GOTO[UPDTIOCB20],RDC16_T; UPDTIOCB12: LU_(PHASE)AND(100C); *PHASE2 OR PHASE4 OR PHASE6 GOTO[UPDTIOCB121,ALU=0],RDC16_HEAERR; GOTO[UPDTIOCB20],RDC16_HEAERR; *PHASE6 UPDTIOCB121:T_LABELR; *BUILD READ COMMD TASK,RDC16_(RDC16)OR(T); T_DATAR; GOTO[UPDTIOCB20],RDC16_(RDC16)OR(T); UPDTIOCB20: NOP; TASK,PSTORE1[IOCBA,RDC16,15]; *COMMAND WORD RDCIOCB PSTORE1[IOCBA,BLOCK,16]; *RDCDATA POINTER PSTORE1[IOCBA,MSTARTU,17]; *RDCDATA POINTER UPPER LU_RANDOM; GOTO[UPDTIOCBNRDC1,ALU=0]; LOADPAGE[DISK4]; GOTOP[UPDTIOCBRANDOM]; UPDTIOCBNRDC1:T_LSH[DISKE,14]; TASK; T_(CYLE)OR(T); T_(DISKSAVE)XOR(T); GOTO[UPDTIOCBNR$,ALU#0];T_LSH[HEADE,10]; T_(SECTORE)OR(T); T_(HEADSAVE)XOR(T); GOTO[UPDTIOCB30$,ALU=0]; *GET CURRENT RDCSECTOR NOP; UPDTIOCBNR$:NOP; UPDTIOCBNR: T_LDF[HEADSAVE,10,10]; *GET CURRENT RDCSECTOR TASK,RDC3_T; T_RDC3_(RDC3)+1; *RDC3=NEW RDCSECTOR+1 RDC4_35C; LU_(RDC4)-T; GOTO[UPDTIOCB23,ALU<0]; *IS RDC3>35 T_SECTORE; TASK,RDC4_T; T_RDC3; T_(RDC4)-T; GOTO[UPDTIOCB23$,ALU<0]; *IS RDC3>ENDING SEC GOTO[UPDTIOCB30],HEADSAVE_(HEADSAVE)+1; UPDTIOCB23$:NOP; UPDTIOCB23: HEADSAVE_(HEADSAVE)AND(177400C); TASK,T_SECTORS; HEADSAVE_(HEADSAVE)OR(T); RDC3_(RDC3)+1; *RDC3=LAST RDCSECTOR +1 UPDTIOCB24: T_LDF[HEADSAVE,0,10]; *GET CURRENT RDCHEAD RDC3_T; TASK,T_RDC3_(RDC3)+1; *RDC3=NEW RDCHEAD+1 RDC4_10C; LU_(RDC4)-T; GOTO[UPDTIOCB25,ALU<0]; *IS RDC3>7 T_HEADE; TASK,RDC4_T; T_RDC3; T_(RDC4)-T; GOTO[UPDTIOCB25$,ALU<0]; *IS RDC3>ENDING RDCHEAD GOTO[UPDTIOCB30],HEADSAVE_(HEADSAVE)+(400C); UPDTIOCB25$:NOP; UPDTIOCB25: T_377C; TASK,HEADSAVE_(HEADSAVE)AND(T); T_HEADS; *GET START RDCHEAD RDC4_T; T_LSH[RDC4,10]; HEADSAVE_(HEADSAVE)OR(T); *RDC7=NEW RDCHEAD UPDTIOCB26: T_LDF[DISKSAVE,0,4]; *GET CURRENT DISK RDC3_T; TASK,T_RDC3_(RDC3)+1; *RDC3=NEW DISK+1 RDC4_3C; LU_(RDC4)-T; GOTO[UPDTIOCB27,ALU<0]; *IS RDC3>3 T_DISKE; TASK,RDC4_T; T_RDC3; T_(RDC4)-T; GOTO[UPDTIOCB27$,ALU<0]; *IS RDC3>ENDING DISK GOTO[UPDTIOCB30],DISKSAVE_(DISKSAVE)+(10000C); *DISKSAVE=NEW DISK UPDTIOCB27$:NOP; UPDTIOCB27: T_377C; TASK,DISKSAVE_(DISKSAVE)AND(T); T_DISKS; *GET START DISK RDC4_T; T_LSH[RDC4,14]; DISKSAVE_(DISKSAVE)OR(T); UPDTIOCB21: T_LDF[DISKSAVE,10,10]; RDC3_T; TASK;T_RDC3_(RDC3)+1; *RDC3=NEW TRACK+1 RDC4_311C; LU_(RDC4)-T; GOTO[UPDTIOCB22,ALU<0]; *IS RDC3>311 T_CYLE; TASK,RDC4_T; T_RDC3; T_(RDC4)-T; GOTO[UPDTIOCB22$,ALU<0]; *IS RDC3>ENDING TRACK GOTO[UPDTIOCB30],DISKSAVE_(DISKSAVE)+(1C); UPDTIOCB22$:NOP; UPDTIOCB22: T_RDC3_177400C; TASK,DISKSAVE_(DISKSAVE)AND(T); T_CYLS; DISKSAVE_(DISKSAVE)OR(T); NOP; UPDTIOCB30$:NOP; UPDTIOCB30: RDC0_CSBA; LOADPAGE[DISK3]; GOTOP[UPDTIOCB40]; ON PAGE[DISK3]; UPDTIOCB40:RDC1_0C; TASK; PFETCH4[RDC0,RDC10,10]; *GET NOT USED TRACKS RDC10_RDC10;*INTERLOCK T_DISKSAVE; LU_(RDC10)XOR(T); GOTO[UPDTIOCBBY0,ALU=0]; LU_(RDC11)XOR(T); GOTO[UPDTIOCBBY1,ALU=0]; LU_(RDC12)XOR(T); GOTO[UPDTIOCBBY2,ALU=0]; LU_(RDC13)XOR(T); GOTO[UPDTIOCBBY3,ALU=0]; PSTORE2[IOCBA,DISKSAVE,0]; *NEW DISK ADDRESS TASK,T_BLOCK; RDC0_T; T_MSTARTU; RDC1_T; NOP; TASK,PFETCH4[RDC0,RDC10,0]; PFETCH4[RDC0,RDC14,4]; RDC14_RDC14; TASK,PSTORE4[IOCBA,RDC10,4]; PSTORE4[IOCBA,RDC14,10]; APCTASK&APC_SAVE; RETURN; UPDTIOCBBY0:GOTO[UPDTIOCBBY3]; UPDTIOCBBY1:GOTO[UPDTIOCBBY3]; UPDTIOCBBY2:GOTO[UPDTIOCBBY3]; UPDTIOCBBY3:LOADPAGE[DISK1]; GOTOP[UPDTIOCBNRDC1]; ON PAGE[DISK4]; UPDTIOCBRANDOM:T_MSTARTL; TASK,RDC0_T; T_MSTARTU; RDC1_T; T_RANDOM_(RANDOM)-1; GOTO[UPDTIOCBRANDOM1,ALU=0]; RANDOM4:PFETCH1[RDC0,RDC14]; *GET NEW WORD T_LDF[DISKSAVE,10,10]; RDC14_(RDC14)+(T); DISKSAVE_177400C; HEADSAVE_(ZERO)-1; TASK,T_(RDC14)AND(377C); DISKSAVE_(DISKSAVE)OR(T); LU_(CYLS)-T; GOTO[UPDTIOCBRANDOM2,ALU>=0]; UPDTIOCBRANDOM3: DISKSAVE_(DISKSAVE)OR(T); LOADPAGE[DISK1]; GOTOP[UPDTIOCBNR]; UPDTIOCBRANDOM1:RANDOMD_1C,GOTO[RANDOM4]; UPDTIOCBRANDOM2:T_(CYLE)-1,GOTO[UPDTIOCBRANDOM3]; ********** SUBROUTINE: UPDTCSB ********** * * UPDTCSB updates the CSB block with the new * IOCB pointer, clears status, and sets process wakeup. * ON PAGE[DISK1]; UPDTCSB: USECTASK; TASK,T_GETRSPEC[143]; SAVE_T; LOADPAGE[DISK4]; CALLP[HANDSHAKE]; RDC0_CSBA; *CLEAR STATUS AND SET RDCIOCB LINK INTO RDCCSB RDC1_0C; RDC14_PIOCBA; RDC15_1C;*SET PROCESS W/U RDC16_0C; PSTORE2[RDC0,RDC14,0]; TASK; PSTORE1[RDC0,RDC16,2]; RDC7_0C;*TIMERCOUNT APCTASK&APC_SAVE; RETURN; ********** SUBROUTINE: WAKEUPWAIT ********** * * WAKEUPWAIT waits until the RDC responds * or until it is timed out. * ON PAGE[DISK4]; WAKEUPWAIT: USECTASK; TASK,T_GETRSPEC[143]; SAVE_T; WAKEUPWAITSPIN:NOP; CALL[HANDSHAKE]; IOERROR_0C; *SPIN HERE UNTILL WE GET A PROCESS W/U#0 RDC0_CSBA; RDC1_0C; RDC7_(RDC7)-1; GOTO[TIMERHALT1,ALU=0],T_(NWW)AND(4C); GOTO[WAKEUPWAIT1,ALU=0],T_(NWW)AND(1C);*CHECK FOR IOCB DONE W/U NWW_0C; RDC7_0C; TASK,PFETCH1[RDC0,RDC14,0]; *GET IOCB LINK PFETCH1[RDC0,RDC0,17]; *GET OLDIOCBLINK RDC14_RDC14; *INTERLOCK GOTO[WAKEUPWAIT2,ALU#0]; *IF LINK #TO 0,NOT DONE YET RDC0_RDC0; *INTERLOCK TASK,T_20C; PFETCH1[RDC0,RDC14]; *GET IOCB STATUS WORD RDC14_RDC14; T_12C; T_(LDF[RDC14,0,4])-(T); GOTO[WAKEUPWAIT3,ALU<0]; WAKEUPWAIT4:IOERROR_1C; WAKEUPWAIT3:APCTASK&APC_SAVE; RETURN; WAKEUPWAIT1:GOTO[WAKEUPWAIT5,ALU=0],NWW_0C; RDC7_0C,GOTO[WAKEUPWAITSPIN]; WAKEUPWAIT2:GOTO[WAKEUPWAITSPIN]; WAKEUPWAIT5:GOTO[WAKEUPWAITSPIN]; TIMERHALT1:LOADPAGE[DISK5]; CALLP[EXTRACT]; TIMERHALT:BREAKPOINT; GOTO[WAKEUPWAIT4]; END;(1270)\39847f9 1f0 4f9 5f0