$CONTROL MAP,CODE,USLINIT                                               00010000
<<PFAIL - MODULE 30>>                                                   00012000
<< HP32033C MPE SOURCE C.00.00 >>                                       00014000
$COPYRIGHT     "(C) COPYRIGHT HEWLETT-PACKARD CO. 1980. ",            & 00016000
$     "THIS PROGRAM MAY BE USED WITH ONE COMPUTER SYSTEM AT A ",      & 00018000
$     "TIME AND SHALL NOT OTHERWISE BE RECORDED, TRANSMITTED OR ",    & 00020000
$     "STORED IN A RETRIEVAL SYSTEM.  COPYING OR OTHER REPRODUCTION ",& 00022000
$     "OF THIS PROGRAM EXCEPT FOR ARCHIVAL PURPOSES IS PROHIBITED ",  & 00024000
$     "WITHOUT THE PRIOR WRITTEN CONSENT OF HEWLETT-PACKARD COMPANY."   00026000
$CONTROL UNCALLABLE,PRIVILEGED,MAIN=PFAIL                               00028000
$TP                                                                     00030000
$TITLE "POWERFAIL RESTART/RECOVERY PROCESS"                             00032000
BEGIN                                                                   00034000
                                                                        00036000
EQUATE                                                                  00038000
   ICF'55      = 4,   <<CPU # OF ICF55>>                       <<03045>>00040000
   POWERFAIL   = %72, << SYSDB INDEX >>                                 00042000
   PFAILURE    = 65,  << OPCODE TO TELL DRIVER PFAILED >>               00044000
   SYSDB       = %1000,                                                 00046000
   SYSLPDT     = %10,                                                   00048000
   DINIL       = 7,                                            <<00.04>>00050000
   DIOQP       = 2,   << DIT INDEX TO IOQ POINTER >>                    00052000
   DDLTP       = 4,   << DIT INDEX TO DVR LINK TABLE PTR >>             00054000
   DILTP       = 5,   << DIT INDEX TO ILT >>                            00056000
   DMNTR       = 1,   << DLT INDEX TO MONITOR PLABEL >>                 00058000
   ICNTRL      = 7,   << CONTROLLER INFO OF ILT >>                      00060000
   IMASK       = 7,   << INTERRUPT MASK WORD >>                         00062000
   IMASK55     = %32, <<4 WORD INT MASK FOR ICF/55>>           <<03045>>00064000
   JUNKWAIT    = -%20,                                                  00066000
   JUNK'IOWAIT = -%120,                                                 00068000
   CONSLDEV    = %74, << SYSDB INDEX >>                                 00070000
   QI          = 5;                                                     00072000
                                                                        00074000
DEFINE                                                                  00076000
   DRTNUMBER   = (7:9)#,  <<DRT NUMBER FIELD IN ILT>>          <<03045>>00078000
   CHAN'NUM    = (9:4)#,  <<4-BIT-CHANNEL NUMBER>>             <<03045>>00080000
   IMB'NUM     = (7:2)#,  <<2-BIT-IMB NUMBER>>                 <<03045>>00082000
   QPFAILS     = (11:1)#, << PFAIL TO BE INDICATED BY ATTACHIO >>       00084000
   ABORT       = (0:1)#,  << ABORT BIT OF IOQ >>                        00086000
   ABS         = ABSOLUTE#,                                             00088000
   ASMB        = ASSEMBLE#,                                             00090000
   DIRCSTATE   = (0:2)#,   << DEVICE RECOGNITION STATE IN LPDT >>       00092000
   DISABLE     = ASSEMBLE(SED 0)#,                                      00094000
   ENABLE      = ASSEMBLE(SED 1)#,                                      00096000
   IAK         = (8:1)#,  << INTERRUPT ACKNOWLEDGE BIT OF DIT >>        00098000
   MAXENTRY    = (0:8)#,  << # OF ENTRIES IN LPDT >>                    00100000
   PDISABLE    = ASMB(PSDB)#,                                           00102000
   PENABLE     = ASMB(PSEB)#,                                           00104000
   PF          = ABS(SYSDB+POWERFAIL)#,                                 00106000
   PFAIL       = (11:1)#, << PFAIL BIT OF IOQ >>                        00108000
   REQUEST     = (3:1)#; << REQUEST FLAG OF DIT DFLAGS >>               00110000
                                                                        00112000
INTEGER                                                                 00114000
   SYSUP       = DB+%73,                                                00116000
   SYSCONSOLE  = DB+CONSLDEV;                                           00118000
                                                                        00120000
INTEGER POINTER                                                         00122000
   LPDT        = DB+SYSLPDT,                                            00124000
   PS0         = S-0,                                                   00126000
   PS1         = S-1;                                                   00128000
                                                                        00130000
DOUBLE POINTER                                                          00132000
   LPDTD       = LPDT;                                                  00134000
                                                                        00136000
ARRAY                                                                   00138000
   PFMSG(0:8)  := %6412,"**POWER FAIL**",%6412;                         00140000
                                                                        00142000
INTEGER ARRAY                                                           00144000
   IOQX(0:255) := 256(0);                                               00146000
$PAGE                                                                   00148000
DOUBLE PROCEDURE ATTACHIO(LDEV,QMISC,DSTX,ADDR,FUNC,CNT,P1,P2,FLAGS);   00150000
VALUE LDEV,QMISC,DSTX,ADDR,FUNC,CNT,P1,P2,FLAGS;                        00152000
INTEGER LDEV,QMISC,DSTX,ADDR,FUNC,CNT,P1,P2,FLAGS;                      00154000
OPTION EXTERNAL;                                                        00156000
                                                                        00158000
PROCEDURE AWAKEIO(DITP,FLAGS);                                          00160000
VALUE DITP,FLAGS;                                                       00162000
POINTER DITP;                                                           00164000
LOGICAL FLAGS;                                                          00166000
OPTION EXTERNAL;                                                        00168000
                                                                        00170000
PROCEDURE CHECKLDEV(DEV);                                               00172000
VALUE DEV;                                                              00174000
INTEGER DEV;                                                            00176000
OPTION EXTERNAL;                                                        00178000
                                                                        00180000
PROCEDURE DSETCONTROL(OP,DITP);                                         00182000
VALUE OP,DITP;                                                          00184000
INTEGER OP;                                                             00186000
POINTER DITP;                                                           00188000
OPTION EXTERNAL;                                                        00190000
                                                                        00192000
PROCEDURE LOG7;                                                         00194000
OPTION EXTERNAL;                                                        00196000
                                                                        00198000
DOUBLE PROCEDURE IOSTATUS(IOQX);                                        00200000
VALUE IOQX;                                                             00202000
INTEGER IOQX;                                                           00204000
OPTION EXTERNAL;                                                        00206000
                                                                        00208000
PROCEDURE HELP;                                                         00210000
OPTION EXTERNAL;                                                        00212000
                                                                        00214000
PROCEDURE PRINTPFMSG(MSG,WORDS);                                        00216000
VALUE MSG,WORDS; DOUBLE MSG;                                            00218000
INTEGER WORDS;                                                          00220000
OPTION EXTERNAL;                                                        00222000
                                                                        00224000
PROCEDURE RESETDB(A);                                                   00226000
VALUE A;                                                                00228000
INTEGER A;                                                              00230000
OPTION EXTERNAL;                                                        00232000
                                                                        00234000
LOGICAL PROCEDURE SETSYSDB;                                             00236000
OPTION EXTERNAL;                                                        00238000
                                                                        00240000
PROCEDURE TERMINIT(DITP);                                               00242000
VALUE DITP;                                                             00244000
POINTER DITP;                                                           00246000
OPTION EXTERNAL;                                                        00248000
                                                                        00250000
PROCEDURE WAIT(A,B);                                                    00252000
VALUE A,B;                                                              00254000
INTEGER A,B;                                                            00256000
OPTION EXTERNAL;                                                        00258000
                                                                        00260000
PROCEDURE WRITE2(WORD);                                                 00262000
VALUE WORD;                                                             00264000
INTEGER WORD;                                                           00266000
OPTION EXTERNAL;                                                        00268000
                                                                        00270000
PROCEDURE INITIO(FLAG);                                                 00272000
   VALUE FLAG;                                                          00274000
   LOGICAL FLAG;                                                        00276000
   OPTION EXTERNAL;                                                     00278000
                                                               <<02062>>00280000
LOGICAL PROCEDURE EXCHANGEDB(INX);                             <<02062>>00282000
    VALUE   INX;                                               <<02062>>00284000
    INTEGER  INX;                                              <<02062>>00286000
    OPTION EXTERNAL;                                           <<02062>>00288000
                                                                        00290000
$PAGE                                                                   00292000
PROCEDURE POWERUP;                                                      00294000
BEGIN                                                                   00296000
INTEGER I,J,K,L,X=X;                                                    00298000
INTEGER S0=S-0;                                                <<03045>>00300000
DOUBLE DSAVE;                                                           00302000
INTEGER DEVICE;                                                <<02062>>00304000
INTEGER POINTER DITP = DSAVE;                                           00306000
INTEGER ARRAY LDT(*) = DB + 0;                                 <<02062>>00308000
LOGICAL LFLAGS = DSAVE+1,NEW := TRUE;                                   00310000
LOGICAL QPFAIL;   << TELL DRIVER OF PFAIL VIA ATTACHIO >>               00312000
EQUATE LDTDST  = %16,                                          <<02062>>00314000
   INP'DEV     = %21,          <<INP DEVICE NUMBER>>           <<02062>>00316000
   WORDCT      = 5;                                            <<02062>>00318000
DEFINE DRSTATE  = (0:2)#, <<DEVICE STATE>>                     <<02062>>00320000
   DEV'TYPE    = (10:6)#;       <<DEVICE TYPE>>                <<02062>>00322000
ARRAY                                                          <<03045>>00324000
  TEMPMASK (0:3);      <<TEMP COPY OF INT-MASK WORDS>>         <<03045>>00326000
LOGICAL                                                        <<03045>>00328000
   MASKADDR;           <<ADDRESS OF INTERRUPT MASK>>           <<03045>>00330000
                                                                        00332000
INTEGER                                                        <<03045>>00334000
   IMB,                <<LOOP COUNTER INDEX INTO TEMPMASK>>    <<03045>>00336000
   CHANNUM,                   <<CHANNEL NUMBER>>               <<03676>>00338000
   MAXIMB,             <<NUMBER OF IMBS SUPPORTED BY CPU>>     <<03045>>00340000
   CPUNUM;             <<CPU NUMBER RETURNED FROM CPN>>        <<03045>>00342000
                                                                        00344000
RESTART:                                                                00346000
   INITIO(1); <<INITIALIZE SYSTEM VOLUMES AND CONSOLE>>        <<01686>>00348000
   PUSH(DB);                                                            00350000
   TOS := TOS+@PFMSG;   << ABSOLUTE ADDRESS OF PFMSG >>                 00352000
   TOS := 9;            << MSG LENGTH WOULD STACK PARAMETERS >>         00354000
   SETSYSDB;                                                            00356000
   PRINTPFMSG(*,*);       << OUTPUT MSG TO CON >>                       00358000
   PF := 4; << SET POWERFAIL INDICATOR TO RECOVERY >>                   00360000
   ENABLE;                                                              00362000
   I := 1;                                                              00364000
                                                               <<03045>>00366000
    <<======================================================>> <<03045>>00368000
    <<THE NORMAL OPERATIONS OF READ/SET MASK ARE COMPLICATED>> <<03045>>00370000
    <<BY THE INTRODUCTION OF A 4-WORD INTERRUPT MASK FOR THE>> <<03045>>00372000
    <<ICF/55.    FOR NON ICF/55 CPUS:                       >> <<03045>>00374000
    <<    INTERRUPT MASK STORED AT %7                       >> <<03045>>00376000
    <<    READ MASK RETURNS THE (1 WORD) MASK ON TOS        >> <<03045>>00378000
    <<    SET MASK EXPECTS  THE (1 WORD) MASK ON TOS        >> <<03045>>00380000
    <<           FOR THE ICF/55 CPU:                        >> <<03045>>00382000
    <<    INTERRUPT MASK STORED AT %32  (MASK FOR IMB 0)    >> <<03045>>00384000
    <<                             %33  (MASK FOR IMB 1)    >> <<03045>>00386000
    <<                             %34  (MASK FOR IMB 2)    >> <<03045>>00388000
    <<                             %35  (MASK FOR IMB 3)    >> <<03045>>00390000
    <<    SET MASK / READ MASK EXPECT OR RETURN TOP OF STACK>> <<03045>>00392000
    <<                             S-3  (MASK FOR IMB 3)    >> <<03045>>00394000
    <<                             S-2  (MASK FOR IMB 2)    >> <<03045>>00396000
    <<                             S-1  (MASK FOR IMB 1)    >> <<03045>>00398000
    <<                  TOS ==>    S-0  (MASK FOR IMB 0)    >> <<03045>>00400000
    <<======================================================>> <<03045>>00402000
   ASSEMBLE(PCN);      <<DETERMINE CPU NUMBER>>                <<03045>>00404000
   CPUNUM := TOS;      << AND SAVE IT>>                        <<03045>>00406000
                                                               <<03045>>00408000
   MAXIMB := IF CPUNUM=ICF'55 THEN 3 ELSE 0;                   <<03045>>00410000
                       <<ICF/55 SUPPORTS 4 IMBS>>              <<03045>>00412000
                       <<ALL OTHERS CPUS SUPPORT 1 IMB>>       <<03045>>00414000
                                                               <<03045>>00416000
                       <<INTERNAL INT. MASK MIGHT BE DEAD>>    <<03045>>00418000
                       <<USE CORE INT. MASK VALUES TO BE>>     <<03045>>00420000
                       <<SURE OF GETTING DECENT VALUES>>       <<03045>>00422000
   MASKADDR := IF CPUNUM = ICF'55                              <<03045>>00424000
               THEN IMASK55 ELSE IMASK;  <<POINTER TO I-MASK>> <<03045>>00426000
   IMB := 0;                  <<STORE INTO TEMPMASK>>          <<03045>>00428000
   WHILE IMB <= MAXIMB DO BEGIN                                <<03045>>00430000
       TEMPMASK(IMB) := ABSOLUTE(MASKADDR);                    <<03045>>00432000
       MASKADDR := MASKADDR + 1;                               <<03045>>00434000
       IMB := IMB+1;                                           <<03045>>00436000
   END;                                                        <<03045>>00438000
   DO                                                                   00440000
   BEGIN << EXAMINE ALL DEVICES TO DETERMINE DISPOSITION >>             00442000
      DSAVE := LPDTD(I);                                                00444000
      RESETDB(-1);                                             <<02062>>00446000
      EXCHANGEDB(LDTDST);                                      <<02062>>00448000
      DEVICE := LDT(I*WORDCT+2);                               <<02062>>00450000
      EXCHANGEDB(0);                                           <<02062>>00452000
      SETSYSDB;         <<BACK TO SYS GLOB>>                   <<02062>>00454000
      TOS := @DITP;                                            <<00.04>>00456000
      IF > AND (DEVICE.DEV'TYPE <> INP'DEV OR                  <<02062>>00458000
                LFLAGS.DRSTATE <> 0) THEN                      <<02062>>00460000
    << THE DEVICE IS AN INP (THAT IS OWNED) OR NOT AN INP->>   <<02062>>00462000
    << SO INITIALIZE THE DEVICES*A FIX FOR CS DEVICES     >>   <<02062>>00464000
      BEGIN                                                    <<00.05>>00466000
      TOS := DITP(DILTP);                                               00468000
      TOS := PS0(ICNTRL).DRTNUMBER;  <<DRT # FROM ILT>>        <<03045>>00470000
      DELB;                     << DELTE ILT POINTER >>                 00472000
      IMB := S0.IMB'NUM;        <<EXTRACT IMB NUMBER>>         <<03045>>00474000
      CHANNUM := TOS.CHAN'NUM;  <<CHANNEL NUMBER>>             <<03676>>00476000
      TOS := TEMPMASK(IMB); <<PUT MASK WORD FOR IMB ON TOS>>   <<03045>>00478000
      X := CHANNUM;           <<CHANNEL NUMBER>>               <<03676>>00480000
      ASMB( TSBC 0,X);      <<SET BIT FOR THE CHANNEL>>        <<03045>>00482000
      TEMPMASK(IMB) := TOS;  <<STORE BACK INTO TEMP MASK>>     <<03045>>00484000
                                                               <<03045>>00486000
      IMB := MAXIMB;    <<WILL WORK FOR ALL CPU>>              <<03045>>00488000
              <<NOW STACK THE MASK WORDS FOR SETMASK>>         <<03045>>00490000
              << 4 WORDS FOR ICF/55    1 WORD ALL OTHERS>>     <<03045>>00492000
      WHILE IMB >= 0 DO BEGIN                                  <<03045>>00494000
          TOS := TEMPMASK(IMB);                                <<03045>>00496000
          IMB := IMB-1;                                        <<03045>>00498000
      END;                                                     <<03045>>00500000
                           << IMB-0 = S-0  IMB-3=S-3>>         <<03045>>00502000
      ASSEMBLE (SMSK);                                         <<03045>>00504000
                                                               <<03045>>00506000
      TOS := DITP(DDLTP); << DLT PTR >>                        <<00.04>>00508000
      QPFAIL := PS0.QPFAILS; << FLAG TO TELL DRIVER VIA ATTACHIO >>     00510000
      TOS := PS0(DINIL); << INITIALIZATION PLABEL >>           <<00.04>>00512000
      DELB;                                                    <<00.04>>00514000
      IF < AND I<>SYSCONSOLE THEN ASMB(PCAL 0) ELSE DDEL;               00516000
      CHECKLDEV(I);                                                     00518000
      IF = AND NOCARRY THEN                                             00520000
      IF QPFAIL THEN ATTACHIO(I,0,0,0,PFAILURE,0,0,0,%13) ELSE          00522000
      BEGIN << NON DISC SIO DEVICE >>                                   00524000
ABORTSIO:                                                               00526000
         DISABLE;                                                       00528000
         TOS := DITP(DIOQP);                                            00530000
         IF <> THEN                                                     00532000
         BEGIN << IOQ ATTACHED, ABORT THE I/O >>                        00534000
            TOS := PS0;                                                 00536000
            TOS.ABORT := 1;                                             00538000
            TOS.PFAIL := 1;                                             00540000
            PS1 := TOS;                                                 00542000
            TOS := DITP; << GET FLAGS WORD OF DIT >>                    00544000
            TOS.IAK := 1;                                               00546000
            TOS.REQUEST := 1;                                           00548000
            DITP := TOS;                                                00550000
            PDISABLE;                                                   00552000
            ENABLE;                                                     00554000
            AWAKEIO(DITP,0); << HAVE DRIVER DO THE ABORT >>             00556000
            PENABLE;                                                    00558000
         END;                                                           00560000
         ENABLE;                                                        00562000
         DEL;                                                           00564000
      END;                                                              00566000
                                                                        00568000
      END ELSE DEL;                                            <<00.05>>00570000
      IF PF <> 4 THEN GO RESTART;                                       00572000
   END UNTIL (I:=I+1) > LPDT.MAXENTRY;                                  00574000
   ABS(ABS(QI)-12) := 0; << RESET PFAIL FLAG SO USERS WILL RUN >>       00576000
   RESETDB(-1);                                                         00578000
   TOS := NEW;                                                          00580000
   TOS := 7;                                                            00582000
   LOG7; << ISSUE LOG RECORD TO RECORD POWERFAIL >>                     00584000
   SETSYSDB;                                                            00586000
   IF NEW THEN                                                          00588000
   BEGIN << NEW POWERFAIL, SEND MESSAGES TO TERMINALS >>                00590000
      J := 0;                                                           00592000
      K := -1;                                                          00594000
      NEW := FALSE;                                                     00596000
   END;                                                                 00598000
   WHILE (J := J + 1) <= LPDT.MAXENTRY DO                               00600000
   BEGIN << SEND POWERFAIL MESSAGE TO ALL ACTIVE TERMINALS >>           00602000
      CHECKLDEV(J);                                                     00604000
      IF > THEN                                                         00606000
      BEGIN << DEVICE IS A TERMINAL >>                                  00608000
         DSAVE := LPDTD(J);                                             00610000
         IF LFLAGS.DIRCSTATE <> 0 THEN                                  00612000
         BEGIN << SEND PFAIL MSG TO TERMINAL >>                         00614000
            L := (IF J = SYSCONSOLE THEN 1 ELSE 8);                     00616000
            RESETDB(-1);                                                00618000
            TOS := ATTACHIO(J,0,0,@PFMSG,1,L,0,0,%406);                 00620000
            ASSEMBLE(DEL,TEST);                                         00622000
            IF <> THEN IOQX(K:=K+1) := TOS ELSE DEL;                    00624000
            << FORGET REQUEST IF OUT OF IOQ'S >>                        00626000
            SETSYSDB;                                                   00628000
         END;                                                           00630000
      END;                                                              00632000
      IF PF <> 4 THEN GO RESTART;                                       00634000
   END;                                                                 00636000
   SYSUP := 1;                                                          00638000
   RESETDB(-1);                                                         00640000
CHECKAGAIN:  << NOW ALLOW ALL THE I/O TO COMPLETE >>                    00642000
   FOR X := 0 UNTIL K DO                                                00644000
   IF IOQX(X) <> 0 THEN                                                 00646000
   BEGIN << CHECK FOR COMPLETION >>                                     00648000
      IOSTATUS(IOQX(X));                                                00650000
      IF <= THEN IOQX(X) := 0; << ALL DONE, ZERO ENTRY >>               00652000
   END;                                                                 00654000
   TOS := IOQX(0); << SEE IF ALL I/O IS COMPLETE >>                     00656000
   WHILE (X:=X+1) <= K DO TOS := TOS LOR LOGICAL(IOQX(X));              00658000
   ASMB(TEST,DEL);                                                      00660000
   IF <> THEN                                                           00662000
   BEGIN << NOT ALL DONE YET >>                                         00664000
      WAIT( JUNK'IOWAIT,0);                                             00666000
      IF PF <> 4 THEN GO RESTART;                                       00668000
      GO CHECKAGAIN;                                                    00670000
   END;                                                                 00672000
   IF PF <> 4 THEN GO TO RESTART;                                       00674000
   PF := 0;                                                             00676000
   NEW := TRUE;                                                         00678000
WAITSOMEMORE:                                                           00680000
   WAIT(JUNKWAIT,0);                                                    00682000
   IF PF <> 0 THEN GO RESTART;                                          00684000
   GO WAITSOMEMORE;                                                     00686000
   HELP;                                                                00688000
END;                                                                    00690000
   POWERUP;                                                             00692000
END.                                                                    00694000
