TITLE TAPSER - COMMON MAGTAPE PHYSICAL IO DRIVER V1026 SUBTTL L.BOSACK/TAH/TW 11 OCT 83 SEARCH F,S IFE FTKS10, $RELOC $HIGH IFNDEF STUPID,STUPID==-1 ;Make SET NOMESS MTx: stick. [JE] ;Inserted SPR #10-32672. [JE] ;[JE] try to get TU45/RH10/DF10 working with RP06/RH10 on the same DF10. BUGFIX==STUPID ;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED ; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; .CPYRT< COPYRIGHT (C) 1974,1975,1976,1977,1978,1979,1980,1982,1984 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS. > ;DATE EDIT # LOAD ;---- ------ ---- ;02-DEC-80 075 70127 ;MCO 9477 ;27-JAN-81 70136 036 ;03-FEB-81 70137 077 ;9560- ;23-JUN-81 70163 1000 ;07-JUL-81 70165 1001 ;14-JUL-81 70166 1002 ;9814 ;28-JUL-81 70170 1003 ;9839 ;06-OCT-81 70177 1004 ;9915 ;13-OCT-81 70111 1005 ;9929- ;02-NOV-81 70114 1006 ;9952 ;05-JAN-82 70125 1007 ;12-JAN-82 70126 1010 ;19-JAN-82 70127 1011 ;26-JAN-82 70130 1012 ;10066 ;13-APR-82 70143 1013 ;10203 ;27-APR-82 70144 1014 ;10213 ;24-AUG-82 70145 1015 ;10371 ;31-AUG-82 70166 1016 ;10382 ;5-APR-83 70134 1017 ;10686 ;31-MAY-83 70143 1020 ;10776 ;7-JUN-83 70144 1021 ;2-AUG-83 70154 1022 ;9-AUG-83 70155 1023 ;06-SEP-83 70161 1024 ;25-OCT-83 70165 1025 ;11-OCT-83 70166 1026 ; XP VTAPSR,1026 ;FOR LINKEDIT MAP SALL TAPSER:: ENTRY TAPSER ;BIT DEFINITIONS ;IN TKBSTS ;BITS 0-2 = CPU NUMBER WHICH "OWNS" CONTROL ;IN TKBSTS & TUBSTS TKSOFL==:(1B17) ;OFFLINE TKSSEL==:(1B16) ;SELECTED TKSSTD==:(1B15) ;STARTED TKSSCH==:(1B14) ;REQUESTED SCHED INTERUPT TKSSIL==:(1B13) ;REQUEST SILENCE ABT OFF-LINE CONDITION TKSMNT==:(1B12) ;CTL IS IN MAINT MODE TKSCHE==(1B11) ;JOB HAS SWEPT CACHE FOR QUEUED REQUEST TKSCHX==:(1B10) ;NOT YET SWEPT FOR (CPU0) TKSCHA==(17B10) ;TKSCHX BITS FOR ALL CPUS ;IN TUBSTS TUSNS==:(1B0) ;DO NOT SCHEDULE THIS UNIT (SIGN BIT) TUSBOT==:(1B1) ;BEGINNING OF TAPE TUSWTL==:(1B2) ;WRITE LOCKED TUSREW==:(1B3) ;TAPE REWINDING TUSFLT==:(1B4) ;TAPE UNIT FAULT (BROKEN DRIVE) TUSBOF==:TUSBOT!TKSOFL ;IN TKBSTS TKSNS==:(1B3) ;DON'T SCHEDULE THIS KONTROLLER (DIAG.) ;IN TUBCNF TUC7TK==:1B18 ;SEVEN TRACK TUCIRD==:1B19 ;INTERUPTS WHEN REWIND DONE TUCDMS==:1B20 ;DIAG MODE SET TUCSNS==:1B21 ;FORCE SENSE ;TUCD??==:1B22 ;THIS BIT LEFT FOR EXPANSION TUCD62==:1B23 ;DRIVE CAN DO 6250 BPI TUCD16==:1B24 ;DRIVE CAN DO 1600 BPI TUCD80==:1B25 ;DRIVE CAN DO 800 BPI TUCD55==:1B26 ;DRIVE CAN DO 556 BPI TUCD20==:1B27 ;DRIVE CAN DO 200 BPI ; THE FOLLOWING SYMBOLS ARE FOR THE CONVENIENCE OF MACRO V50 TUCDR8==:TUCD20+TUCD55+TUCD80 ;TM10 9 TRACK DENSITIES TUCDR7==:TUC7TK+TUCDR8 ;7 TRACK TAPE + DENSITIES TUCDR6==:TUCD80+TUCD16 ;TM02 AND TU70 DENSITIES TUCDR5==:TUCD16+TUCD62 ;TU72 DENSITIES TUCDIG==:1B28 ;DIAG. UUO ON THIS DRIVE ;IN TUBERR NXTLSE==:(1B0) ;NEXT TO LAST ERROR RETRY ;ERROR RECOVERY PARAMETERS ERPNCS==5 ;NUMBER OF BACKSPACE/SPACE OP IN TAPE CLEANER SEQ. IOSCP2==:(1B11) ;MUST BE SAME AS TKSCHE TPKINI==:0 ;INITIALIZATION CODE TPKRES==:1 ;RESET ACTIVE TRANSFER TPKSIO==:2 ;START IO TPKINT==:3 ;INTERRUPT ROUTINE TPKCMD==:4 ;SET DEVICE COMMAND IN LIST (DX10 ONLY) TPKIDL==:5 ;SET DEVICE IDLE TPKONL==:6 ;SKIP IF KON ONLINE TPKSCH==:7 ;CAUSE SCHEDULE CYCLE TPKINX==:10 ;INITIALIZATION CODE AFTER SYSTEM STARTUP ;(WHEN KONTROLLER COMES ONLINE, ETC.) TPKCFG==:11 ;AUTO-CONFIG. ONLY NEEDED FOR TAPES WITH SUBUNITS ;EG TM02, TM78 ;BYTE POINTERS ;INTO KDB TKYCPU:: POINT 3,TKBSTS##(W),2 ;INTO UDB TUYKTP:: POINT 4,TUBCNF##(U),35 ;CONTROLLER TYPE TUYECT: POINT ERCCTS,TUBERR##(U),17 ;POINTER TO RETRY COUNTER TUYEC1: POINT ERCCTS,TUBERR##(U),17-ERCCTS ;SECONDARY RETRY COUNTER ;INTO IORB PRBRQS:: POINT RB.RQS,TRBLNK(T1),RB.RQP ;REQUEST STATUS PRBMOD:: POINT RB.MDS,TRBLNK(T1),RB.MDP ;REQUEST MODE PRBMD2:: POINT RB.MDS,TRBLNK(P1),RB.MDP PRBFCN:: POINT RB.FNS,TRBLNK(T1),RB.FNP ;REQUEST FUNCTION PRBDEN:: POINT RB.DNS,TRBLNK(T1),RB.DNP ;DENSITY PRBBYT:: POINT RB.BYS,TRBLNK(T1),RB.BYP ;REQUEST INFO SUBTTL INTERRUPT SERVICE. ;HERE WITH AC'S SAVED AND PDL SETUP. ;C(W) := KDB ADDRESS ;AFTER CALL TO DEVICE DEPENDENT ROUTINE OR ERROR PROCESSOR ;C(T1) := IORB ADDRS IF COMPLETED ; 0 IF ANOTHER INTERUPT COMING - NO FURTHER PROCESSING ; -1 IF SCHED CYCLE REQUESTED ;C(TUBERR) NON-ZERO IF ERROR RECOVERY IN PROGRESS TAPINT:: IFE FTKS10,< SKIPG TKBUNI##(W) ;MULTI UNITS ON AN RH? JRST TAPIN2 ;NO, CARRY ON XCT TKBCIS##(W) ;YES. CONI TRNE T2,CI.DON ;IF DONE IS ON JRST TAPIN2 ; THE INTERRUPT IS FROM THIS KDB MOVSI T2,(.DIASR) ;ATTEN INTERRUPT. READ ATTN SUMMARY XCT TKBDOS##(W) ; REGISTER IMULI P,1 IMULI P,1 ;STALL IN CASE AN RH10 XCT TKBDIS##(W) ;READ ATTENTION BITS ANDI T2,377 ;GET JUST ATTENTION BITS MOVE T1,W ;SAVE STARTING KDB ADDR TAPIN1: TDNE T2,TKBUNI##(W) ;INTERRUPT FOR THIS KDB? JRST TAPIN2 ;YES. HANDLE IT HLR W,TKBCDB##(W) ;NO, STEP TO NEXT KDB ON CONTROLLER CAME T1,W ;BACK WHERE WE STARTED? JRST TAPIN1 ;NO, SEE IF INTERRUPT FOR THIS KDB HRLI T2,(.DIASR!DO.LDR!DO.DRE) ;YES, NOT FOR ANY KDB WE KNOW OF XCT TKBDOS##(W) ; SO CLEAR THE INTERRUPT POPJ P, ;AND GO AWAY > TAPIN2: HRRZ T1,TKBDSP##(W) ;GET XFER VECTOR PUSHJ P,TPKINT(T1) ;CALL DEV DEP INT RTN TAPAGO::JUMPE T1,CPOPJ## ;IF ZERO, ANOTHER INT IS COMING JUMPL T1,TPINT1 ;NO COMPLETION - DO SCHED CYCLE MOVSI T2,TKSSTD ;CHANNEL NO LONGER STARTED ANDCAM T2,TKBSTS##(W) ;SO CLEAR STATUS ANDCAM T2,TUBSTS##(U) ;AND UNIT STATUS SKIPE T2,TUBERR##(U) ;IS ERP IN PROGRESS? PUSHJ P,ERPINT ;YES - CALL INTERRUPT PART JUMPE T1,CPOPJ## ;TERMINATE NOW? JUMPL T1,TPINT1 ;NO COMPLETION MOVEI T2,RB.DUN ;MARK IORB AS DONE DPB T2,PRBRQS ;... PUSHJ P,TPMDON## ;YES - NOTIFY UPPER LEVEL HRRZ T2,TKBSTS##(W) ;SEE IF A SCHED CYCLE IS DUE JUMPG T2,CPOPJ## ;NO - DISMISS PUSHJ P,TAPDSL ;DE-SELECT KONTROLLER TPINT1: IFN BUGFIX,< SETZB S,F ;Clear out these. [JE] >;IFN BUGFIX SETZM TKBTIM##(W) ;CLEAR HUNG TIMER PUSHJ P,TAPSCH ;SEE IF THERE IS MORE WORK POPJ P, ;NO MORE TO DO PJRST TPMSIO## ;START IO ;ROUTINE TO DE-SELECT A KONTROLLER AND CLEAR I/O TAPDSL::HRRZ T1,TKBDSP##(W) ;GET XFER VECTOR PUSHJ P,TPKIDL(T1) ;MARK IDLE HLLZS TKBSTS##(W) ;SET QUANTUM TO ZERO MOVSI T1,TKSSEL ;CLEAR SELECTION BITS ANDCAM T1,TUBSTS##(U) ; IN UDB ANDCAM T1,TKBSTS##(W) ; AND KDB HRRZ T1,TKBCDB##(W) ;LOC OF CHANNEL DATA BLOCK SETOM (T1) ;INDICATE THAT CHAN IS IDLE POPJ P, ;RETURN ;GENERAL INTERUPT ERROR HALT TAPIFI::STOPCD .,STOP,IFI, ;++ ILLEGAL FUNCTION AT INTERUPT SUBTTL CHANNEL SCHEDULER ;W/ KDB TO CONTINUE SCANNING. ;SKIP RETURNS WITH W AND U SETUP IF ANOTHER REQUEST IS FOUND ;NON SKIP RETURN IF NOTHING TO DO TAPSCH: PUSH P,W ;SAVE INITIAL KDB HRRZS (P) ;SAVING ONLY RIGHT HALF MOVE T4,TKBCUN##(W) ;GET CURRENT AOBJN POINTER PUSH P,T4 ;SAVE START MOVSI T2,TKSOFL!TKSMNT!TKSNS ;CHECK IF HE IS AMOUNG US TDNE T2,TKBSTS##(W) ;... JRST TPSCH2 ;NO, DON'T SCHEDULE FOR HIM AOBJP T4,TPSCH2 ;AND START LOOKING AT NEXT UNIT TPSCH1: SKIPN U,(T4) ;GET UDB JRST TPSCHN ;NONE PRESENT HRRZ T1,TUBQUE##(U) ;GET QUEUE POINTER JUMPE T1,TPSCHN ;GO IF NONE IFE FTMP,< SKIPL T2,TUBSTS##(U) ;NO SCHED? > IFN FTMP,< SKIPGE T2,TUBSTS##(U) ;NO SCHED ON THIS CPU TLNE T2,TKSCHE > TLNE T2,TKSSEL!TKSCHA ;OR SELECTED BY ANOTHER? JRST TPSCHN ;YES IFN FTMP,< MOVE T3,TRBLNK(T1) ;GET IORB FLAGS TLNN T2,TKSCHE ;QUEUED REQUEST ON UDB? TLNN T3,RB.PCL ;YES, QUEUED IORB REQUEST? TDCA T2,S ;NO. CLEAR IOSCP2(=TKSCHE) IF REQUEST TYPES MATCH JRST TPSCHN ;CANT DO IT IF CHE=0, PCL=1 TLNN T2,IOSCP2 ;CP2=CHE=PCL? > JRST TPSCH3 ;FOUND 1 - USE IT TPSCHN: CAMN T4,(P) ;BACK TO ORIGINAL UNIT? JRST TPSCHY ;NOTHING TO DO - NON SKIP RETURN AOBJN T4,TPSCH1 ;NEXT UNIT TPSCH2: MOVSI T2,TKSSCH ANDCAM T2,TKBSTS##(W) TPSC2A: HLRZ W,TKBCDB##(W) ;STEP TO NEXT KDB ON THIS CHANNEL MOVSI T4,TKSOFL!TKSMNT!TKSNS ;BE SURE HE'S REALLY HERE TDNE T4,TKBSTS##(W) ;IS HE? JRST [CAMN W,-1(P) ;NO, BACK TO ORIGINAL KDB ALREADY? JRST TPSCHY ;YES, EXIT JRST TPSC2A ];NO, STEP ON IORM T2,TKBSTS##(W) MOVE T4,TKBIUN##(W) ;RESET POINTER JRST TPSCH1 ;CONTINUE SEARCH ;HERE WHEN A REQUEST IS FOUND TPSCH3: IFN FTMP,< SKIPE T3,CPUTPQ## ;ANY QUEUED REQUESTS? MOVSI T3,TKSCHE ;YES TDNE T3,TKBSTS##(W) ;REQUEST FOR THIS CONTROL? SOS T3,TKBFCT##(W) ;YES, TIME TO BE FAIR? JUMPL T3,TPSCHY ;YES, LET TAPTIC HAVE IT > MOVSI T2,RB.AIO ;IS THIS REQUEST SPECIAL? TDNE T2,TRBLNK(T1) ;? PUSHJ P,UUOLVL## ;YES, ARE WE AT UUO LEVEL? JRST TPSCH4 ;AT INTERRUPT LEVEL OR NOT SPECIAL PUSH P,F ;SAVE F HRRZ F,TUBCUR##(U) ;GET DDB ADDR LDB T2,PJOBN## ;GET JOB NUMBER POP P,F ;RESTORE F CAMN T2,.CPJOB## ;CURRENT JOB (CURRENTLY SWAPPED USER)? JRST TPSCH4 ;YES, OK TO START IT HRRZ T2,TKBDSP##(W) ;CAN'T START NOW, CLANK THE PUSHJ P,TPKSCH(T2) ;SCHEDULER TO COME BACK @INTERRUPT LEVEL JRST TPSCHY ;FIX STACK AND RETURN TPSCH4: MOVEM T4,TKBCUN##(W) ;STORE CURRENT UNIT MOVSI T2,TKSSEL ;FLAG AS SELECTED IORM T2,TKBSTS##(W) ;IN KDB IORM T2,TUBSTS##(U) ;AND IN UDB HRRZ T2,TKBCDB##(W) ;LOC OF CHAN DATA BLOCK AOS (T2) ;INDICATE THAT CHAN IS BUSY MOVEI T2,MQUANT## ;SET SLICE HRRM T2,TKBSTS##(W) ; .. HLRZ T3,TUBADR##(U) ;GET KON1 ADR HLRZ T2,TUBKDB##(U) ;SETUP CURRENT KON AND ADR CAIE T2,(W) ; ... HRRZ T3,TUBADR##(U) ; ... HRLM T3,TUBAKA##(U) ;STORE UNIT ADDR HRRM W,TUBAKA##(U) ;STORE KDB ADDRESS AOS -2(P) ;SET FOR SKIP RETURN TPSCHY: POP P,(P) POP P,(P) TPSCHX: MOVSI T2,TKSSCH ;CLEAR FACT THAT WE SCHEDULED ANDCAM T2,TKBSTS##(W) ; FOR THIS KDB POPJ P, ;RETURN SUBTTL START IO ;HERE WHEN UPPER LEVEL WANTS TO START IO. THE USER JOB IS LOCKED ;AND THE IORB HAS A VALID DATA XFR LIST IF ONE IS NEEDED TAPSIO::MOVE T2,TKBSTS##(W) ;KONTROLLER STATUS TAPOFF ;GUARD AGAINST TLNE T2,TKSOFL ;CONTROLLER INTERRUPTS JRST TPONPJ ;WHICH SET CONTROLLER OFFLINE TLOE T2,TKSSEL ;SELECTED? TLZE T2,TKSSTD ;AND NOT STARTED STOPCD TAPSI3,DEBUG,KSW, ;++KONTROLLER STATUS WRONG TAPSI1: MOVE T2,TUBSTS##(U) ;UNIT STATUS TLOE T2,TKSSEL ;SELECTED? TLZE T2,TKSSTD ;AND NOT STARTED (ON ANOTHER KONTROL)? STOPCD TAPSI4,DEBUG,USW, ;++UNIT STATUS WRONG TAPSI2: MOVEI T2,RB.ACT ;SET IORB STATUS TO ACTIVE DPB T2,PRBRQS ; ... IFN FTMP,< LDB T2,DEYPCL## ;DON'T SET NON-ZERO IF JUMPE T2,TPSI2A ;IT WASN'T SKIPN T2,.CPCPN## ;TELL THW WORLD MOVEI T2,7 ; WHAT CPU IS DOING THE IO DPB T2,DEYPCL## TPSI2A:> PUSHJ P,TAPFLT ;CHECK IF FORCING HUNG DEVICE JRST TAPSI5 ;WILL HANG, DON'T START THE IORB MOVSI T2,TKSSTD ;MARK AS STARTED IORM T2,TKBSTS##(W) ;IN KDB IORM T2,TUBSTS##(U) ;AND UDB MOVE T2,TUBITM##(U) ;SET UP TIMER MOVEM T2,TUBTIM##(U) ; FOR MISSED REWIND-DONE INTERRUPT HRRZ T2,TKBDSP##(W) ;GET KONTROLLER DISPATCH PUSHJ P,TPKSIO(T2) ;CALL START IO TAPSI5: TAPON ;SAFE NOW POPJ P,0 ;HERE AFTER KSW STOPCD, TRY TO RECOVER TAPSI3: MOVEM T2,TKBSTS##(W) ;STORE REASONABLE STAUS JRST TAPSI1 ;GO CHECK UNIT STAUS ;HERE AFTER USW STOPCD TAPSI4: MOVEM T2,TUBSTS##(U) ;STORE REASONABLE STATUS JRST TAPSI2 ;GO START THE IO ;HERE TO SETUP FOR HUNG DEVICE. ;SKIP IF OPERATION OK, NON-SKIP IF FORCING DEVHNG. TAPFLT::MOVSI T2,TUSFLT ;TU FAULT BIT TDNN T2,TUBSTS##(U) ;IS THE DRIVE BROKEN? JRST CPOPJ1## ;NO, GIVE OK RETURN LDB T2,PRBFCN ;GET THE IORB FUNCTION CAIE T2,RB.FRW ;IS IT REWIND? CAIN T2,RB.FRU ;OR UNLOAD? JRST CPOPJ1## ;YES, THIS IS SAFE MOVEI T2,1 ;A SMALL HUNG TIME LIMIT DPB T2,TDYHNG## ;ONLY TRY ONCE MOVEM T2,TKBTIM##(W) ;LIMIT FOR TAPSEC POPJ P, ;GIVE FORCED DEVHNG RETURN SUBTTL ONLINE CHECK ;HERE ONCE A SECOND/MINUTE.. GROVEL THROUGH THE KDBS AND SEE ;IF THERE ARE ANY OFFLINE. IF SO, COMPLAIN THROUGH TPMOFL. ;IF ANY CLAIM TO BE OFFLINE AND ARE NOW ONLINE, INITIALIZE ;AND OPERATE A SCHEDULE CYCLE. (IT IS UNLIKELY ANYTHING WILL ; BE THERE, BUT IN CASE..) CHKKON: SKIPN W,CNFMTK## ;GET FIRST KDB JRST CPOPJ1## ;NO TAPES CHKKNL: MOVSI T1,TKSMNT ;BIT TO TEST IFN FTMP,< LDB T2,TKYCPU ;IF ON DIFFERENT CPU CAMN T2,.CPCPN## ; DONT CHECK ON THIS ONE > TDNE T1,TKBSTS##(W) ; TOO SEE IF WE SHOULD CHECK JRST CHKNXT ; IF HE IS ONLINE HRRZ T1,TKBDSP##(W) ;GET XFR VECTOR PUSHJ P,TPKONL(T1) ;SEE IF ONLINE JRST CHKOFL ;NOT ON LINE - COMPLAIN MOVSI T1,TKSOFL ;NOW ONLINE - SEE IF TDNN T1,TKBSTS##(W) ;IF FORMERLY OFFLINE. JRST CHKNXT ;NO IFE STUPID,< TLO T1,TKSSCH!TKSSTD!TKSSEL!TKSSIL!IFN FTMP, ;CLR THESE ALSO >;IFE STUPID IFN STUPID,< ;We said "SET NOMESSAGE MTx", please note! TLO T1,TKSSCH!TKSSTD!TKSSEL!IFN FTMP, >;IFN STUPID ANDCAM T1,TKBSTS##(W) ;CLEAR OFFLINE MOVSI T2,TKSSTD!TKSSEL!IFN FTMP, ;BITS TO CLEAR IN UDB MOVE T3,TKBIUN##(W) ;GET AOBJN PNTR TO LIST CHKUNL: SKIPE U,0(T3) ;UNIT PRESENT? ANDCAM T2,TUBSTS##(U) ;YES - CLEAR BITS AOBJN T3,CHKUNL ;LOOP TILL DONE HRRZ T1,TKBDSP##(W) ;YES - GET XFR VECTOR PUSHJ P,TPKINX(T1) ;CALL TO INITIALIZE IFN FTMP,< SETZB S,F > PUSHJ P,CKSIO2 ;CLANK SCHED FOR THIS KON. CHKNXT: IFN FTMP,< MOVEI T1,TKBICT## SKIPGE TKBFCT##(W) MOVEM T1,TKBFCT##(W) ;ABJECT PARANOIA > HRRZ W,TKBKDB##(W) ;GET NEXT KDB JUMPN W,CHKKNL ;IF THE IS ONE, CHECK IT. PJRST CPOPJ1## ;ELSE SKIP OVER ARG CHKOFL: IFN FTAUTC,< MOVE T1,TKBIUN##(W) ;IF A KON BUT NO UNITS SKIPN (T1) AOBJP T1,CHKNXT ;DON'T COMPLAIN ABOUT IT > PUSHJ P,@0(P) ;CALL CO-ROUTINE JRST CHKNXT ;CONTINUE LOOP ;ONCE A SECOND - JUST CHECK AND UPDATE INFO TAPSEC::PUSHJ P,CHKKON ;CRAWL THROUGH DATA BASE JRST SETOFL ;WHERE TO GO FOR OFF-LINE CTL SKIPN W,CNFMTK## ;START AT FIRST KONTROLLER POPJ P, ;NO TAPES TAPSE1: IFN FTMP,< LDB T1,TKYCPU ;IF ON DIFFERENT CPU CAME T1,.CPCPN## ; DONT DECR. TIMER ON THIS ONE JRST TAPSE5 > SOSE TKBTIM##(W) ;HUNG MTAPE? JRST TAPSE3 ;NO MOVE U,TKBCUN##(W) ;GET RIGHT UNIT MOVE U,(U) MOVSI T1,TUSFLT ;FAULTY DRIVE BIT TDNE T1,TUBSTS##(U) ;DID THE DRIVE GO BAD? JRST TAPSE2 ;YES, IGNORE SPECIAL CASE FOR SCHEDULE MOVSI T1,TKSSCH ;HUNG TRYING TO FORCE A SCHEDULE? TDNN T1,TKBSTS##(W) ;... JRST TAPSE2 ;NO, MUST BE A REAL TAPE OPERATION IFN STUPID,< MOVEI T1,TAPTIM## ;Hung count. [SPR #10-32672] MOVEM T1,TKBTIM##(W) ;Reset timer. [SPR #10-32672] >;IFN STUPID HRRZ T1,TKBDSP##(W) ;YES, TRY AGAIN PUSHJ P,TPKSCH(T1) ;BY REQUESTING ANOTHER INTERRUPT JRST TAPSE5 ;LOOK TO NEXT KONTROLLER TAPSE2: MOVE T1,TUBSTS##(U) TLNN T1,TKSSEL ;IS UNIT SELECTED? JRST TAPSE5 ;NO, BETTER HUNG THAN STOPCD MOVE F,TUBCUR##(U) ;YES, SET SO DEVCHK WILL CATCH IT MOVEI T1,1 DPB T1,PDVCNT## MOVEI S,IOACT IORM S,DEVIOS(F) TAPSE3: MOVE T1,TKBIUN##(W) ;SET TO LOOK AT ALL UNITS ON KDB MOVSI T2,TUSREW ;BITS TO CLEAR TAPSE4: SKIPE U,(T1) ;UDB EXIST? SOSE TUBTIM##(U) ;YES, TIMER GONE TO 0? CAIA ;NO ANDCAM T2,TUBSTS##(U) ;YES, CLEAR UNIT-IS-REWINDING (MISSED AN INTERRUPT) AOBJN T1,TAPSE4 ;LOOP FOR ALL UNITS ON KDB TAPSE5: HRRZ W,TKBKDB##(W) ;STEP TO NEXT KONTROLLER JUMPN W,TAPSE1 POPJ P, ;DONE - RETURN SETOFL: MOVSI T1,TKSOFL TDNE T1,TKBSTS##(W) ;ON LINE? POPJ P, ;NO - JUST RETURN IORM T1,TKBSTS##(W) ;YES - ITS OFF NOW PJRST TPMOFL## ;TELL WORLD AND RETURN ;ONCE A MINUTE - SEE IF STILL OFF LINE TAPMIN::PUSHJ P,CHKKON ;LOOK AT THINGS JRST TPMOFL## ;JUST COMPLAIN IF OFF LINE POPJ P, ;RETURN IFN FTMP,< ;HERE ONCE A TICK TAPTIC::SKIPN W,CNFMTK## ;YES, START AT 1ST KDB POPJ P, ;NO TAPES SKIPN CPUTPQ## ;ANY QUEUED REQUESTS FROM ANY CPU? JRST TAPTI4 ;NO TAPTI1: MOVSI T2,TKSCHE ;USE 1 BIT PER CPU LDB T1,TKYCPU ;IS THE KDB ON THIS CPU? CAMN T1,.CPCPN## TDNN T2,TKBSTS##(W) ;YES, DOES IT HAVE A QUEUED REQUEST? JRST TAPTI3 ;NO, TRY NEXT KDB MOVE T3,.CPQPC## ;YES, CLEAR THE DOORBELL ANDCAM T3,DOORBL## ; SINCE WE HAVE SERVICED THE REQUEST TLO S,IOSCP2 ;INDICATE WE ARE LOOKING FOR A QUEUED REQUEST MOVEI T2,TKBICT## ;IF FAIRNESS HAS GONE OFF SKIPGE TKBFCT##(W) MOVEM T2,TKBFCT##(W) ;RESET IT PUSHJ P,CKSIO2 ;TRY TO SELECT SOME UNIT ON KDB MOVSI T1,TKSCHE MOVE T2,TKBIUN##(W) ;START AT THE BEGINNING SYSPIF TLNN S,IOSCP2 ;DID WE SELECT A UNIT? ANDCAM T1,TUBSTS##(U) ;YES, CLEAR THE QUEUED REQUEST BIT TAPT1A: SKIPE T3,(T2) ;GET A UDB TDNN T1,TUBSTS##(T3) ;DOES IT HAVE A QUEUED REQUEST? JRST TAPT1B ;NO, TRY NEXT HRRZ T4,TUBQUE##(T3) ;MAYBE JUMPN T4,TAPT1C ;IS THERE AN IORB? ANDCAM T1,TUBSTS##(T3) ;NO. IT GOT DESELECTED TAPT1B: AOBJN T2,TAPT1A ;YES, TRY NEXT ANDCAM T1,TKBSTS##(W) ;NO, CLEAR BIT IN THE KDB TAPT1C: SYSPIN TLZN S,IOSCP2 ;DID WE SELECT A UDB? SOSA CPUTPQ## ;YES, DECREMENT NO OF OUTSTANDING REQUESTS JRST TAPTI3 ;NO, TRY NEXT KDB HRRZ T1,TUBQUE##(U) ;POINT AT IORB MOVE F,TUBCUR##(U) ;SET UP NEEDED ACS MOVE S,DEVIOS(F) LDB J,PJOBN## ;JOB WHICH OWNS THE UDB MOVE T2,TRBLNK(T1) ;GET IORB FLAGS TLNE T2,RB.PCL ;THERE IS A RACE WITH ^C WHICH COULD GET JRST TAPTI2 ; US HERE FOR A NON-QUEUED REQUEST MOVE T1,J ;THE JOB IS WAITING AT KONWAT PUSHJ P,EWAKE## ;SO JUST TAKE IT OUT OF EW JRST TAPTI3 ;AND KEEP ON TAPTI2: PUSHJ P,TAPTIX ;"REGULAR" ROUTE - GO START UP THE IO TAPTI3: HRRZ W,TKBKDB##(W) ;STEP TO NEXT KDB JUMPN W,TAPTI1 ;AND GO TEST IT ;HERE AFTER STARTING WHAT WE COULD TAPTI4: SKIPN T1,.CPTAP## ;ANY REQUEST FOR THIS CPU POPJ P, ;NO, GO AWAY IFN FTKL10,< SKIPG T1 ;YES, DID FILIO ALREADY SWEEP? PUSHJ P,CSDMP## ;NO, SWEEP CACHE NOW > MOVE W,CNFMTK## ;START AT BEGINNING MOVE T1,.CPCHX## ;NEEDS-A-SWEEP BIT MOVSI T2,TKSCHE ;SWEEP-WAS-DONE BIT TAPTI5: TDNN T1,TKBSTS##(W) ;DOES THIS KDB NEED A SWEEP? JRST TAPTI8 ;NO ANDCAM T1,TKBSTS##(W) ;YES, CLEAR THAT BIT SYSPIF IORM T2,TKBSTS##(W) ;AND LIGHT SWEEP-DONE MOVE T3,TKBIUN##(W) ;START AT 1ST UDB TAPTI6: SKIPE T4,(T3) TDNN T1,TUBSTS##(T4) ;CLEAR SWEEP-NEEDED, SET SWEEP-DONE JRST TAPTI7 ANDCAM T1,TUBSTS##(T4) ; FOR ALL UDBS WHICH NEEDED A SWEEP IORM T2,TUBSTS##(T4) TAPTI7: AOBJN T3,TAPTI6 SYSPIN TAPTI8: HRRZ W,TKBKDB##(W) ;STEP TO NEXT KDB JUMPN W,TAPTI5 ;GO SWITCH THE BITS FOR IT TOO MOVM T1,.CPTAP## ;GET NO OF REQUESTS WE JUST SATISFIED ADDM T1,CPUTPQ## ;AND ADD TO REQUESTS FOR ALL CPUS SETZM .CPTAP## ;CLEAR THIS-CPU-NEEDS-A-SWEEP POPJ P, ;AND EXIT ;HERE TO GET A QUEUED REQUEST STARTED ;WILL GET TO START THE IO VIA TPMDON TAPTIX: CONSO PI,II.IPA ;IF WE ARE NOT ON PI 7 PUSHJ P,SVEUB## ; TAPUUO WONT CALL SVEUF JRST TAPAGO ;CALL TAPAGO TO GET TO TPMDON TO START IO >;END IFN FTKL10 SUBTTL HUNG DEVICE TAPHNG::TAPOFF ;WHO KNOWS WHAT EVIL... HRRZ W,TUBAKA##(U) ;GET CURRENT KDB HRRZ T2,TKBDSP##(W) ;CALL KON RESET ENTRY MOVSI T1,TKSSTD TDNN T1,TUBSTS##(U) ;IF TAPE HAS BEEN STARTED JRST TAPHN1 PUSHJ P,TPKRES(T2) ; ... IFN FTEL,< MOVSI T1,(1B2) IORM T1,TUBTRY##(U) ;TELL DAEMON ITS A HUNG HRRZ P1,TUBQUE##(U) ;SETUP FOR TPEMOV PUSHJ P,TPEMOV## ;PUT STATS IN DAEMON'S PART OF TUB PUSHJ P,TPELOG## ;AND GO LOG IT > TAPHN1: MOVSI T1,TKSSTD ;CLEAR STARTED ANDCAM T1,TUBSTS##(U) ;IN UDB TLO T1,TKSSCH ;ALSO CLEAR SCH ANDCAM T1,TKBSTS##(W) ;IN KDB IFN FTMP,< MOVSI T1,TKSCHE ;SWEEP-NEEDED OR SWEEP-DONE IOR T1,.CPCHX## TDNE T1,TUBSTS##(U) ;IF EITHER IS ON SOS CPUTPQ## ;DECREMENT NO OF OUTSTANDING QUEUED REQUESTS ANDCAM T1,TUBSTS##(U) ;AND CLEAR THE BITS IN THE TUB > ;PRUNE QUEUE, DESELECT,PION TAPKIL::TAPOFF ;FIGHT RACE HRRZ W,TUBAKA##(U) ;GET KONTROLLER HRRZ T1,TUBQUE##(U) ;RETURN HEAD OF LIST MOVSI T2,TUBQUE##(U) ;RESET POINTERS MOVEM T2,TUBQUE##(U) ; ... SETZM TUBERR##(U) ;STOP ERROR RECOV MOVSI T2,TUSNS ;CLEAR HOLD ANDCAM T2,TUBSTS##(U) PUSH P,T1 ;SAVE PNTR PUSHJ P,TPCSEL ;DESELECT IF NECESSARY POP P,T1 ;RESTORE PNTR PJRST TPONPJ ;TURN ON PI AND EXIT SUBTTL HOLD/CONTINUE ;HERE TO SET NS BIT ON A UNIT TAPHLD::MOVSI T1,TUSNS ;SET NO SCHEDULE IORM T1,TUBSTS##(U) ;... IFN FTMP,< PUSHJ P,CHKCP## JRST [MOVEI T1,1 HRRM T1,TKBSTS##(W) POPJ P,] > MOVSI T1,TKSSTD ;SEE IF STARTED TDNE T1,TUBSTS##(U) ;... JRST [HLLZS TKBSTS##(W) ;GRNTEE NO MORE POPJ P,] ;RETURN TPCSEL: MOVSI T1,TKSSEL ;SEE IF SELECTED TDNN T1,TUBSTS##(U) POPJ P, ;NOT SELECTED - EXIT PUSHJ P,TAPDSL ;YES - DESELECT PJRST CKSIO1 ;CLANK SCHED IF NECESSARY ;ROUTINE CALLED TO ALLOW UNIT TO SCHEDULE AGAIN TAPCNT::MOVSI T1,TUSNS ANDCAM T1,TUBSTS##(U) ;CLEAR NS BIT HLRZ W,TUBKDB##(U) ;CHECK ONE KONT PUSHJ P,CKSIO1 ; ... JUMPN W,CPOPJ## HRRZ W,TUBKDB##(U) ;AND THEN THE OTHER ;FALL INTO CKSIO1 CKSIO1: JUMPE W,CPOPJ## ;IF NONE, PUNT IFN FTMP,< LDB T2,TKYCPU ;CPU WHICH OWNS CONTROL DPB T2,DEYCPF## ;LET REST OF WORLD KNOW PUSHJ P,CHKCPI## ;ARE WE ON THAT CPU? PJRST PCLTAP ;NO, QUEUE THE REQUEST > IFN BUGFIX,< TLZ S,IOSCP2 ;Clear bit. [JE] >;IFN BUGFIX CKSIO2: HRRZ T3,TKBCDB##(W) ;POINT AT CHAN DATA BLOCK MOVSI T2,TKSSEL!TKSSCH!TKSOFL SYSPIF SKIPGE (T3) ;IS CHAN BUSY? TDNE T2,TKBSTS##(W) ; ARE ANY OF THESE ON? JRST ONPOPJ## ;YES - SOMETHING WILL HAPPEN MOVSI T2,TKSSCH ;SET SCHED REQUESTED IORM T2,TKBSTS##(W) ;... AOS (T3) ;INDICATE THAT CHAN IS BUSY SYSPIN PUSH P,U ;SAVE U PUSHJ P,TAPSCH ;TRY TO START SOMETHING JRST CKSIO3 ;NOTHING TO DO, RETURN FOR NOW IFN FTMP,< TLZE S,IOSCP2 JRST CKSIO4 > PUSH P,F ;SAVE F MOVE T1,TUBQUE##(U) ;CURRENT IORB PUSHJ P,TPMSIO## ;CRANKUP THE I/O JRST FUPOPJ## ;RESTORE F,U,AND RETURN CKSIO3: MOVE U,(P) ;RESTORE U CKSIO4: HRRZ T1,TKBCDB##(W) SOS (T1) ;INDICATE CHAN IS NOT BUSY JRST TPOPJ## ;MAKE STACK RIGHT AND RETURN IFN FTMP,< PCLTAP: HRRZ T1,TUBQUE##(U) ;GET IORB ADDRESS IFE BUGFIX,JUMPE T1,PCLTP1 ;NONE?????? IFN BUGFIX,JUMPE T1,CPOPJ## ;None?????? [JE] MOVE T1,TRBLNK(T1) ;GET IORB FLAGS TLNE T1,RB.PCL ;IS THIS A QUEUED REQUEST? JRST PCLTP1 ;YES PUSHJ P,TSLEE1## ;NO, LET THE NON-QUEUED STUFF FINISH JRST CKSIO1 ; BEFORE GETTING INTO QUEUED REQUESTS PCLTP1: PUSHJ P,CPUOFS## ;GET CPU WHICH OWNS THE DEVICE SKIPG .C0OK##(T1) ;IS THAT CPU ALIVE AND WELL? JRST PCLTP2 ;YES PUSHJ P,HNGSTP## ;NO, "PROBLEM ON DEVICE" JRST PCLTAP ;AND TRY, TRY AGAIN PCLTP2: MOVE T2,.CPCHX## ;INDICATE WE NEED CACHE SWEEP SYSPIF IORM T2,TUBSTS##(U) ;DONT SCHED UNIT TILL SWEEP IORM T2,TKBSTS##(W) SKIPLE .CPTAP## ;COUNT UP A REQUEST AOSA .CPTAP## SOS .CPTAP## ; (.CPTAP COULD BE NEGATIVE) SYSPIN PJRST SETQPB## ;RING THE DOORBELL ON THE OWNING CPU ;SUBROUTINE TO GET JOB ONTO THE CPU WHICH OWNS THE DEVICE TOCPU:: HLRZ W,TUBKDB##(U) SKIPN W HRRZ W,TUBKDB##(U) PUSH P,T1 TOCPU1::LDB T1,TKYCPU ;CPU WHICH OWNS THE DEVICE PUSHJ P,ONCPUS## ;GET US ONTO THAT CPU JRST [PUSHJ P,HNGSTP## JRST TOCPU1] JRST TPOPJ## ;AND RETURN > SUBTTL QUEUE MANIPULATION ;HERE TO INSERT AN IORB AT THE HEAD OF A UNIT QUEUE ;U/ UDB, T1/ IORB CPURQH:: IFN FTMP,< PUSHJ P,TOCPU > TAPRQH::MOVEI T2,RB.RPN ;SET IORB TO PENDING DPB T2,PRBRQS ; ... TAPOFF ;FIGHT RACE HRRZ T2,TUBQUE##(U) ;GET HEAD POINTER HRRM T2,TRBLNK(T1) ;FORWARD LINK HRRM T1,TUBQUE##(U) ;NEW HEAD PUSHJ P,TAPCNT ;SEE IF THE CHANNEL NEEDED TO BE POKED PJRST TPONPJ ;RESTORE INTS AND EXIT ;HERE TO INSERT AN IORB AT THE TAIL OF A UNIT QUEUE ;U/UDB, T1/IORB CPURQT:: IFN FTMP,< PUSHJ P,TOCPU > TAPRQT::MOVEI T2,RB.RPN ;SET IORB AS PENDING DPB T2,PRBRQS ; ... TAPOFF ;FIGHT RACE HLRZ T2,TUBQUE##(U) ;GET TAIL POINTER HRRM T1,TRBLNK(T2) ;FORWARD LINK AT OLD TAIL HRLM T1,TUBQUE##(U) ;NEW TAIL POINTER PUSHJ P,TAPCNT PJRST TPONPJ ;RETURN ;HERE TO REMOVE THE IORB FROM THE HEAD OF A UNIT QUEUE TAPREM::TAPOFF ;FIGHT RACE HRRZ T1,TUBQUE##(U) ;GET CURRENT HEAD JUMPE T1,TPONPJ ;EXIT IF NONE HRRZ T2,TRBLNK(T1) ;FOLLOW FORWARD LINK HRRM T2,TUBQUE##(U) ;NEW HEAD POINTER HLRZ T3,TUBQUE##(U) ;CHECK IF QUEUE ONLY HAD ONE ELEMENT CAIE T3,(T1) ;... JRST TPONPJ ;NO - LEAVE MOVSI T2,TUBQUE##(U) ;MAKE TAIL POINT TO QUEUE HEAD MOVEM T2,TUBQUE##(U) ; ... TPONPJ: TAPON ;ALLOW INTS POPJ P, ;HERE WHEN UPPER LEVEL DECIDES THAT A SELECTED IORB IS NOT TO ;BE INITIATED AFTER ALL TAPFLS::PUSHJ P,TAPDSL ;FLUSH HDWRE PUSHJ P,TAPREM ;AND PRUNE QUEUE PUSHJ P,UUOLVL## ;IF NOT ON UUO LEVEL (DIAG) POPJ P, ; RETURN WITHOUT STARTING ANYTHING PUSH P,T1 ;SAVE T1 PUSHJ P,CKSIO1 ;SEE IF SCHED CYCLE NEEDED MOVSI T1,TKSSEL TDNN T1,TUBSTS##(U) ;DID THIS UNIT GET SELECTED AGAIN? TDON T1,TKBSTS##(W) ;NO, DID SOME OTHER UNIT GET SEL'D? JRST TPOPJ## ;NO, RETURN TLNE T1,TKSSTD ;YES, WAS IT ACTUALLY STARTED? JRST TPOPJ## ;YES, RETURN PUSH P,U ;NO, SAVE U MOVE U,TKBCUN##(W) MOVE U,(U) ;SET U TO RIGHT UNIT MOVSI T1,TKSSEL ;NO UNIT IS ACTUALLY STARTED ANDCAM T1,TUBSTS##(U) ; NOW MOVSI T1,TKSSCH ;INDICATE WE'RE REQUESTING A SCHEDULE IORM T1,TKBSTS##(W) ;FOR THIS KONTROLLER MOVE T1,[TKBICT##,,TAPTIM##] HRRZM T1,TKBTIM##(W) ;SET TIMER TO CATCH LOST INTERRUPT IFN FTMP,< HLRZM T1,TKBFCT##(W) ;ENSURE TAPSCH FINDS IT > MOVE T1,TKBCDB##(W) ;MARK CHAN AVAILABLE SETOM (T1) HRRZ T1,TKBDSP##(W) PUSHJ P,TPKSCH(T1) ;GO CAUSE AN INTERRUPT ON THAT UNIT POP P,U ;RESTORE U JRST TPOPJ## ;RESTORE T1 AND EXIT SUBTTL NOTIFY OPERATOR OF KONTROLLERS WITH DOWN-LEVEL MICROCODE ;HERE TO TYPE OUT MESSAGE FOR WRONG MICROCODE ;CALL WITH T1/ MICROCODE VERSION,,[ASCIZ PREFIX STRING] ;OR WITH T1/ -1,,[ASCIZ TEXT] TAPREV::PUSHJ P,SAVT## ;SAVE ACS FOR OUR CALLERS PUSH P,U ;SAVE UNIT PUSH P,F ;SAVE FROM DESTRUCTION PUSHJ P,TTYERO## ;SET UP U WITH OPR LDB USUALLY PUSHJ P,INLMES## ;TYPE MESSAGE ASCIZ / %Tape controller / ;SAY WHAT DEVICE MOVE T2,TKBNAM##(W) ;GET KON NAME ADD T2,['A'-'0',,0] ;EXTERNALIZE IT PUSHJ P,PRNAME## ;TELL OPERATOR PUSHJ P,INLMES## ;FINISH THIS LINE ASCIZ / is below required microcode revision levels % / ;AND FLAG THE NEXT LINE HRRZ T1,-4(P) ;RETRIEVE CALLER'S TEXT POINTER PUSHJ P,CONMES## ;TYPE THAT TOO SKIPGE -4(P) ;SEE IF VERSION GIVEN JRST TAPRV1 ;NO, SKIP THIS PUSHJ P,PRSPC## ;SPACE OVER FOR NUMBER HLRZ T1,-4(P) ;GET REVISION NUMBER PUSHJ P,PRTDI8## ;TYPE THE NUMBER (OCTAL) TAPRV1: PUSHJ P,CRLF## ;TYPE THE CRLF JRST FUPOPJ## ;RETURN, RESTORING ALL ACS USED SUBTTL ERROR RECOVERY PROCEDURE. ;CALL HERE FROM TPMDON WHEN ERROR RECOVERY IS TO BE INITIATED ;SELECT MUST BE ON FOR KDB AND UDB. IORB IN T1. TAPERP::MOVEI T1,TKBERB##(W) ;ENQUEUE ERP IORB HLLOS TKBSTS##(W) ;SET INFINITE QUANTUM PUSHJ P,TAPRQH ;THIS IS CHEATING SLIGHTLY HRRZ T1,TRBLNK+TKBERB##(W) ;RECOVER ORIGINAL IORB LDB T2,PRBFCN ;GET FUNCTION CODE LDB T3,ERYCNT ;GET INITIAL RETRY COUNT DPB T3,TUYECT ;SET IN TUBERR SETZM TUBTRY##(U) ;CLEAR ATTEMPT COUNTER PUSHJ P,ERPCMV ;CHECK IF TAPE MOVED TDZA T4,T4 ;NO MOVE MOVNI T4,1 ;MOVED - ADJUST POSITION SKIPL ERCTAB(T2) ;WAS OP FORWARD MOTION? MOVNS T4 ;NO - FIX COUNT ADD T4,TUBREC##(U) ;GET CORRECTED COUNT JUMPL T4,[SETOM TUBPBE##(U) ;IF NEG REC COUNT JRST ERP0] ;THEN WE WON'T POS CHECK RIGHT HRL T4,TUBFIL##(U) ;ALSO COMPARE FILE POSITION MOVEM T4,TUBPBE##(U) ;STORE POSITION BEFORE ERROR JRST ERP0 ;START ERP ;HERE ON AN INTERRUPT WHILE THE ERP IS RUNNING ERPINT: CAIE T1,TKBERB##(W) ;BE REAL SURE ALL IS WELL STOPCD .,STOP,ERF, ;++ERP REALLY FOULED UP HRRZ T2,TUBERR##(U) ;GET DISPATCH ADDR SKIPE T2 ;CODE ZERO IS ILLEGAL CAIL T2,XERPMX ;SMALLER THAN MAX? STOPCD .,STOP,RFU, ;++RECOVERY FOULED UP MOVE F,TUBCUR##(U) ;SET UP F AND S MOVE S,DEVIOS(F) JRST @ERPSTB(T2) ;THE LEAP OF FAITH ;HERE TO SEE IF ANYTHING OFFENSIVE HAS HAPPENED TO ;THE IORB IN T1 ANYERR: SKIPL TRBLNK(T1) ;IS EXCEPTION UP? POPJ P, ;NO - ALL IS WELL. MOVE T2,TRBSTS(T1) ;GET STATUS WORD TLNN T2,RB.SER!RB.SED!RB.SLK!RB.SOL!RB.STL ;... POPJ P, ;NOTHING TO OFFEND JRST CPOPJ1## ;LOSE ;HERE TO COPY NEEDED THINGS TO THE ERP IORB SETERB: HRRZ T1,TRBLNK+TKBERB##(W) ;GET OLD IORB HLLZ T3,TRBLNK(T1) ;GET MODE ETC TLZ T3,RB.EXC ;CLEAR EXCEPTION BIT HLLM T3,TRBLNK+TKBERB##(W) ;STORE IN NEW IORB HRRZ T3,TRBXCW(T1) ;GET XFR LIST ADDR MOVEM T3,TRBXCW+TKBERB##(W) ;STORE MOVE T3,TRBRCT(T1) ;COPY WORDCOUNT (FOR TM02) MOVEM T3,TRBRCT+TKBERB##(W) HLLZ T3,TRBEXL(T1) ;GET END OF XFR LIST MOVEM T3,TRBEXL+TKBERB##(W) ;STORE POPJ P, ;HERE TO SETUP ERP IORB FOR A NON DATA XFR OP STERBS: PUSHJ P,SETERB ;SETUP ERB MOVEI T1,1 ;SET OP COUNT HRRM T1,TRBXCW+TKBERB##(W) ;... HRRZS TRBEXL+TKBERB##(W) ;ALSO CLEAR END OF LIST MOVEI T1,TKBERB##(W) ;ERR REC IORB POPJ P, ;HERE TO CLEAN UP WHEN LEAVING THE ERP FOR THE LAST TIME ERPDON: HRRZ T2,TRBLNK+TKBERB##(W) ;PNTR TO ACTUAL IORB MOVE T3,TRBRCT+TKBERB##(W) ;LAST BYTE COUNT MOVEM T3,TRBRCT(T2) ;INTO IORB PUSHJ P,TAPREM ;REMOVE ERP IORB MOVE T2,TUBERR##(U) ;SAVE STATE WORD AT TERMINATION MOVEM T2,TUBFES##(U) ;AS FINAL ERROR STATE SETZM TUBERR##(U) ;CLEAR STATE INFO HLLZS TKBSTS##(W) ;CLEAR CHANNEL QUANTUM POPJ P, ;ERP ACTION 0 - REPOSITION IF NEEDED. IORB IN T1 ;FCN CODE IN T2 ERP0: PUSHJ P,ERPCMV ;CHECK MOVEMENT JRST ERP2 ;NO - NO NEED TO REPOSITION MOVSI T3,(ERCRPS) ;SHOULD REPOSITIONING BE DONE? TDNN T3,ERCTAB(T2) ; ... JRST ERP2 ;NO - GO RETRY PUSHJ P,STERBS ;YES - SETUP ERP IORB MOVEI T4,RB.FBR ;ASSUME FORWARD MOTION, REPOS W/ BS SKIPL ERCTAB(T2) ;WAS OP FORWARD MOTION? MOVEI T4,RB.FSR ;NO-REPOS WITH FWD SPACE DPB T4,PRBFCN ;STORE FUNCTION CODE MOVEI T2,XERP1 ;SET NEXT STATE ;HERE TO EXIT AND START IO ON ERP IORB ERPX0: HRRM T2,TUBERR##(U) ;STORE NEXT STATE MOVEI T1,TKBERB##(W) ;GET ERP IORB PUSHJ P,TAPSIO ;GO INITIATE OP SETZ T1, ;RETURN ZERO POPJ P, ;HERE AT TERMINATION OF A REPOSITION ERP1: MOVSI T2,RB.SNM!RB.SOL ;MOVED OR OFF-LINE? TDNN T2,TRBSTS(T1) JRST ERP1A ;SEE IF SPECIAL ACTION ;HERE WHEN RECOVERY HAS FAILED ERP4: HRRZ T3,TRBLNK+TKBERB##(W) ;ORIG IORB MOVSI T2,RB.SOL ;OFFLINE BIT TDNE T2,TRBSTS(T1) ;CHECK STATUS IORM T2,TRBSTS(T3) ;COPY BIT TO ORIG. IORB PUSHJ P,ERPDON ;CLEAN UP HRRZ T1,TUBQUE##(U) ;GET FORMER IORB MOVSI T2,RB.SER ;FLAG NON REC ERROR IORM T2,TRBSTS(T1) ;IN IORB POPJ P, ;RETURN FAILING IORB ;SEE IF THE LAST OP SHOULD BE ERASED. ERP1A: HRRZ T1,TRBLNK+TKBERB##(W) ;GET ORIGINAL OP LDB T2,PRBFCN ; ... CAIE T2,RB.FWT ;WRITE? CAIN T2,RB.FTM ;OR WRITE TAPE MARK? JRST ERP5 ;YES JRST ERP2 ;NO - DO RETRY NOW. ;MORE ERROR RECOVERY PROCEDURE ;HERE TO RETRY A FAILING OPERATION. THE TAPE HAS BEEN ;REPOSITIONED IF NECESSARY ERP2: MOVE T3,TUBPBE##(U) ;GET POSITION BEFORE ERROR JUMPL T3,ERP2A ;SKIP CHECK IF NEG. MOVE T2,TUBREC##(U) ;CHECK THAT REPOSITIONING HRL T2,TUBFIL##(U) ;HAS BROUGHT US CAME T2,T3 ;BACK TO BEFORE THE ERROR JRST ERP4 ERP2A: PUSHJ P,SETERB ;COPY NEEDED GOODIES HRRZ T1,TRBLNK+TKBERB##(W) ;GET OLD IORB LDB T2,PRBFCN ;GET FUNCTION LDB T3,ERYFCN ;GET FUNCTION TO RETRY MOVEI T1,TKBERB##(W) ;GET ERP IORB DPB T3,PRBFCN ;STORE NEW OP. AOS TUBTRY##(U) ;INCREMENT ATTEMPT COUNT MOVEI T2,XERP3 ;SET NEXT STATE JRST ERPX0 ;HERE ON THE TERMINATION OF A RETRY OPERATION ERP3: PUSHJ P,ANYERR ;ANY ERRORS TO SPEAK OF? JRST ERP3B ;NO - WIN WIN WIN MOVSI T2,RB.SOL!RB.SER ;OFFLINE OR NON-RECOVERABLE TDNE T2,TRBSTS(T1) ;??? JRST ERP4 ;YES - LOSAGE LDB T2,TUYECT ;GET RETRY COUNTER SUBI T2,1 ;DECREMENT JUMPLE T2,ERP4 ;SIGH - LOSE DPB T2,TUYECT ;RESTORE COUNT MOVSI T1,NXTLSE ;GET NEXT TO LAST RETRY BIT ANDCAM T1,TUBERR##(U) ;CLEAR IT CAIN T2,2 ;IS THIS NEXT TO LAST RETRY? IORM T1,TUBERR##(U) ;YES--THEN SET IT HRRZ T1,TRBLNK+TKBERB##(W) ;GET OLD IORB LDB T2,PRBFCN ;GET FUNCTION MOVE T4,TUBTRY##(U) ;RE-TRY COUNTER MOVSI T3,(ERCTCS) ;THIS OP USE TCS? TDNE T3,ERCTAB(T2) ;?? TRNE T4,3 ;TCS EVERY 4 RE-TRIES JRST ERP3A ;NO TCS NOW JRST ERP7 ;TCS TIME NOW ;HERE TO PERFORM REPOS/RETRY ERP3A: MOVEI T1,TKBERB##(W) ;SET UP ERROR IORB LDB T2,PRBFCN ;AND FUNCTION JRST ERP0 ;AND TRY THE WHOLE THING AGAIN ;HERE WHEN THE ERROR IS RECOVERED. THE WORLD IS AMAZED. ERP3B: MOVSI T2,RB.SNM ;CHECK MOVEMENT TDNE T2,TRBSTS(T1) ;DID IT? JRST ERP3C ;NO - TRY AGAIN PUSHJ P,ERPDON ;GO CLEAN UP HRRZ T1,TUBQUE##(U) ;GET OLD IORB MOVSI T2,RB.SRE ;RECOVERY SUCCEEDED IORM T2,TRBSTS(T1) ;SET IN IORB POPJ P, ;RETURN AND REJOICE ;HERE WHEN RETRY DIDN'T MOVE TAPE TRY AGAIN ERP3C: LDB T2,TUYECT ;GET COUNTER SUBI T2,1 ;DECREMENT JUMPLE T2,ERP4 ;ALL THROUGH IF ZERO DPB T2,TUYECT ;PUT COUNT BACK JRST ERP2 ;AND RETRY OP ;HERE TO DO AN ERG BEFORE RETRY ERP5: PUSHJ P,STERBS ;SETUP ERB MOVEI T2,RB.FLG ;GET ERG FUNCTION DPB T2,PRBFCN ;STORE IN ERP IORB MOVEI T2,XERP6 ;NEXT STATE JRST ERPX0 ;EXIT AND SET STATE ;HERE AT THE TERMINATION OF AN OP BEFORE RETRY. ERP6: PUSHJ P,ANYERR ;ERRORS? JRST ERP2 ;NO - DO RETRY JRST ERP4 ;YES - FAIL ;ERROR RECOVERY TAPE CLEANER SEQUENCE (TCS) ;FCN CODE IN T2 ;HERE TO STARTUP TCS ERP7: MOVEI T1,TKBERB##(W) ;GET RETRY IORB MOVSI T3,RB.SBT!RB.SAP ;AT BOT OR ALREADY REPOSITIONED? TDNE T3,TRBSTS(T1) ; ??? JRST ERP3A ;YES - NO TCS MOVEI T4,ERPNCS ;NUMBER OF SPACE OPS IN TCS SKIPL ERCTAB(T2) ;WAS OP FORWARD MOTION? SUBI T4,1 ;NO - USE ONE LESS BACKSPACE DPB T4,TUYEC1 ;STORE IN SECONDARY COUNTER ;HERE TO DO A BACKSPACE AS PART OF A TAPE CLEANER SEQ ERP8: PUSHJ P,STERBS ;SETUP IORB MOVEI T2,RB.FBR ;BACKSPACE FUNCTION DPB T2,PRBFCN ;STORE MOVEI T2,XERP9 ;NEXT STATE JRST ERPX0 ;LEAVE ;HERE WHEN A TCS BACKSPACE HAS COMPLETED ERP9: LDB T2,TUYEC1 ;GET COUNT SOSL T2 ;DECREMENT DPB T2,TUYEC1 ;SAVE NEW VALUE HLRZ T3,TRBSTS(T1) ;GET STATUS TRNE T3,RB.SBT ;DONE? JRST ERP9B ;YES - RECOMPUTE SPACE COUNT TRNE T3,RB.SNM ;DID IT MOVE AT ALL JRST ERP4 ;NO -******SHOULD FIX POSITION**** JUMPG T2,ERP8 ;TRY AGAIN IF STILL MORE TO GO MOVEI T4,ERPNCS-1 ;NUMBER OF SPACE OPS JRST ERP9C ERP9B: MOVEI T4,ERPNCS-2 ;COMPUTE NUMBER OF SPACE OPS LDB T2,TUYEC1 ; ... SUB T4,T2 ; ... ERP9C: HRRZ T1,TRBLNK+TKBERB##(W) ;GET ORIG IORB LDB T2,PRBFCN ;ORIG FCN MOVEI T1,TKBERB##(W) ;RESTORE ERROR IORB SKIPL ERCTAB(T2) ;WAS OP FORWARD MOTION? ADDI T4,1 ;NO - ONE MORE THEN DPB T4,TUYEC1 ;STORE COUNT JUMPLE T4,ERP2 ;NONE - GO TRY AGAIN ;FALL THROUGH INTO ERP10. ;FALL THROUGH HERE FROM ERP9C. ;HERE TO DO A SPACE RECORD AS PART OF A TCS ERP10: PUSHJ P,STERBS ;SETUP IORB MOVEI T2,RB.FSR ;SPACE OP DPB T2,PRBFCN ;STORE MOVEI T2,XERP11 ;NEXT STATE JRST ERPX0 ;START IO AND EXIT ;HERE ON THE TERMINATION OF A TCS SPACE OP ERP11: HLRZ T2,TRBSTS(T1) ;GET STATUS TRNE T2,RB.SNM ;MOVED? JRST ERP4 ;NO ****SHOULD FIX POSN**** LDB T2,TUYEC1 ;GET COUNT SUBI T2,1 ;DECREMENT DPB T2,TUYEC1 ;RESTORE JUMPLE T2,ERP2 ;CONTINUE RETRY JRST ERP10 ;MORE SPACES TO DO ;TABLE RELATING STATE CODES TO ROUTINE ADDRS. ERPSTB: PHASE 0 0,,-1 ;ILLEGAL XERP1:! ERP1 ;REPOSITION TERMINATION XERP3:! ERP3 ;RETRY TERMINATION XERP6:! ERP6 ;ERASE GAP TERMINATION XERP9:! ERP9 ;TCS BACKSPACE TERMINATION XERP11:! ERP11 ;TCS SPACE TERMINATION XERPMX:! ;HIGHEST STATE DEPHASE ;TABLE USED TO GUIDE THE ERROR RECOVERY PROCEDURE ;BITS ERCFWD==1B0 ;OPERATION MOVES TAPE FOREWARD ERCRPS==1B1 ;OPERATION NEEDS REPOSITION BEFORE RETRY ERCCSZ==1B2 ;THIS OP IGNORE "NOISE" RECORDS ERCTCS==1B3 ;THIS OP USES TCS ;BYTES AND BYTE POINTERS ERCCTP==^D17 ;INITIAL RETRY COUNT POSITION ERCCTS==6 ;INITIAL RETRY COUNT SIZE ERYCNT: POINT ERCCTS,ERCTAB(T2),ERCCTP ERCFNP==^D35 ;RETRY FUNCTION POSITION ERCFNS==5 ;RETRY FUNCTION SIZE ERYFCN: POINT ERCFNS,ERCTAB(T2),ERCFNP ;MACRO TO BUILD ERCTAB ENTRY DEFINE X(FLGS,CNT,FCN) < EXP FLGS+B+B > ;THE TABLE ERCTAB: EXP -1 ;ILLEGAL X(ERCFWD+ERCRPS+ERCCSZ+ERCTCS,^D40,RB.FCR) ;READ FORWARD X(ERCFWD+ERCRPS,^D14,RB.FWT) ;WRITE X(ERCRPS+ERCCSZ+ERCTCS,^D40,RB.FRB) ;READ BACKWARDS X(ERCFWD+ERCRPS,6,RB.FSR) ;SKIP RECORD X(ERCRPS,6,RB.FBR) ;BACKSPACE RECORD X(ERCFWD+ERCRPS,6,RB.FSF) ;SKIP FILE X(ERCRPS,6,RB.FBF) ;BACKSPACE FILE X(ERCFWD,6,RB.FLG) ;ERASE GAP X(ERCFWD,6,RB.FSE) ;DATA SECURITY ERASE X(0,6,RB.FRW) ;REWIND X(0,6,RB.FRU) ;REWIND AND UNLOAD X(ERCFWD+ERCRPS,^D14,RB.FTM) ;TAPE MARK X(ERCFWD,1,RB.FYB) ;YELLOW BALL X(ERCFWD+ERCRPS+ERCCSZ,6,RB.FCR) ;CORRECTION READ (ONLY IF USER REQD) X(ERCFWD+ERCRPS+ERCCSZ+ERCTCS,^D40,RB.FCR) ;READ LOW THRESHOLD ;ROUTINE CHECK IF TAPE MOVED OR ERROR ON NOISE RECORD ;CALL: MOVE T1,IORB ; MOVE T2,FCN ; PUSHJ P,ERPCMV ; RETURN IF NO MOVEMENT ; RETURN IF MOVEMENT ERPCMV: MOVE T4,TRBRCT(T1) ;GET BYTE COUNT MOVSI T3,(ERCCSZ) ;SIZE CHECK? TDNN T3,ERCTAB(T2) ;... JRST ERPCM1 ;NO - PROCEED CAIGE T4,NOISE## ;IS THIS A NOISE RECORD JUMPGE T4,CPOPJ## ;NOISE IF NOT AN IOWD - DIDN'T MOVE ERPCM1: MOVSI T3,RB.SNM!RB.SAP ;NO - CHECK PHYSICAL MOVEMENT TDNN T3,TRBSTS(T1) ;... AOS 0(P) ;OK POPJ P, ;RETURN SUBTTL COMMON ROUTINES ;ROUTINES COMMON TO ALL KONTROLLER DEPENDENT CODE ;HERE ON REWIND DONE REWDON::MOVSI T2,TUSREW!TUSFLT ;NO LONGER REWINDING ANDCAM T2,TUBSTS##(U) ;... UNIBOT::MOVSI T2,TUSBOT ;ALSO NOW AT BOT IORM T2,TUBSTS##(U) ; ... SETZM TUBREC##(U) ; ... SETZM TUBFIL##(U) ; ... POPJ P, ;HERE TO VERIFY THAT TUBQUE POINTS TO A REASONABLE IORB CHKIRB::HRRZ T1,TUBQUE##(U) ;GET HEAD IORB JUMPE T1,CPOPJ## ;EXIT IF NOT REQUEST BLOCK LDB T2,PRBRQS ;GET REQUEST STATUS CAIN T2,RB.ACT ;ACTIVE? AOS (P) ;YES - GIVE GOOD RETURN POPJ P, ;ROUTINE TO HANDLE SPURIOUS INTERRUPTS TAPDIS::HRRZ T1,TKBDSP##(W) ;GET DISPATCH PUSHJ P,TPKIDL(T1) ;SET CTRL IDLE (USER WILL GET HUNG DEVICE) MOVSI T2,TKSSCH ;TEST SCHED REG. BIT MOVEI T1,0 ;ASSUME IGNORE INT. TDNE T2,TKBSTS##(W) ;WANT SCHED. CYCLE? MOVNI T1,1 ;YES- INFORM WORLD POPJ P, ; AND EXIT ;ROUTINE TO SET UP U TO POINT TO UDB MENTIONED IN T2 ;C(T2) = UNIT # , C(W) = KDB ADDRS ;NON-SKIP RETURN LF NON-EX UNIT ;SKIP RETURN IF UNIT IS OK SETUDB::MOVEI U,TKBUDB##(W) ;BASE ADDRS ADD U,T2 ;PLUS OFFSET SKIPN U,0(U) ;SEE IF ONE EXISTS POPJ P, PJRST CPOPJ1## ;TABLE USED TO CONVERT IORB MODE TO CHARS/WORD TMODTB::0 ;0 - ILLEGAL 5 ;1 - 9-TK CORE DUMP 4 ;2 - 9-TK INDUSTRY COMPAT. 6 ;3 - TU70 SIXBIT 5 ;4 - TU70 MARVELOUS ASCII 6 ;5 - 7-TK CORE DUMP ;TABLE TO CONVERT IORB MODE TO FRAME SIZE TMODFS::0 ;0 - ILLEGAL 0 ;1 - CORE DUMP (N/A) 8 ;2 - 9 TK INDUSTRY COMPATIBLE 6 ;3 - SIXBIT 7 ;4 - ASCII 0 ;5 - 7 TK CORE DUMP (N/A) TPSEND: END