" " Begin include file ...... sav_util.incl.alm " This is the initialization code for the SAVE and RESTOR commands. " Modified for NSS 11/75 by Noel I. Morris " Last modified 9/9/76 by Noel I. Morris " Modified 2/80 by R.J.C. Kissel to support 6250 bpi operation. " Modified 3/82 by J. Bongiovanni for new pack layout " Modified 5/82 by Sherm D. Sprague to print target pack info. " Modified 83-10-10 by E. N. Kittlitz for disks up to 63. include sav_io_buf_seg include disk_pack include vol_map " include fs_vol_label include old_fs_vol_label include config_cards " Label buffer segment equivalences. " SAVE Header. equ svh,0 equ svh.version,svh+1 version # equ svh.allsw,svh+0 nonzero if saving everything equ svh.nvol,svh+2 number of volumes saved equ svh.curvol,svh+3 current volume being processed equ svh.sva,16 array of volume info equ svh_length,2048 " Volume Preamble. equ svp,svh+svh_length equ svp.version,svp+0 version # equ svp.recs,svp+1 # of records on this volume equ svp.sva,svp+16 volume info equ svp.bits,svp+32 bit map equ svp_length,3072 " Volume Label. equ svl,svp+svp_length equ LABEL,svl+LABEL_ADDR*1024 equ MAP,svl+VOLMAP_ADDR*1024 equ svl_length,DUMPER_BIT_MAP_ADDR*1024 " SAVE Header Copy. equ svhc,svl+svl_length " Volume Info. equ sva.pvname,0 physical volume name equ sva.pvid,8 physical volume ID equ sva.first,9 first record saved equ sva.last,10 last record saved equ sva.done,11 current record saved equ sva.devt,12 device type word equ sva.vtoc_size,13 size of VTOC area on volume equ sva.skip,14 nonzero to skip this volume equ sva_size,16 " stx2 x2 tsx2 init_io tsx2 ttyinit get tty requests arg ttyrequest lda geastab set for MVT instruction sta gvmvt .. eaa label_buff_len length of label buffer in AU tsx2 makesdw make a segment tra x2 Don't clobber core. staq ds|bf*2 store SDW eaa disk_buff_len length of disk buffer segment in AU tsx2 makesdw make another segment tra x2 staq ds|tmp*2 set SDW for temporary segment cams ldq =v12/,24/label_buff_len*4 length of seg 2 in QL mlr (),(pr,rl),fill(0) zero seg 2 desc9a *,0 desc9a bf|0,ql " stz bf|svh.allsw clear all switch lda 2,dl set version number sta bf|svh.version .. ldx2 x2 get command line and scan it ourselvs lda mem|0,2 get address of command line ana =-1,dl .. als 2 get character offset mlr (pr,al),() copy command line desc9a mem|0,84 desc9a line,84 tsx2 scan now scan to get dec numbers too lda arg get name of command era =h save if SAVE, sta savesw make switch zero lda =o65,dl set the default tape density sta tapeden save it for later use eax1 1 use X1 for argument index arglp: lda arg,1 get next argument eax7 0 search list of args rpt nargs,2,tze .. cmpa args,7 .. ttn badarg if not found, complain xec -1,7 perform appropriate action eax1 1,1 step to next arg tra arglp and process next arg args: bci " brief" stc1 disk_brief,* bci " all" stc1 bf|svh.allsw bci " tape" tra argtape bci " disk" tra argdisk bci " copy" tra argcopy bci " d=800" tra arg800 bci "d=1600" tra arg1600 bci "d=6250" tra arg6250 dec -1 tra argend equ nargs,(*-args)/2 " arg800: lda =o60,dl sta tapeden eax1 1,1 tra arglp arg1600: lda =o65,dl sta tapeden eax1 1,1 tra arglp arg6250: lda =o41,dl sta tapeden eax1 1,1 tra arglp argtape: lda =h ntape set name of module sta modulename .. lda =h tape and name of subsystem sta subsysname .. stc1 tapesw set switch to indicate tape usage stz copysw clear switch indicating disk copy tra setdrives now try to get drive numbers argdisk: lda =h ndisk set name of module sta modulename .. eax1 1,1 step to next arg lda arg,1 get name of disk subsystem sta subsysname and save stz tapesw clear tape usage flag stz copysw clear disk copy flag tra setdrives try to get drive numbers argcopy: lda =h ncopy set module name sta modulename .. eax1 1,1 step to next arg lda arg,1 get name of disk subsystem sta subsysname and save stz tapesw clear tape usage flag stc1 copysw set disk copy flag tra setdrives get drive numbers setdrives:eax7 0 initialize tape index drivlp: eax1 1,1 step argument index lda darg,1 get tape number tmoz drivend end of list cmpa 63,dl don't allow numbers > idcw device field tpnz drivend .. sta taplst,7 set tape number in list eax7 1,7 step to next slot in list tra drivlp .. drivend: cmpx7 0,du were any numbers supplied? tze arglp if not, use default setting stx7 ntapes set number of tapes lda taplst get first tape number sta tapen and set it for ntape package tra arglp process rest of arguments badarg: tsx2 erpt else, print error acc '^g unknown' arg unknown arg arg,1 tra x2 " argend: stz bf|svh.nvol initialize number of volumes gvloop: tsx2 nextline read an input line lda arg get argument cmpa =h end "end"? tze setup if so, start processing cmpa =h quit "quit"? tze x2 if so, exit command eax0 0 start with first arg tsx2 argmul and get device address extent tra gvloop .. lda arg,0 look at last arg cmpa =-1 was it supplied? tze nolblerr if not, error ldq bf|svh.nvol get current volume number mpy sva_size,dl compute array index epp xs1,bf|svh.sva,ql get pointer in xs1 mvt (id),(pr),fill(20) copy pvname and translate to ASCII arg earg,0 desc9a xs1|sva.pvname,32 gvmvt: arg * tsx2 cklabel read and check volume label stz xs1|sva.skip clear skip indicator lda amdvt,* get devt word sta xs1|sva.devt save szn copysw is this a SAVE COPY? tze gvfirst nope, we don't want to make the following check ldq bf|svh.nvol get the volume number tze gvfirst first time, we cannot check with the last entry lcq =o20,dl load mask cmk xs1|sva.devt-sva_size check the device type with the last volume entry tnz devterr not the same, this is not allowed for SAVE COPY gvfirst: lda amfirst,* get first record to process sta xs1|sva.first save sta xs1|sva.done .. lda amlast,* get last record to process sta xs1|sva.last save aos bf|svh.nvol step volume index tra gvloop and continue to next one " cklabel: stx2 cklbx2 save X2 lda amdvt,* for bulk, any is ok. ana =o17,dl cmpa 1,dl bulk? tze cklbx2 yeh, ok. lda LABEL_ADDR,dl get record number of disk label tsx2 mulbos convert to BOS sector address arg amdvt,* tra x2 tsx2 rdev read it in arg amdvt,* arg bf|LABEL tra lblioerr cmpc (pr),(),fill(040) check the label desc9a bf|LABEL+label.Multics,32 desc9a Multics_label,32 tze mulabel tra if Multics storage system disk szn savesw SAVE or RESTOR? tze lblerr if SAVE, complain about bad label tra cklbx2 if RESTOR, write on unlabelled disk mulabel: cmpc (pr),(pr) test the physical volume name hisldesc: desc9a bf|LABEL+label.pv_name,32 myldesc: desc9a xs1|sva.pvname,32 tnz pvnamerr if not equal, complain tsx2 erpt print the volume name acc " Multics storage system volume ^A." arg hisldesc ldaq bf|LABEL+label.time_map_updated tsx2 cvclock staq time_map_updated tsx2 erpt acc " Time last updated ^g ^g" arg time_map_updated arg time_map_updated+1 lda bf|LABEL+label.pvid sta xs1|sva.pvid copy the volume ID lda bf|LABEL+label.vtoc_size sta xs1|sva.vtoc_size copy the VTOC size szn savesw doing save? tnz cklbx2 if not, skip following szn bf|svh.allsw doing SAVE ALL? tnz cklbx2 if so, don't check for consistent volumes lda bf|LABEL+label.volmap_version Check label format tmoz pre_MR10_label Old cmpa 2,dl MR 10.x tpnz pre_MR10_label No ldaq bf|LABEL+label.time_unmounted tra common_label pre_MR10_label: ldaq bf|LABEL+old_label.time_unmounted common_label: staq time_unmounted ldaq bf|LABEL+label.time_map_updated Get time of map update. cmpaq time_unmounted Same as time of unmount? tze cklbx2 If so, volume is OK. cmpaq bf|LABEL+label.time_salvaged Same as time salvaged? tnz allerr If not, must do SAVE ALL. cmpaq time_unmounted If so, must be later than unmount. tmoz allerr Otherwise, must do SAVE ALL. cklbx2: eax2 * restore X2 tra 0,2 and return " setup: szn nogo did errors occur? tnz stopit if so, stop dead in our tracks eaq ntape_org origin of tape package in QU lda modulename tsx2 ldcom load in the tape package tra x2 lda subsysname get name of subsystem tsx2 inittape init tape package zero tapeden send the density argument zero x2 fatal error return point for opens tra x2 error return lda 4,du thread queue forwards szn copysw unless copying disk tze *+2 .. neg 0 in which case, thread it backwards sta qdelta .. eax3 ql thread tape queue lda =v3/tmp,15/,18/1024 fill in segment and length thq: sta 2,3 eax2 0,3 queue index in X2 adlx2 qdelta X2 points to next entry stx2 0,3 set pointer to next entry eax3 4,3 ada =1024,du cmpx3 ql+128,du tmi thq szn copysw copying disk? tnz thq1 if so, must take special action eax3 qp stx3 ql+128-4 make queue wrap tra qth thq1: eax3 ql+32-4 X3 points to start of first group of 8 stx3 qp set pointer in preamble record thq2: eax3 32,3 thread blocks together stx3 -64+4,3 .. cmpx3 ql+128-4,du tmi thq2 eax3 qp get address of preamble record stx3 ql+96 set pointer at end of last block of 8 qth: stc1 ql+3 put in stoppers stc1 ql+64+3 and half way points to make 2 buffers lda 1,dl set initial volume index sta bf|svh.curvol .. tra go go to beginning of SAVE/RESTOR program " done: tsx2 erpt acc "^d records processed." arg recs tsx2 endtape close out the tape ttyrequest: x2: eax2 * restore X2 lca 1,dl don't chain to another command tra mem|1,2 and return to BOS main control " lblioerr: tsx2 erpt acc "Fatal error reading volume label." tra x2 lblerr: tsx2 erpt acc "Volume is not a Multics storage system volume." stc2 nogo tra gvloop nolblerr: tsx2 erpt acc "No volume label supplied." stc2 nogo tra gvloop pvnamerr: tsx2 erpt acc "Physical volume name does not match request." tsx2 erpt acc "Request is for ^A, but volume name is ^A." arg myldesc arg hisldesc stc2 nogo tra gvloop allerr: tsx2 erpt acc "Volume requires salvaging." tsx2 erpt acc "Use ALL option to save volume." stc2 nogo tra gvloop devterr: tsx2 erpt acc "Multiple device types cannot be processed by SAVE COPY, process each type individually." stc2 nogo tra gvloop stopit: tsx2 erpt acc "Errors found in arguments. Cannot proceed." tra x2 " nogo: bss ,1 non-zero if error(s) in args savesw: bss ,1 zero if performing SAVE tapesw: arg * non-zero if using tape copysw: arg 0 non-zero if copying disk qdelta: bss ,1 used for threading queue modulename: bci " ntape" name of SAVE/RESTOR I/O Module subsysname:bci " tape" name of subsystem used for SAVE/RESTOR tapen: oct 1 current tape number tapeden: bss ,1 tape density setting command ntapes: zero 2,0 numbers of tapes and current index taplst: oct 1 list of tapes to use oct 2 default is tapes 1 & 2 bss ,8 pvbcname: bss ,6 BCD volume name even time_map_updated: bss ,2 Multics_label: aci "Multics Storage System Volume",32 even time_unmounted: bss ,2 " " This is the main loop subroutine for processing a volume. " tsx2 savloop " arg subr called for each 32K block savloop: stx2 svlx2 save return eax3 ql start at beginning of queue lda bf|svp.sva+sva.done start ID ana =o777740,dl sta id lda bf|svp.sva+sva.devt get device type word ana =o17,dl mask device type als 18 move to AU orsa id insert in ID lda bf|svh.curvol get volume index als 24 as part of ID orsa id .. didl: tsx2 ckmore see if any more to do on device tra didend if not, finish with volume lxl7 tpskip,dl set preamble entry to be skipped sxl7 qp .. tsx2 getbits pick up free storage bits tra nextaddr skip call if 32K block is all free ldx2 svlx2 restore X2 tsx2 0,2* make subroutine call nextaddr: lda bf|svp.sva+sva.done get first record not done ora =o37,dl bump to next 0 mod 32 ada 1,dl .. sta bf|svp.sva+sva.done .. stca id,07 set next ID tra didl and loop didend: lxl7 tpdone,dl set stop at preamble queue entry sxl7 qp .. svlx2: eax2 * restore X2 tra 1,2 return to caller " " This is the tape I/O waiting and checking subroutine. " eax3 queue_entry queue entry to be checked " tsx2 savwait " arg errsub subroutine called if tape error " tra eot end of tape handler savwait: stx2 svwx2 save X2 waitl: lxl7 0,3 get flags from queue entry canx7 tpeot,du end of tape? tnz saveot if so, switch to next reel canx7 tpdone,du tape I/O finished? tnz endwait if not, wait for completion tsx2 runtape let tape run some more tra waitl and test again endwait: aos recs count records outputted canx7 tpstat,du tape error? tze svwx2 if not, skip error call ldx2 svwx2 restore X2 tsx2 0,2* make error subroutine call svwx2: eax2 * restore X2 tra 2,2 return to caller saveot: tsx2 endtape finished with this tape lxl7 ntapes get current tape index eax7 1,7 bump by one cmpx7 ntapes compare against total number tmi *+2 .. eax7 0 reset to first tape, if necessary lda taplst,7 get next tape number sta tapen and set it for ntape package sxl7 ntapes remember current tape index ldx2 svwx2 restore X2 tra 1,2 take EOT return " " This is the utility subroutine package for SAVE and RESTOR. " tsx2 getbits get free storage for current 32K block " tra nobits if all addresses are free getbits: stz bits clear result lda bf|svp.sva+sva.done lrl 5 szn bf|svh.allsw if allsw, dont get bits from fsdct tnz doall dump all sectors als 5 now have 0 mod 32 address csl (pr,al),(),bool(03) get 32 bits from map descb bf|svp.bits,32 descb bits(1),32 doall: qrl 18-5 if we should start lda =o400000,du in middle of string ars 0,qu make n bits orsa bits lda bf|svp.sva+sva.done check if tail of bits should be done ora =o37,dl sba bf|svp.sva+sva.last tmoz notail eax7 0,al no, or in some tail bits lda =0,dl lcq =1,dl lls 3,7 orsa bits notail: lda =o377777777770 check if nothing to do ansa bits cmpa bits tze 0,2 tra 1,2 normal return bits: bss ,1 free storage bits " " tsx2 disk_io to write or read block on disk " arg io_proc either rdev or wdev disk_io: stx2 diox2 save X2 stx0 diox2+1 and X0 lxl0 bf|svp.sva+sva.devt device ID in X0 anx0 =o17,du .. again: lda top compute length of xfer sba base als 4 in 64 words sta iolen ldq base tze diox2 all bits on anq =-1,dl get addr only div amaxio,*0 compute number of sectors left in unit neg ada amaxio,*0 als 4 cmpa iolen don't read past end of unit tpl *+2 sta iolen lrl 36+4 lda base set starting address ana =o37,dl als 10+18 sta iooff+1 lda base get multics address ana =-1,dl asq base tsx2 mulbos arg =itp(bf,svp.sva+sva.devt),* tra x2 stca iolen,74 lda iolen ldx2 diox2 restore X2 tsx2 0,2* do disk I/O arg =itp(bf,svp.sva+sva.devt),* arg iooff,* tra ioerr tra if error iod: lda base is more to be done? cmpa top tmi again diox2: eax2 * restore X2 eax0 * and X0 tra 1,2 and return " ioerr: szn disk_brief,* brief mode? tnz ioer1 if so, skip message tsx2 erpt acc 'start of 64 word reads' ioer1: lxl1 iolen if error, read each 64 words anx1 =o7777,du so pages after error will be read "and so error will be isolated sloop: lda iolen ana =o777777770000 ora =1,dl ldx2 diox2 restore X2 tsx2 0,2* arg =itp(bf,svp.sva+sva.devt),* arg iooff,* tra iofatal if error sner: lda 64,du bump addr asa iooff+1 arl 12 asa iolen eax1 -1,1 tpnz sloop szn disk_brief,* tnz ioer2 tsx2 erpt acc 'end of 64 word reads' ioer2: tra iod " iofatal: lda iolen print error with multics addr tsx2 bosmul arg =itp(bf,svp.sva+sva.devt),* tra x2 sta error_sector tsx2 erpt acc 'unrecoverable error, record ^d.' arg error_sector stc2 fatalsw tra sner even iooff: its tmp,* location for disk I/O iolen: bss ,1 vfd 24/sector_address,12/sector_count error_sector: bss ,1 for printing message " " tsx2 copy_to_preamble to copy cur vol info into preamble " " tsx2 copy_from_preamble to retrieve cur vol info from preamble " copy_to_preamble: ldq bf|svh.curvol get current volume number sbq 1,dl minus 1 mpy sva_size,dl multiply by size of array element qls 2 multiply by 4 mlr (pr,ql),(pr) copy array element into preamble desc9a bf|svh.sva,sva_size*4 desc9a bf|svp.sva,sva_size*4 tra 0,2 return to caller copy_from_preamble: ldq bf|svh.curvol get current volume number sbq 1,dl minus 1 mpy sva_size,dl compute array element offset qls 2 as character offset mlr (pr),(pr,ql) copy array element back from preamble desc9a bf|svp.sva,sva_size*4 desc9a bf|svh.sva,sva_size*4 tra 0,2 return to caller " " Queue Manipulation Routines. " " ldx7 flags,du flags for queue entry " tsx2 setq to set ID and flags in queue entry " " tsx2 comp_base to compute base and top for disk I/O " " tsx2 nextq to chain to next queue entry " return with indicators set from stopper setq: lda id get ID sta 1,3 and place in queue entry ldq bits get free storage bits qls 1 shift out previous bit stq bits and save tpl *+2 if unused record, orx7 tpskip,du set skip flag sxl7 0,3 set flags in queue entry aos id bump ID to next devadd tra 0,2 and return to caller comp_base:lxl7 0,3 get flags from queue entry canx7 tpskip,du skip this? tnz 0,2 if so avoid setting base lda 1,3 get ID stac base set base if first time ada 1,dl bump by 1 sta top and set top tra 0,2 return to caller nextq: eax3 4,3 step to next queue entry cmpx3 ql+128,du and loop if at end tmi *+2 .. eax3 ql .. szn 3,3 set indicators from queue stopper tra 0,2 and return to caller " " tsx2 resetq to read/write header and turn off queue " " tsx2 ckmore to see if anything more to do " tra nothing return here if all done " resetq: eax7 0 reset done bit for header sxl7 qh eax7 tpdone and turn on for remainder of list sxl7 qp including preamble record eax3 ql rsql: sxl7 0,3 eax3 4,3 step to next queue entry cmpx3 ql+128,du test for completion tmi rsql .. tra 0,2 return when finished ckmore: szn bf|svp.sva+sva.skip skip bit ON? tnz 0,2 if so, take end return lda bf|svp.sva+sva.done make sure something is left to do cmpa bf|svp.sva+sva.last tpnz 0,2 tra 1,2 " " Routine to Print Tape Starting Point. " " tsx2 pprint " pprint: stx2 pprx2 save X2 lxl7 bf|svp.sva+sva.devt get devt word anx7 =o777760,du mask to get config card pointer lda com|DISK_cd.sub,7 get subsystem name sta ppname and save lda bf|svp.sva+sva.devt get devt word again arl 18 right-justify device number ana =o777,dl mask it sta ppdev and save tsx2 erpt print out info acc "^A (^a ^d) ^d. ON ^g ^d." arg ppdesc arg ppname arg ppdev arg bf|svp.sva+sva.done arg subsysname arg tapen pprx2: eax2 * restore X2 tra 0,2 return to caller ppname: bss ,1 ppdev: bss ,1 ppdesc: desc9a bf|svp.sva+sva.pvname,32 " id: oct 0 current ID for queue entry recs: oct 0 count records saved/restored base: bss ,1 start of block for disk I/O top: bss ,1 end of block for disk I/O qtemp: bss ,1 place keeper in queue rtemp: bss ,1 temporary fatalsw: bss ,1 eight qh: zero qp to write out header zero vfd 3/bf,15/svhc,18/svh_length zero qp: zero ql zero vfd 3/bf,15/svp,18/svp_length+svl_length zero eight ql: bss ,128 " End of include file ...... sav_util.incl.alm " " " ----------------------------------------------------------- " " " " Historical Background " " This edition of the Multics software materials and documentation is provided and donated " to Massachusetts Institute of Technology by Group Bull including Bull HN Information Systems Inc. " as a contribution to computer science knowledge. " This donation is made also to give evidence of the common contributions of Massachusetts Institute of Technology, " Bell Laboratories, General Electric, Honeywell Information Systems Inc., Honeywell Bull Inc., Groupe Bull " and Bull HN Information Systems Inc. to the development of this operating system. " Multics development was initiated by Massachusetts Institute of Technology Project MAC (1963-1970), " renamed the MIT Laboratory for Computer Science and Artificial Intelligence in the mid 1970s, under the leadership " of Professor Fernando Jose Corbato. Users consider that Multics provided the best software architecture for " managing computer hardware properly and for executing programs. Many subsequent operating systems " incorporated Multics principles. " Multics was distributed in 1975 to 2000 by Group Bull in Europe , and in the U.S. by Bull HN Information Systems Inc., " as successor in interest by change in name only to Honeywell Bull Inc. and Honeywell Information Systems Inc. . " " ----------------------------------------------------------- " " Permission to use, copy, modify, and distribute these programs and their documentation for any purpose and without " fee is hereby granted,provided that the below copyright notice and historical background appear in all copies " and that both the copyright notice and historical background and this permission notice appear in supporting " documentation, and that the names of MIT, HIS, Bull or Bull HN not be used in advertising or publicity pertaining " to distribution of the programs without specific prior written permission. " Copyright 1972 by Massachusetts Institute of Technology and Honeywell Information Systems Inc. " Copyright 2006 by Bull HN Information Systems Inc. " Copyright 2006 by Bull SAS " All Rights Reserved " "