$CONTROL MAP,CODE,USLINIT                                               00010000
<<PFAIL - MODULE 30>>                                                   00012000
<< HP32002C 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
$THIRTY                                                                 00030000
$TITLE "POWERFAIL RESTART/RECOVERY PROCESS"                             00032000
BEGIN                                                                   00034000
                                                                        00036000
EQUATE                                                                  00038000
   POWERFAIL   = %72, << SYSDB INDEX >>                                 00040000
   PFAILURE    = 65,   << OPCODE TO TELL DRIVER PFAILED >>     <<00144>>00042000
   SYSDB       = %1000,                                                 00044000
   SYSLPDT     = %10,                                                   00046000
   DINIL       = 7,                                            <<00.04>>00048000
   DIOQP       = 2,   << DIT INDEX TO IOQ POINTER >>                    00050000
   DDLTP       = 4,   << DIT INDEX TO DVR LINK TABLE PTR >>             00052000
   DMNTR       = 1,   << DLT INDEX TO MONITOR PLABEL >>                 00054000
   JUNKWAIT    = -%20,                                                  00056000
   JUNK'IOWAIT = -%120,                                                 00058000
   CONSLDEV    = %74, << SYSDB INDEX >>                                 00060000
   QI          = 5;                                                     00062000
                                                                        00064000
DEFINE                                                                  00066000
   QPFAILS     = (11:1)#,  << PFAIL TO BE INDICATED BY ATTACHIO<<00144>>00068000
   ABORT       = (0:1)#,  << ABORT BIT OF IOQ >>                        00070000
   ABS         = ABSOLUTE#,                                             00072000
   ASMB        = ASSEMBLE#,                                             00074000
   DIRCSTATE   = (0:2)#,   << DEVICE RECOGNITION STATE IN LPDT >>       00076000
   DISABLE     = ASSEMBLE(SED 0)#,                                      00078000
   ENABLE      = ASSEMBLE(SED 1)#,                                      00080000
   IAK         = (8:1)#,  << INTERRUPT ACKNOWLEDGE BIT OF DIT >>        00082000
   MAXENTRY    = (0:8)#,  << # OF ENTRIES IN LPDT >>                    00084000
   PDISABLE    = ASMB(PSDB)#,                                           00086000
   PENABLE     = ASMB(PSEB)#,                                           00088000
   PF          = ABS(SYSDB+POWERFAIL)#,                                 00090000
   PFAIL       = (11:1)#, << PFAIL BIT OF IOQ >>                        00092000
   REQUEST     = (3:1)#; << REQUEST FLAG OF DIT DFLAGS >>               00094000
                                                                        00096000
INTEGER                                                                 00098000
   SYSUP       = DB+%73,                                                00100000
   SYSCONSOLE  = DB+CONSLDEV;                                           00102000
                                                                        00104000
INTEGER POINTER                                                         00106000
   LPDT        = DB+SYSLPDT,                                            00108000
   PS0         = S-0,                                                   00110000
   PS1         = S-1;                                                   00112000
                                                                        00114000
DOUBLE POINTER                                                          00116000
   LPDTD       = LPDT;                                                  00118000
                                                                        00120000
ARRAY                                                                   00122000
   PFMSG(0:7)  := %6412,"**POWER FAIL**";                               00124000
                                                                        00126000
INTEGER ARRAY                                                           00128000
   IOQX(0:255) := 256(0);                                               00130000
$PAGE                                                                   00132000
DOUBLE PROCEDURE ATTACHIO(LDEV,QMISC,DSTX,ADDR,FUNC,CNT,P1,P2,FLAGS);   00134000
VALUE LDEV,QMISC,DSTX,ADDR,FUNC,CNT,P1,P2,FLAGS;                        00136000
INTEGER LDEV,QMISC,DSTX,ADDR,FUNC,CNT,P1,P2,FLAGS;                      00138000
OPTION EXTERNAL;                                                        00140000
                                                                        00142000
PROCEDURE AWAKEIO(DITP,FLAGS);                                          00144000
VALUE DITP,FLAGS;                                                       00146000
POINTER DITP;                                                           00148000
LOGICAL FLAGS;                                                          00150000
OPTION EXTERNAL;                                                        00152000
                                                                        00154000
PROCEDURE CHECKLDEV(DEV);                                               00156000
VALUE DEV;                                                              00158000
INTEGER DEV;                                                            00160000
OPTION EXTERNAL;                                                        00162000
                                                                        00164000
PROCEDURE DSETCONTROL(OP,DITP);                                         00166000
VALUE OP,DITP;                                                          00168000
INTEGER OP;                                                             00170000
POINTER DITP;                                                           00172000
OPTION EXTERNAL;                                                        00174000
                                                                        00176000
PROCEDURE LOG7;                                                         00178000
OPTION EXTERNAL;                                                        00180000
                                                                        00182000
DOUBLE PROCEDURE IOSTATUS(IOQX);                                        00184000
VALUE IOQX;                                                             00186000
INTEGER IOQX;                                                           00188000
OPTION EXTERNAL;                                                        00190000
                                                                        00192000
PROCEDURE HELP;                                                         00194000
OPTION EXTERNAL;                                                        00196000
                                                                        00198000
PROCEDURE RESETDB(A);                                                   00200000
VALUE A;                                                                00202000
INTEGER A;                                                              00204000
OPTION EXTERNAL;                                                        00206000
                                                                        00208000
PROCEDURE SETSYSDB;                                                     00210000
OPTION EXTERNAL;                                                        00212000
                                                                        00214000
PROCEDURE TERMINIT(DITP);                                               00216000
VALUE DITP;                                                             00218000
POINTER DITP;                                                           00220000
OPTION EXTERNAL;                                                        00222000
                                                                        00224000
PROCEDURE WAIT(A,B);                                                    00226000
VALUE A,B;                                                              00228000
INTEGER A,B;                                                            00230000
OPTION EXTERNAL;                                                        00232000
                                                               <<02062>>00234000
LOGICAL PROCEDURE EXCHANGEDB(INX);                             <<02062>>00236000
    VALUE   INX;                                               <<02062>>00238000
    INTEGER  INX;                                              <<02062>>00240000
    OPTION EXTERNAL;                                           <<02062>>00242000
                                                                        00244000
$PAGE                                                                   00246000
PROCEDURE POWERUP;                                                      00248000
BEGIN                                                                   00250000
INTEGER I,J,K,L,X=X;                                                    00252000
INTEGER DEVICE;                                                <<02062>>00254000
DOUBLE DSAVE;                                                           00256000
INTEGER POINTER DITP = DSAVE;                                           00258000
INTEGER ARRAY LDT(*) = DB + 0;                                 <<02062>>00260000
LOGICAL LFLAGS = DSAVE+1,NEW := TRUE;                                   00262000
LOGICAL QPFAIL;   << TELL DRIVER OF PFAIL VIA ATTACHIO >>      <<00144>>00264000
EQUATE  LDTDST = %16,                                          <<02062>>00266000
   INP'DEV     = %21,          <<INP DEVICE NUMBER>>           <<02062>>00268000
   WORDCT      = 5;                                            <<02062>>00270000
DEFINE DRSTATE = (0:2)#,               <<DEVICE STATE>>        <<02062>>00272000
   DEV'TYPE    = (10:6)#;       <<DEVICE TYPE>>                <<02062>>00274000
                                                                        00276000
                                                                        00278000
RESTART:                                                                00280000
   SETSYSDB;                                                            00282000
   PF := 4; << SET POWERFAIL INDICATOR TO RECOVERY >>                   00284000
   ENABLE;                                                              00286000
   I := 1;                                                              00288000
   DO                                                                   00290000
   BEGIN << EXAMINE ALL DEVICES TO DETERMINE DISPOSITION >>             00292000
      DSAVE := LPDTD(I);                                                00294000
      RESETDB(-1);                                             <<02062>>00296000
      EXCHANGEDB(LDTDST);                                      <<02062>>00298000
      DEVICE := LDT(I*WORDCT+2);                               <<02062>>00300000
      EXCHANGEDB(0);                                           <<02062>>00302000
      SETSYSDB;         <<BACK TO SYS GLOB>>                   <<02062>>00304000
      TOS := @DITP;                                            <<00.04>>00306000
      IF > AND (DEVICE.DEV'TYPE <> INP'DEV OR                  <<02062>>00308000
                LFLAGS.DRSTATE <> 0) THEN                      <<02062>>00310000
    << THE DEVICE IS AN INP (THAT IS OWNED) OR NOT AN INP->>   <<02062>>00312000
    << SO INITIALIZE THE DEVICES*A FIX FOR CS DEVICES     >>   <<02062>>00314000
      BEGIN                                                    <<00.05>>00316000
                                                               <<00.05>>00318000
      TOS := DITP(DDLTP); << DLT PTR >>                        <<00.04>>00320000
      QPFAIL := PS0.QPFAILS; << FLAG TO TELL DRIVER VIA ATTACHI<<00144>>00322000
      TOS := PS0(DINIL); << INITIALIZATION PLABEL >>           <<00.04>>00324000
      DELB;                                                    <<00.04>>00326000
      IF < THEN ASMB(PCAL 0) ELSE DDEL;                        <<00.04>>00328000
      CHECKLDEV(I);                                                     00330000
      IF = AND NOCARRY THEN                                             00332000
      IF QPFAIL THEN ATTACHIO(I,0,0,0,PFAILURE,0,0,0,%13) ELSE <<00144>>00334000
      BEGIN << NON DISC SIO DEVICE >>                                   00336000
ABORTSIO:                                                               00338000
         DISABLE;                                                       00340000
         TOS := DITP(DIOQP);                                            00342000
         IF <> THEN                                                     00344000
         BEGIN << IOQ ATTACHED, ABORT THE I/O >>                        00346000
            TOS := PS0;                                                 00348000
            TOS.ABORT := 1;                                             00350000
            TOS.PFAIL := 1;                                             00352000
            PS1 := TOS;                                                 00354000
            TOS := DITP; << GET FLAGS WORD OF DIT >>                    00356000
            TOS.IAK := 1;                                               00358000
            TOS.REQUEST := 1;                                           00360000
            DITP := TOS;                                                00362000
            PDISABLE;                                                   00364000
            ENABLE;                                                     00366000
            AWAKEIO(DITP,0); << HAVE DRIVER DO THE ABORT >>             00368000
            PENABLE;                                                    00370000
         END;                                                           00372000
         ENABLE;                                                        00374000
         DEL;                                                           00376000
      END;                                                              00378000
                                                                        00380000
      END ELSE DEL;                                            <<00.05>>00382000
      IF PF <> 4 THEN GO RESTART;                                       00384000
   END UNTIL (I:=I+1) > LPDT.MAXENTRY;                                  00386000
   ABS(ABS(QI)-12) := 0; << RESET PFAIL FLAG SO USERS WILL RUN >>       00388000
   RESETDB(-1);                                                         00390000
   TOS := NEW;                                                          00392000
   TOS := 7;                                                            00394000
   LOG7; << ISSUE LOG RECORD TO RECORD POWERFAIL >>                     00396000
   SETSYSDB;                                                            00398000
   IF NEW THEN                                                          00400000
   BEGIN << NEW POWERFAIL, SEND MESSAGES TO TERMINALS >>                00402000
      J := 0;                                                           00404000
      K := -1;                                                          00406000
      NEW := FALSE;                                                     00408000
   END;                                                                 00410000
   WHILE (J := J + 1) <= LPDT.MAXENTRY DO                               00412000
   BEGIN << SEND POWERFAIL MESSAGE TO ALL ACTIVE TERMINALS >>           00414000
      CHECKLDEV(J);                                                     00416000
      IF > THEN                                                         00418000
      BEGIN << DEVICE IS A TERMINAL >>                                  00420000
         DSAVE := LPDTD(J);                                             00422000
         IF LFLAGS.DIRCSTATE <> 0 THEN                                  00424000
         BEGIN << SEND PFAIL MSG TO TERMINAL >>                         00426000
            L := (IF J = SYSCONSOLE THEN 1 ELSE 8);                     00428000
            RESETDB(-1);                                                00430000
            TOS := ATTACHIO(J,0,0,@PFMSG,1,L,0,0,%406);                 00432000
            ASSEMBLE(DEL,TEST);                                         00434000
            IF <> THEN IOQX(K:=K+1) := TOS ELSE DEL;                    00436000
            << FORGET REQUEST IF OUT OF IOQ'S >>                        00438000
            SETSYSDB;                                                   00440000
         END;                                                           00442000
      END;                                                              00444000
      IF PF <> 4 THEN GO RESTART;                                       00446000
   END;                                                                 00448000
   SYSUP := 1;                                                          00450000
   RESETDB(-1);                                                         00452000
CHECKAGAIN:  << NOW ALLOW ALL THE I/O TO COMPLETE >>                    00454000
   FOR X := 0 UNTIL K DO                                                00456000
   IF IOQX(X) <> 0 THEN                                                 00458000
   BEGIN << CHECK FOR COMPLETION >>                                     00460000
      IOSTATUS(IOQX(X));                                                00462000
      IF <= THEN IOQX(X) := 0; << ALL DONE, ZERO ENTRY >>               00464000
   END;                                                                 00466000
   TOS := IOQX(0); << SEE IF ALL I/O IS COMPLETE >>                     00468000
   WHILE (X:=X+1) <= K DO TOS := TOS LOR LOGICAL(IOQX(X));              00470000
   ASMB(TEST,DEL);                                                      00472000
   IF <> THEN                                                           00474000
   BEGIN << NOT ALL DONE YET >>                                         00476000
      WAIT( JUNK'IOWAIT,0);                                             00478000
      IF PF <> 4 THEN GO RESTART;                                       00480000
      GO CHECKAGAIN;                                                    00482000
   END;                                                                 00484000
   IF PF <> 4 THEN GO TO RESTART;                                       00486000
   PF := 0;                                                             00488000
   NEW := TRUE;                                                         00490000
WAITSOMEMORE:                                                           00492000
   WAIT(JUNKWAIT,0);                                                    00494000
   IF PF <> 0 THEN GO RESTART;                                          00496000
   GO WAITSOMEMORE;                                                     00498000
   HELP;                                                                00500000
END;                                                                    00502000
   POWERUP;                                                             00504000
END.                                                                    00506000
