" *********************************************************** " * * " * Copyright, (C) Honeywell Information Systems Inc., 1982 * " * * " *********************************************************** " ndisk -- Disk I/O for SAVE/RESTOR. " coded 3/5/75 by Noel I. Morris " modified 11/75 for NSS by Noel I. Morris " Modified November 1981 by C. Hornig to not use IOM rel mode. name ndisk " ****************************************************** " * * " * * " * Copyright (c) 1972 by Massachusetts Institute of * " * Technology and Honeywell Information Systems, Inc. * " * * " * * " ****************************************************** include bosequ include bos_toequ include fs_dev_types " include ntape_equ include config_cards " events are: " 0 = bad data xfer " 1 = no tape " 2 = good " " xrs are: " 0 = buffer index " 1 = log record index " 3 = queue index " " disk format is: " 0/ id of data " 1/ offset of next log. header, offset in log record of following data " ... " logical header: " id " next log header, length of log record " ... " org ntape_org org taperopen tra * org tapewopen tra * org taper tra * org tapew tra * org inittape tra inittape_ org opentaper tra opentaper_ org opentapew tra opentapew_ org runtape tra runtape_ org endtape tra endtape_ " equ's specific to ndisk, they do not appear in ntape or ncopy which do things " differently. equ tpn,1024 length of the output disk buffer " " tsx2 inittape to initialize tape package " zero tapeden ignored by ndisk " zero fatal_error go here on fatal error in opentape(r w)_ inittape_: stx2 intpx2 save X2 ldq 2,2 pick up error return stq tperret and retain tsx2 ljust left-justify subsys name tsx2 geas and convert to ASCII sta tpsubsys save subsystem name lrl 36 move to Q lda =achnl look for CHNL card tsx2 getconf .. tra tpnochnl .. cmpq com|CHNL_cd.sub,7 with correct subsystem name tnz getmore .. eax7 3*2,7 step config index to third channel group eax6 3 test for non-null channel group tpsccd: szn com|CHNL_cd.nchan,7 .. tpnz tpfch use last channel group eax7 -3,7 try previous group eax6 -1,6 .. tpnz tpsccd until finished tpnochnl: stz tpdevt clear devt word lls 36 subsystem name in A tsx2 find_disk look for subsystem arg tpdevt tra tpconferr lxl7 tpdevt get config card index anx7 =o777760,du and mask eax7 DISK_cd.iom-CHNL_cd.iom,7 adjust for difference between cards tpfch: lda com|CHNL_cd.iom,7 get IOM number sba 1,dl minus 1 als 6 move over ada com|CHNL_cd.chn,7 insert channel number ada com|CHNL_cd.nchan,7 add number of channels sba 1,dl minus 1 to get last channel als 18 place in AU sta tpchanno als 9 Shift to PCW position sta tppcw+1 intpx2: eax2 * restore X2 tra 3,2 " " tsx2 endtape to close out tape endtape_: stx2 tpet here to end a tape stc1 tpfin tsx2 runtape szn tpfin wait until finished tnz *-2 tsx2 erpt print total errors on tape acc "disk errors = ^d." arg tperrors szn tprecno last disk? tze tpet if not, just return tsx2 erpt acc "disk records left = ^d." arg tprecno tpet: tra * " " tsx2 opentape(r/w) to open tape " zero queue " zero tapeno opentapew_: stc2 setrtn set return loc from setape tra setape perform setup operations lda =o310000,du get write command stca tprwidcw,40 and set in IDCW eax0 0 buffer index stz tpbuf clear header stz tpbuf+1 eax2 tpw0 simulate call tra tpqtest enter subroutine to get next queue entry " " Finish with current queue entry and get next one. tpwql: tsx2 tpnextq on to the next tpw0: tra tpweot end of tape return szn tpeotsw if end of tape tnz tpweot " Prime new buffer. cmpx0 0,du if at start of buffer tnz tpw1 lda 1,3 fill in header sta tpbuf with id lda 2,du sta tpbuf+1 eax0 2 next header at word 2 " Strip trailing zeroes from the data. tpw1: eaq 0,7 length in QU mpy =6,dl compute 6-bit character length tctr (pr,rl) search backward for non-zero word desc6a xs1|0,qu .. arg tctable .. arg tptemp .. ldq tptemp get tally to non-zero character anq =o77777777 mask the tally div =-6 get word tally and complement eax7 1,ql place in X7 and round to nearest even adx7 tplenq subtract from original length anx7 =o777776,du round stx7 tplen save length with stripped zeroes " Set logical header and copy data. sxl7 tpbuf+1,0 set data length in header tpw3: lda 1,3 set id in log header sta tpbuf,0 stx1 tptemp save current data offset eax7 2,0 will rest of data fit in this phy rec? adx7 tplen compute next buffer index sbx7 tptemp sub off what is done cmpx7 tpn,du is it larger than tape record? tmi *+2 tra if no eax7 tpn set index to fill rest of phy rec stx7 tpbuf+1,0 store index to next header eax0 2,0 skip over header info stx0 tpcopyl store current index ssx7 tpcopyl subtract from next index tze tpwc0 if zero, avoid IPR fault lda tpcopyl word count to copy in AU als 2 get character count eax7 0,au in X7 eaa 0,0 buffer offset in AU eaq 0,1 data offset in QU lls 2 compute character offsets mlr (pr,rl,qu),(rl,au) copy the data into buffer desc9a xs1|0,x7 desc9a tpbuf,x7 tpwc0: adx0 tpcopyl bump buffer index and adx1 tpcopyl data index by amount copied " If more data, then write out this record and proceed. " Otherwise, go get next queue entry. cmpx0 tpn,du if buffer not full tnz tpwql go get more tsx2 tpwrit write record eax0 0 reset buffer pointer cmpx1 tplen if all of log record tpl tpwql go get more sxl1 tpbuf+1 set current data offset in header tra tpw3 and copy more data " " End of logical or physical tape. tpweot: eaa 0,0 current buffer offset in AU neg 0 subtract from buffer length eaa tpn,au to get remaining length tze tpwlast avoid IPR on zero length eaq 0,0 buffer offset in QU lls 2 get character count and offset mlr (),(rl,qu),fill(777) pad rest of record with 1's desc9a *,0 desc9a tpbuf,au tpwlast: tsx2 tpwrit write out last record tpreot: " Done with tape, unload it unless it is the last. szn tpfin Zero if tape full, not if closing out last tape. tnz tpnorwun lda tpdevt Check the device type to make sure we don't try to unload one we can't ana =o17,dl lda fs_dev.media_removable-1,al tze tpnorwun tsx2 dotape Rewind and unload the tape, expecting another. oct 72 tra *+1 tpnorwun: lda tpeot,dl get EOT flag orsa 0,3 set in queue entry stz tprunning tape no longer connected tsx2 tpret wait for new open call stz tpfin let endtape return tra tpret " tpwrit: stx2 tpwx2 here to write a record tpwrag: stz tpct reset count of tries to write tsx2 tpnextrec set sector address of next record tprewt: tsx2 connect_iom start io zero tppcw,tpsidcw stc2 tprunning set state tsx2 tpret tra tpwbad retry io errors tra tprewt retry no tape szn tpeotsw end of disk? tnz tpreot if so, stop here tpwx2: tra * tpwbad: aos tpct count another try lda tpct check for 5 tries cmpa 5,dl .. tmi tprewt keep trying szn tpeotsw end of disk? tnz tpreot if so, stop trying tra tpwrag try to write next record " " tsx2 opentape(r/w) to open tape " zero queue " zero tapeno opentaper_: stc2 setrtn set return from setape tra setape setup for tape operation lda =o250000,du get read command stca tprwidcw,40 set IDCW eax0 tpn initialize buffer index to force tape read eax2 tpr0 set return loc for subroutine tra tpqtest go get first queue entry " " Proceed to next queue entry. tprql: tsx2 tpnextq get next queue entry tpr0: tra tpreot end of tape return " Search for correct logical record. tprsl: cmpx0 tpn,du if through record, get another tmi *+2 .. tsx2 tprd .. lda tpbuf,0 pick up ID tmi tpreot test for end of tape cmpa 1,3 is this correct ID? tmi tpnid if not far enough, search more tpnz tprfatal if too far, record is lost cmpx0 0,du at beginning of physical record? tnz tpr2 if not, go set length ldx7 tpbuf+1 X7 = 2 => not a continuation record cmpx7 2,du must not have a continuation record here tnz tprfatal .. tpnid: ldx0 tpbuf+1,0 go to next header tra tprsl .. " Set length of logical record. tpr2: lxl7 tpbuf+1,0 set length stx7 tplen eax1 0 and index " Copy data from tape record. When finished, pad copied data with zeroes. tprcpy: ldx7 tpbuf+1,0 copy data from tpbuf eax0 2,0 skip over header info stx0 tpcopyl store current index ssx7 tpcopyl subtract from next index lda tplenq remaining data length in AU ldq tpcopyl length to copy in QU lls 2 compute character lengths eax6 0,au target length in X6 eax7 0,qu source length in X7 eaa 0,0 get buffer offset eaq 0,1 and data offset lls 2 compute character offsets adx0 tpcopyl bump buffer index adx1 tpcopyl and data index cmpx1 tplen is this the last copy? tpl *+2 tra if so eax6 0,7 if not, don't pad the data cmpx6 0,du are we copying anything? tze tprc0 if not, avoid IPR fault mlr (rl,au),(pr,rl,qu),fill(0) copy and pad desc9a tpbuf,x7 desc9a xs1|0,x6 lca tpcopyl get length copied asa tplenq subtract from remaining data length tprc0: cmpx1 tplen have we transferred all data? tpl tprql yes. get next queue entry " Read and check continuation record. tsx2 tprd read the next physical record cmpa 1,3 correct ID? tnz tprfatal no, fatal error lxl7 tpbuf+1 get offset of first word stx7 tptemp .. cmpx1 tptemp check against desired offset tze tprcpy offset good. copy the data " Fatal error. Mark failure in queue entry. tprfatal: lda tpstat,dl get tape error flag orsa 0,3 insert in queue entry flags tra tprql and get next queue entry " " Read and Check Tape Record. tprd: stx2 tprx2 save X2 tpag1: stz tpct clear count of tries szn tpeotsw have we finished with last record? tnz tpreot if so, quit tsx2 tpnextrec set sector address for next record tpcon: tsx2 connect_iom start read zero tppcw,tpsidcw stc2 tprunning tsx2 tpret set state to reading data tra tpag2 try again on bad read tra tpcon retry if not ready lda tpbuf get first logical ID tmi tpreot if negative, end of tape eax0 0 reset index to first logical header tprx2: eax2 * restore X2 tra 0,2 and return to caller tpag2: aos tpct count another try lda tpct count tries cmpa 5,dl too many? tmi tpcon if not, try again tra tpag1 if so, go to next record " " tsx2 runtape to keep tape moving runtape_: stx2 tprunx2 save callers regs szn tprunning tape connected? tze tpstatp if not, skip check_status call tsx2 check_status arg =0 tra *+2 tra *+1 tpstatp: lda tpstatus get saved status cmpa tpoldstatus has it changed? tze tprunx2 if not, don't print it sta tpoldstatus save for comparison tsx2 erpt print error status acc 'ndisk: disk status = ^w.' arg tpstatus lda tpdetail convert detailed status to hex tsx2 hexwd sta tphex ldaq tpdetail lls 24 tsx2 hexwd sta tphex+1 ldq tpdetail+1 lls 48 tsx2 hexwd ora =h0000 " sta tphex+2 tsx2 erpt print detailed status acc 'ndisk: detailed status = ^g^g^g.' arg tphex arg tphex+1 arg tphex+2 tprunx2: eax2 * szn tprunning tape running now? tnz 0,2 if so, return to caller sreg tphisreg lreg tpmyreg load mine ldx2 tpstate and tra to state prog tra 0,2 at run entry tpret: stx2 tpstate remember where we were sreg tpmyreg here to return, save my regs lreg tphisreg and load theirs tra 0,2 " " ldaq status " tsx2 tpint to deliver status tpint: sznc tprunning tape connected? tze 0,2 if not, must be spurious call sreg tphisreg save callers machine lreg tpmyreg restore mine ldx2 tpstate lda tphisreg+4 get status cana =o370000770000 Check for all bad status. tnz tperr If bad, analyze error. stz tpstatus Clear old status. stz tpoldstatus .. tra 2,2 Report normal termination. tperr: sta tpstatus save tsx2 xio_wait read detailed status vfd 18/tpdetail,12/2 zero tpchanno,18 tra *+1 ldx2 tpstate state in X2 again lda tpstatus status in A eaq 0,au Major status in QU. qrl 12 Right-justify in QU. anq =o37,du Mask major status and power bit. tra tpdisp,qu Dispatch on major status. tpdisp: tra tpbio 0: IOM channel or central error tra tpatt 1: device busy tra tpatt 2: device attention tra tpbio 3: device data alert tra tpbio 4: end of file tra tpbio 5: command reject tra tpbio 6: tra tpbio 7: tra tpbio 10: tra tpbio 11: tra tpbio 12: MPC device attention tra tpbio 13: MPC device data alert tra tpbio 14: tra tpbio 15: MPC command reject tra tpbio 16: tra tpbio 17: tra tpatt 20: peripheral absent or power off tpbio: aos tperrors count errors tra 0,2 take error return tpatt: tra 1,2 Retry operation. " " Utility subroutines. " tsx2 setape to set up PCW and IDCW's. setape: eax2 2,2 change return loc sreg tphisreg save registers ldx3 -2,2 get queue pointer in X3 lda -1,2* get tape # in A sta tapeno fill tape number into pcw's als 18 but first place in devt word sta tpdevt .. als 6 stca tppcw,20 stca tpsidcw,20 stca tprwidcw,20 stca tpdidcw,20 stz tpfin clear flags stz tpeotsw stz tperrors Clear error count. tsx2 get_status_interrupt reset status handler routine arg =0,0 lda tpsubsys get subsystem name tsx2 find_disk get subsystem info arg tpdevt tra tperret,* lda disk_brief,* get brief switch setting sta tpsvbf and save it stc2 disk_brief,* suppress disk error messages stc2 tpqfirst set first query switch tprdy: tsx2 query_disk see if disk is storage system volume arg tpdevt tra tpnotrdy tra *+2 if not, proceed tra tperret,* if so, take error return lda tpsvbf restore brief switch setting sta disk_brief,* .. lxl7 tpdevt get device type in X7 anx7 =o17,du .. lda rec_per_dev_list,*7 get number of records on device sba 1,dl compute last record sta tprecno start with last record on device tsx2 get_status_interrupt Run "interrupt" driven for faster response. zero tpchanno,tpint setrtn: tra * return to caller " " tsx2 tpnextrec to set next record number tpnextrec:stx2 tpnxrx2 save X2 lda tprecno get next record number tsx2 mulbos convert to sector address arg tpdevt tra * stop on error arl 12 sector address in A(12-35) stca tpsect,17 place in seek address word lda tprecno decrement record number sba 1,dl .. sta tprecno .. tpnz *+2 if at first record, stc1 tpeotsw set EOT flag tpnxrx2: tra * return to caller " " tsx2 tpnextq to discard current queue and get next entry tpnextq: lda tpdone,dl finish with current queue entry orsa 0,3 turn on done bit ldx3 0,3 step to next queue entry tpqtest: lda 0,3 get flags cana tpdone,dl anything to do? tze tpnd if so, go to it szn tpfin finished with tape? tnz 0,2 if so, take end of tape return stx2 tpnqx2 save X2 stz tprunning set state to waiting tsx2 tpret and wait for more work tpnqx2: eax2 * run call, restore X2 tra tpqtest see if more work to do tpnd: cana tpskip,dl skip this queue entry? tnz tpnextq if so, go get another one ora tpstat,dl turn off error bit era tpstat,dl .. sta 0,3 store flags back in queue entry ldx7 2,3 get segment # and offset eaa 0,7 segment # in A (0-2) anx7 =o77777,du mask the offset arl 15 right-justify segment # in AU easp xs1,0,au pr 4 -> data segment eawp xs1,0,7 .. lxl7 2,3 get length from queue eax7 1,7 round to next even anx7 =o777776,du .. stx7 tplenq save data length eax1 0 reset data index tra 1,2 return to caller " " tsx2 dotape to perform non-data transfer operation " oct command " tra error dotape: stx2 dx lda 0,2 als 30 fill in command stca tpdidcw,40 domore: tsx2 connect_iom start oper zero tppcw,tpdidcw stc2 tprunning tsx2 tpret wait for status tra dobad tra domore dx: eax2 * tra 2,2 dobad: ldx2 dx tra 1,2 " tpconferr: tsx2 erpt acc "ndisk: Cannot get disk channel number." tra tperret,* tpnotrdy: sznc tpqfirst first time? tze tprdy if not, keep trying tsx2 erpt ask operator to ready disk acc "ndisk: please ready ^a ^d." arg tpsubsys arg tapeno tra tprdy now, try again " " Storage and Constants. tpstate: bss ,1 last loc'n in ntape package tprunning:bss ,1 non-zero if tape connected tpfin: bss ,1 non-zero to finish up tape tpeotsw: bss ,1 non-zero when EOT reflector encountered tperret: bss ,1 error return tapeno: bss ,1 current tape handler # tplen: bss ,1 length of logical record on tape tplenq: bss ,1 length of logical record from queue tpchanno: bss ,1 tape channel # tpct: bss ,1 # of records skipped reading tpstatus: bss ,1 tpoldstatus: bss ,1 even tpdetail: bss ,2 tphex: bss ,3 tptemp: bss ,1 tperrors: bss ,1 count of errors on tape tpcopyl: bss ,1 # of words to copy tpsubsys: bss ,1 disk subsystem name tpdevt: bss ,1 devt word tprecno: bss ,1 current record number on disk tprtemp: bss ,1 temporary for record calculation tpsvbf: bss ,1 place to save brief switch tpqfirst: bss ,1 non-zero on first query tpsect: vfd 12/tpn/64,24/0 sector address for seek tctable: vfd 9/0,9/1,9/1,9/1 table to stop tct on non-zero character vfd 9/1,9/1,9/1,9/1 vfd 9/1,9/1,9/1,9/1 vfd 9/1,9/1,9/1,9/1 vfd 9/1,9/1,9/1,9/1 vfd 9/1,9/1,9/1,9/1 vfd 9/1,9/1,9/1,9/1 vfd 9/1,9/1,9/1,9/1 vfd 9/1,9/1,9/1,9/1 vfd 9/1,9/1,9/1,9/1 vfd 9/1,9/1,9/1,9/1 vfd 9/1,9/1,9/1,9/1 vfd 9/1,9/1,9/1,9/1 vfd 9/1,9/1,9/1,9/1 vfd 9/1,9/1,9/1,9/1 vfd 9/1,9/1,9/1,9/1 " " DCW Lists and Tape Buffers. even tppcw: vfd o6/40,6/0,6/0,3/7,3/2,6/2,6/1 reset status (PSIA compat.) vfd 9/*-* tpsidcw: vfd o6/34,6/0,6/0,3/7,3/2,6/0,6/0 Seek. vfd 18/tpsect+pgmorg,6/0,12/1 IOTD tpsect,1 tprwidcw: vfd o6/25,6/0,6/0,3/7,3/0,6/0,6/0 Read/Write disk. vfd 18/tpbuf+pgmorg,6/0,12/tpn IOTD tpbuf,tpn tpdidcw: vfd o6/0,6/0,6/0,3/7,3/0,6/2,6/1 Non-data operation. tpddcw: vfd 6/0,6/0,6/0,3/7,3/0,6/2,6/1 Request status (just in case). eight bss tpmyreg,8 bss tphisreg,8 bss tpbuf,tpn include qdisk " include fs_vol_label include bos_tv include bos_common end " " " ----------------------------------------------------------- " " " " 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 " "