<< LINES .001/.009 ARE RESERVED FOR SYSTEMS INTEGRATION>>               00005000
$control map,code,uslinit                                               00010000
<<pfail - module 30>>                                                   00015000
<< hp32033c mpe source c.00.00 >>                                       00020000
$copyright     "(C) COPYRIGHT HEWLETT-PACKARD CO. 1980. ",            & 00025000
$     "THIS PROGRAM MAY BE USED WITH ONE COMPUTER SYSTEM AT A ",      & 00030000
$     "TIME AND SHALL NOT OTHERWISE BE RECORDED, TRANSMITTED OR ",    & 00035000
$     "STORED IN A RETRIEVAL SYSTEM.  COPYING OR OTHER REPRODUCTION ",& 00040000
$     "OF THIS PROGRAM EXCEPT FOR ARCHIVAL PURPOSES IS PROHIBITED ",  & 00045000
$     "WITHOUT THE PRIOR WRITTEN CONSENT OF HEWLETT-PACKARD COMPANY."   00050000
$control uncallable,privileged,main=pfail                               00055000
$tp                                                                     00060000
$title "POWERFAIL RESTART/RECOVERY PROCESS"                             00065000
begin                                                                   00070000
                                                                        00075000
equate                                                                  00080000
   multi'imb   = %60, <<mask of cpus having multi imbs>>       <<m8290>>00085000
   powerfail   = %72, << sysdb index >>                                 00090000
   pfailure    = 65,  << opcode to tell driver pfailed >>               00095000
   sysdb       = %1000,                                                 00100000
   dinil       = 7,                                            <<00.04>>00105000
   dioqp       = 2,   << dit index to ioq pointer >>                    00110000
   ddltp       = 4,   << dit index to dvr link table ptr >>             00115000
   diltp       = 5,   << dit index to ilt >>                            00120000
   dmntr       = 1,   << dlt index to monitor plabel >>                 00125000
   icntrl      = 7,   << controller info of ilt >>                      00130000
   imask       = 7,   << interrupt mask word >>                         00135000
   imask55     = %32, <<4 word int mask for icf/55>>           <<03045>>00140000
   junkwait    = -%20,                                                  00145000
   junk'iowait = -%120,                                                 00150000
   consldev    = %74, << sysdb index >>                                 00155000
   qi          = 5,                                            <<06836>>00160000
   ics'pfail   = 12;                                           <<06836>>00165000
                                                                        00170000
define                                                                  00175000
   drtnumber   = (7:9)#,  <<drt number field in ilt>>          <<03045>>00180000
   chan'num    = (9:4)#,  <<4-bit-channel number>>             <<03045>>00185000
   imb'num     = (7:2)#,  <<2-bit-imb number>>                 <<03045>>00190000
   qpfails     = (11:1)#, << pfail to be indicated by attachio >>       00195000
   abs         = absolute#,                                             00200000
   asmb        = assemble#,                                             00205000
   disable     = assemble(sed 0)#,                                      00210000
   enable      = assemble(sed 1)#,                                      00215000
   iak         = (8:1)#,  << interrupt acknowledge bit of dit >>        00220000
   pdisable    = asmb(psdb)#,                                           00225000
   penable     = asmb(pseb)#,                                           00230000
   pf          = abs(sysdb+powerfail)#,                                 00235000
   request     = (3:1)#; << request flag of dit dflags >>               00240000
                                                                        00245000
integer                                                                 00250000
   sysup       = db+%73,                                                00255000
   sysconsole  = db+consldev;                                           00260000
                                                                        00265000
integer pointer                                                         00270000
   ps0         = s-0,                                                   00275000
   ps1         = s-1;                                                   00280000
                                                                        00285000
equate                                                         <<06835>>00290000
  pf'msg'length = 16;                                          <<06835>>00295000
                                                               <<06835>>00300000
array                                                                   00305000
   pfmsg(0:pf'msg'length-1) := %6412,                          <<06835>>00310000
                               "**RECOVERY FROM POWER FAIL**", <<06835>>00315000
                               %6412;                          <<06835>>00320000
                                                                        00325000
$include incllpdt                                              <<06835>>00330000
$include inclldt5                                              <<06835>>00335000
$title " "                                                     <<07305>>00340000
$include incliqh                                               <<06836>>00345000
$include inclioq                                               <<06836>>00350000
$page                                                                   00355000
double procedure attachio(ldev,qmisc,dstx,addr,func,cnt,p1,p2,flags);   00360000
value ldev,qmisc,dstx,addr,func,cnt,p1,p2,flags;                        00365000
integer ldev,qmisc,dstx,addr,func,cnt,p1,p2,flags;                      00370000
option external;                                                        00375000
                                                                        00380000
procedure awakeio(ditp,flags);                                          00385000
value ditp,flags;                                                       00390000
pointer ditp;                                                           00395000
logical flags;                                                          00400000
option external;                                                        00405000
                                                                        00410000
procedure checkldev(dev);                                               00415000
value dev;                                                              00420000
integer dev;                                                            00425000
option external;                                                        00430000
                                                                        00435000
procedure dsetcontrol(op,ditp);                                         00440000
value op,ditp;                                                          00445000
integer op;                                                             00450000
pointer ditp;                                                           00455000
option external;                                                        00460000
                                                                        00465000
procedure log7;                                                         00470000
option external;                                                        00475000
                                                                        00480000
double procedure iostatus(ioqx);                                        00485000
value ioqx;                                                             00490000
integer ioqx;                                                           00495000
option external;                                                        00500000
                                                                        00505000
procedure help;                                                         00510000
option external;                                                        00515000
                                                                        00520000
procedure printpfmsg(msg,words);                                        00525000
value msg,words; double msg;                                            00530000
integer words;                                                          00535000
option external;                                                        00540000
                                                                        00545000
procedure resetdb(a);                                                   00550000
value a;                                                                00555000
integer a;                                                              00560000
option external;                                                        00565000
                                                                        00570000
logical procedure setsysdb;                                             00575000
option external;                                                        00580000
                                                                        00585000
procedure terminit(ditp);                                               00590000
value ditp;                                                             00595000
pointer ditp;                                                           00600000
option external;                                                        00605000
                                                                        00610000
procedure wait(a,b);                                                    00615000
value a,b;                                                              00620000
integer a,b;                                                            00625000
option external;                                                        00630000
                                                                        00635000
procedure write2(word);                                                 00640000
value word;                                                             00645000
integer word;                                                           00650000
option external;                                                        00655000
                                                                        00660000
procedure initio(flag);                                                 00665000
   value flag;                                                          00670000
   logical flag;                                                        00675000
   option external;                                                     00680000
                                                               <<02062>>00685000
logical procedure exchangedb(inx);                             <<02062>>00690000
    value   inx;                                               <<02062>>00695000
    integer  inx;                                              <<02062>>00700000
    option external;                                           <<02062>>00705000
                                                                        00710000
procedure mmstat'(event,p1,p2,p3,p4,p5,p6);                    <<07305>>00715000
   value event,p1,p2,p3,p4,p5,p6;                              <<07305>>00720000
   integer event,p1,p2,p3,p4,p5,p6;                            <<07305>>00725000
   option external;                                            <<07305>>00730000
                                                               <<07305>>00735000
                                                               <<*7944>>00740000
procedure suddendeath (num);                                   <<*7944>>00745000
  value num;                                                   <<*7944>>00750000
  integer num;                                                 <<*7944>>00755000
  option external;                                             <<*7944>>00760000
                                                               <<*7944>>00765000
integer procedure get'dsdevice( ldev );                        <<d9004>>00770000
   value ldev;                                                 <<d9004>>00775000
   integer ldev;                                               <<d9004>>00780000
   option external;                                            <<d9004>>00785000
                                                               <<d9004>>00790000
$page                                                                   00795000
procedure powerup;                                                      00800000
begin                                                                   00805000
integer x=x,                                                   <<06836>>00810000
        ldev,                                                  <<06835>>00815000
        count,    << length of message for attachio >>         <<06835>>00820000
        dev'type, << device type from ldt           >>         <<06835>>00825000
        ioq'cnt,<< # ioqs to terminals for pfail msg >>        <<06836>>00830000
        ioq'entry'index,                                       <<06836>>00835000
        lpdt'index,                                            <<06835>>00840000
        ldt'index;                                             <<06835>>00845000
                                                               <<06835>>00850000
integer s0=s-0;                                                <<03045>>00855000
integer pointer ditp;                                          <<06835>>00860000
integer array ldt(*) = db + 0;                                 <<02062>>00865000
logical new := true;                                           <<06835>>00870000
logical qpfail;   << tell driver of pfail via attachio >>               00875000
equate                                                         <<06835>>00880000
   ibm'subsystem = %26,        <<imf, mrje        >>           <<d9004>>00885000
   inp'dev'type= %21;          <<inp device number>>           <<07305>>00890000
                                                               <<06836>>00895000
array                                                          <<03045>>00900000
  tempmask (0:3) = q;  << temporary copy of int. mask word >>  <<07305>>00905000
logical                                                        <<03045>>00910000
   maskaddr;           <<address of interrupt mask>>           <<03045>>00915000
                                                                        00920000
integer                                                        <<03045>>00925000
   imb,                <<loop counter index into tempmask>>    <<03045>>00930000
   channum,                   <<channel number>>               <<03676>>00935000
   maximb,             <<number of imbs supported by cpu>>     <<03045>>00940000
   cpunum;             <<cpu number returned from cpn>>        <<03045>>00945000
                                                               <<07305>>00950000
<< this must be the last declaration. >>                       <<07305>>00955000
                                                               <<07305>>00960000
integer array ioq'holder(*) = q;                               <<07305>>00965000
                                                               <<07305>>00970000
                                                                        00975000
                                                               <<06836>>00980000
<< set up storage area for the ioqs. there will need to be     <<06836>>00985000
<< at least one for every terminal device (for the pfail msg)>><<06836>>00990000
<< will set asside enough room to equal the total # ioqs     >><<06836>>00995000
<< configured.                                               >><<06836>>01000000
                                                               <<06836>>01005000
tos := iqh'tot'ent;                                            <<06836>>01010000
assemble (adds 0);   << allocate room for ioq'holder array >>  <<07305>>01015000
                                                               <<06836>>01020000
ioq'holder := 0;                                               <<06836>>01025000
move ioq'holder(1) := ioq'holder(0), (iqh'tot'ent-1);          <<06836>>01030000
                                                               <<06836>>01035000
restart:                                                                01040000
   mmstat'(240,2,new,pf,sysup,0,0);                            <<*7720>>01045000
   initio(1); <<initialize system volumes and console>>        <<01686>>01050000
   push(db);                                                            01055000
   tos := tos+@pfmsg;   << absolute address of pfmsg >>                 01060000
   tos := pf'msg'length;                                       <<06835>>01065000
   setsysdb;                                                            01070000
   printpfmsg(*,*);       << output msg to con >>                       01075000
   pf := 5; << set powerfail indicator to recovery >>          <<m8290>>01080000
   enable;                                                              01085000
   ldev := 1;                                                  <<06835>>01090000
                                                               <<03045>>01095000
    <<======================================================>> <<03045>>01100000
    <<the normal operations of read/set mask are complicated>> <<03045>>01105000
    <<by the introduction of a 4-word interrupt mask for the>> <<03045>>01110000
    <<icf/55.    for non icf/55 cpus:                       >> <<03045>>01115000
    <<    interrupt mask stored at %7                       >> <<03045>>01120000
    <<    read mask returns the (1 word) mask on tos        >> <<03045>>01125000
    <<    set mask expects  the (1 word) mask on tos        >> <<03045>>01130000
    <<           for the icf/55 cpu:                        >> <<03045>>01135000
    <<    interrupt mask stored at %32  (mask for imb 0)    >> <<03045>>01140000
    <<                             %33  (mask for imb 1)    >> <<03045>>01145000
    <<                             %34  (mask for imb 2)    >> <<03045>>01150000
    <<                             %35  (mask for imb 3)    >> <<03045>>01155000
    <<    set mask / read mask expect or return top of stack>> <<03045>>01160000
    <<                             s-3  (mask for imb 3)    >> <<03045>>01165000
    <<                             s-2  (mask for imb 2)    >> <<03045>>01170000
    <<                             s-1  (mask for imb 1)    >> <<03045>>01175000
    <<                  tos ==>    s-0  (mask for imb 0)    >> <<03045>>01180000
    <<======================================================>> <<03045>>01185000
   assemble(pcn);      <<determine cpu number>>                <<03045>>01190000
   cpunum := tos;      << and save it>>                        <<03045>>01195000
                                                               <<03045>>01200000
   maximb := if multi'imb &lsr(cpunum) then 3 else 0;          <<m8290>>01205000
                       <<icf/55 supports 4 imbs>>              <<03045>>01210000
                       <<all others cpus support 1 imb>>       <<03045>>01215000
                                                               <<03045>>01220000
                       <<internal int. mask might be dead>>    <<03045>>01225000
                       <<use core int. mask values to be>>     <<03045>>01230000
                       <<sure of getting decent values>>       <<03045>>01235000
   maskaddr := if multi'imb &lsr(cpunum)                       <<m8290>>01240000
               then imask55 else imask;  <<pointer to i-mask>> <<03045>>01245000
   imb := 0;                  <<store into tempmask>>          <<03045>>01250000
   while imb <= maximb do begin                                <<03045>>01255000
       tempmask(imb) := absolute(maskaddr);                    <<03045>>01260000
       maskaddr := maskaddr + 1;                               <<03045>>01265000
       imb := imb+1;                                           <<03045>>01270000
   end;                                                        <<03045>>01275000
                                                               <<06836>>01280000
   do                                                                   01285000
   begin << examine all devices to determine disposition >>             01290000
      lpdt'index := ldev * size'of'lpdt'entry;                 <<06835>>01295000
      ldt'index := ldev * size'of'ldt'entry;                   <<06835>>01300000
      @ditp := lpdt'dit'ptr;                                   <<06835>>01305000
      resetdb(-1);                                             <<02062>>01310000
      exchangedb(ldt'dst);                                     <<06835>>01315000
      dev'type := ldt'device'type;                             <<06835>>01320000
      exchangedb(0);                                           <<02062>>01325000
      setsysdb;         <<back to sys glob>>                   <<02062>>01330000
      tos := @ditp;                                            <<00.04>>01335000
      if <> and not lpdt'virtual'device and                    <<07305>>01340000
         ( dev'type <> inp'dev'type  or                        <<07305>>01345000
           lpdt'dev'own'state <> lpdt'not'owned) and           <<d9004>>01350000
         ( dev'type <> ibm'subsystem ) and                     <<d9004>>01355000
         ( get'dsdevice(ldev) <= 1 ) then                      <<d9004>>01360000
    << the device is an inp (that is owned) or not an inp->>   <<02062>>01365000
    << so initialize the devices*a fix for cs devices     >>   <<02062>>01370000
      begin                                                    <<00.05>>01375000
      tos := ditp(diltp);                                               01380000
      tos := ps0(icntrl).drtnumber;  <<drt # from ilt>>        <<03045>>01385000
      delb;                     << delte ilt pointer >>                 01390000
      imb := s0.imb'num;        <<extract imb number>>         <<03045>>01395000
      channum := tos.chan'num;  <<channel number>>             <<03676>>01400000
      tos := tempmask(imb); <<put mask word for imb on tos>>   <<03045>>01405000
      x := channum;           <<channel number>>               <<03676>>01410000
      asmb( tsbc 0,x);      <<set bit for the channel>>        <<03045>>01415000
      tempmask(imb) := tos;  <<store back into temp mask>>     <<03045>>01420000
                                                               <<03045>>01425000
      imb := maximb;    <<will work for all cpu>>              <<03045>>01430000
              <<now stack the mask words for setmask>>         <<03045>>01435000
              << 4 words for icf/55    1 word all others>>     <<03045>>01440000
      while imb >= 0 do                                        <<*7944>>01445000
      begin                                                    <<*7944>>01450000
          tos := tempmask(imb);                                <<03045>>01455000
          imb := imb-1;                                        <<03045>>01460000
      end;                                                     <<03045>>01465000
                           << imb-0 = s-0  imb-3=s-3>>         <<03045>>01470000
      assemble (smsk);                                         <<03045>>01475000
      if < then suddendeath(222);  << can't afford to fail >>  <<*7944>>01480000
                                                               <<03045>>01485000
      tos := ditp(ddltp); << dlt ptr >>                        <<00.04>>01490000
      qpfail := ps0.qpfails; << flag to tell driver via attachio >>     01495000
      tos := ps0(dinil); << initialization plabel >>           <<00.04>>01500000
      delb;                                                    <<00.04>>01505000
      if < and ldev <> sysconsole then asmb(pcal 0) else ddel; <<06835>>01510000
      checkldev(ldev);                                         <<06835>>01515000
      if = and nocarry then                                             01520000
      if qpfail then attachio(ldev,0,0,0,pfailure,0,0,0,%13)   <<06835>>01525000
      else                                                     <<06835>>01530000
         begin     << non disc sio device >>                   <<06836>>01535000
abortsio:                                                               01540000
         disable;                                                       01545000
         ioq'entry'index := ditp(dioqp);                       <<06836>>01550000
         if ioq'entry'index <> 0 then                          <<06836>>01555000
            begin << ioq attached, abort the i/o >>            <<06836>>01560000
            ioq'abort := 1;                                    <<06836>>01565000
            ioq'pfail := 1;                                    <<06836>>01570000
            tos := ditp; << get flags word of dit >>                    01575000
            tos.iak := 1;                                               01580000
            tos.request := 1;                                           01585000
            ditp := tos;                                                01590000
            pdisable;                                                   01595000
            enable;                                                     01600000
            awakeio(ditp,0); << have driver do the abort >>             01605000
            penable;                                                    01610000
            end;                                               <<06836>>01615000
         enable;                                                        01620000
         end;                                                  <<06836>>01625000
                                                                        01630000
      end else del;   << deletes ditp pushed at start of loop>><<*7944>>01635000
      if pf <> 5 then go restart;                              <<m8290>>01640000
   end until (ldev := ldev+1) > integer(lpdt'max'entries);     <<06835>>01645000
                                                               <<06836>>01650000
   << reset power fail flag so users will run >>               <<06836>>01655000
                                                               <<06836>>01660000
   abs(abs(qi)-ics'pfail) := 0;                                <<06836>>01665000
   resetdb(-1);                                                         01670000
   tos := new;                                                          01675000
   tos := 7;                                                            01680000
   log7; << issue log record to record powerfail >>                     01685000
   setsysdb;                                                            01690000
                                                               <<06836>>01695000
   if new then                                                          01700000
   begin << new powerfail, send messages to terminals >>                01705000
      ldev := 0;                                               <<06835>>01710000
      ioq'cnt := -1;                                           <<06836>>01715000
      new := false;                                                     01720000
   end;                                                                 01725000
                                                               <<06836>>01730000
   while (ldev := ldev+1) <= integer(lpdt'max'entries) do      <<06835>>01735000
      begin      << send pfail message to all active terms. >> <<06836>>01740000
      checkldev(ldev);                                         <<06835>>01745000
      if > then                                                         01750000
         begin      << a terminal >>                           <<06836>>01755000
         lpdt'index := ldev * size'of'lpdt'entry;              <<06835>>01760000
         @ditp := lpdt'dit'ptr;                                <<06835>>01765000
         if lpdt'dev'own'state <> lpdt'not'owned then          <<06835>>01770000
            begin      << send pfail msg to terminal >>        <<06835>>01775000
            count := (if ldev = sysconsole then 1              <<06835>>01780000
                      else pf'msg'length);                     <<06835>>01785000
            resetdb(-1);                                                01790000
            tos := attachio(ldev,0,0,@pfmsg,1,count,0,0,%406); <<06835>>01795000
            assemble(del,test);                                         01800000
            if <> then                                         <<06836>>01805000
               ioq'holder(ioq'cnt := ioq'cnt+1) := tos         <<06836>>01810000
            else del;                                          <<06836>>01815000
            << forget request if out of ioq's >>                        01820000
            setsysdb;                                                   01825000
            end;                                               <<06836>>01830000
         end;                                                  <<06836>>01835000
      if pf <> 5 then go restart;                              <<m8290>>01840000
   end;                                                                 01845000
                                                               <<06836>>01850000
   sysup := 1;                                                          01855000
   resetdb(-1);                                                         01860000
checkagain:  << now allow all the i/o to complete >>                    01865000
   for x := 0 until ioq'cnt do                                 <<06836>>01870000
   if ioq'holder(x) <> 0 then                                  <<06836>>01875000
   begin << check for completion >>                                     01880000
      iostatus(ioq'holder(x));                                 <<06836>>01885000
      if <= then ioq'holder(x) := 0; << all done, clear entry>><<06836>>01890000
   end;                                                                 01895000
                                                               <<06836>>01900000
   tos := ioq'holder(0); << see if all i/o are complete >>     <<06836>>01905000
   while (x:=x+1) <= ioq'cnt do                                <<06836>>01910000
      tos := tos lor logical(ioq'holder(x));                   <<06836>>01915000
                                                               <<06836>>01920000
   asmb(test,del);                                                      01925000
   if <> then                                                           01930000
   begin << not all done yet >>                                         01935000
      wait( junk'iowait,0);                                             01940000
      if pf <> 5 then go restart;                              <<m8290>>01945000
      go checkagain;                                                    01950000
   end;                                                                 01955000
                                                               <<06836>>01960000
   if pf <> 5 then go to restart;                              <<m8290>>01965000
   pf := 0;                                                             01970000
   new := true;                                                         01975000
                                                               <<06836>>01980000
                                                               <<06836>>01985000
waitsomemore:                                                           01990000
   mmstat'(240,1,new,pf,sysup,0,0);                            <<*7720>>01995000
   wait(junkwait,0);                                                    02000000
   if pf <> 0 then go restart;                                          02005000
   go waitsomemore;                                                     02010000
   help;                                                                02015000
end;                                                                    02020000
   powerup;                                                             02025000
end.                                                                    02030000
