1 ; I T S DISK SERVICE ROUTINES AND FILE SYSTEM -*-MIDAS-*-
2 ;;; Copyright (c) 1999 Massachusetts Institute of Technology
4 ;;; This program is free software; you can redistribute it and/or
5 ;;; modify it under the terms of the GNU General Public License as
6 ;;; published by the Free Software Foundation; either version 3 of the
7 ;;; License, or (at your option) any later version.
9 ;;; This program is distributed in the hope that it will be useful,
10 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ;;; General Public License for more details.
14 ;;; You should have received a copy of the GNU General Public License
15 ;;; along with this program; if not, write to the Free Software
16 ;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 IFN DC10P+RP10P+RH10P+RH11P-1, .ERR WRONG NUMBER OF DISK CONTROLLERS
22 ;GET DISK PHYSICAL PARAMETERS BY .INSRT'ING APPROPRIATE FILE
38 IFE KS10P, .ERR RH11 on something other than a KS10?
39 IFN RP06P+RM03P+RM80P-1, .ERR WRONG NUMBER OF KINDS OF DISK DRIVE
51 ;GET FILE SYSTEM DEFINITIONS:
52 ; MFD MASTER FILE DIRECTORY
53 ; TUT TRACK (BLOCK) UTILIZATION TABLE
54 ; UFD USER FILE DIRECTORY
62 SUBTTL MISC FILE SYSTEM CALLS
64 ADMPCH: UMOVE A,(J) ;SET OR READ STATUS OF DUMP BIT OF FILE OPEN ON
66 MOVEI T,POPJ1 ;MAKE CHNDCD SKIP RETURN IF ALL OK.
67 PUSHJ P,CHNDCD ;DECODE RH(A) AS CHNL NUM.
68 JRST ILUUO ;NO SKIP IMPLIES BAD CHNL NUM.
70 JRST ILUUO ;NOT DISK CHANNEL.
71 PUSHJ P,QCHNLT ;DECODE THE CHNL FURTHER.
80 LDB A,[430100,,UNRNDM(C)]
84 NRFDATE: PUSHJ P,QCHNLT ;READ FILE CREATION DATE WORD
87 JRST POPJ1 ;STORE BACK IN USER MEM
89 NSRDATE: PUSHJ P,QCHNLT ; SET REFERENCE DATE
91 DPB B,[UNREFD+UNREF(C)]
94 NRESRDT: PUSHJ P,QCHNLT ; RESTORE REFERENCE DATE
95 HLRZ A,OLDRDT(R) ; WHOEVER CHOSE R IN QCHNLC SHOULD BE SHOT
96 DPB A,[UNREFD+UNREF(C)]
99 NSFDATE: PUSHJ P,QCHNLT ;SET FILE CREATION DATE WORD
107 NRDMPBT: PUSHJ P,QCHNLT ;READ FILE DUMPED BIT
108 LDB A,[430100,,UNRNDM(C)]
111 NSDMPBT: PUSHJ P,QCHNLT ;SET FILE DUMPED BIT
112 DPB B,[430100,,UNRNDM(C)]
116 PUSHJ P,QCHNLT ;RETURN NONZERO IF WE TRACED LINKS TO GET THIS FILE.
118 LDB A,[.BP (%QALOP),T]
121 NFILBLK:PUSHJ P,QCHNLT ;READ ALL 5 PARAMETERS OF NAME AREA
127 JRST NRDM1 ; UNLOCK DIR AND STORE ARGUMENTS
129 QCHNLT: TLNN R,%CLSQ ;IS CHNL A DISK CHNL?
130 JRST [SUB P,[1,,1] ? JRST OPNL34]
139 ASAUTH: PUSHJ P,QCHNLT ;SET AUTHOR OF FILE
141 JUMPE B,ASAUT4 ;SETTING AUTHOR TO 0
166 DPB J,[UNAUTH+UNREF(C)]
169 ARAUTH: PUSHJ P,QCHNLT ;READ CREATOR OF FILE
170 LDB B,[UNAUTH+UNREF(C)]
171 MOVEI A,0 ;RETURN VALUE IS 0 IF UNKNOWN OR ILLEGAL AUTHOR
175 MOVEI B,2000-<NUDSL*2>(B)
181 ASREAP: PUSHJ P,QCHNLT ;SET NO REAP BIT
182 DPB B,[.BP (UNREAP),UNRNDM(C)]
185 ARQDAT: CONO PI,CLKOFF ;GET DSK TIME AND DATE
188 MOVE B,QDATEI ;2ND VALUE = DATE & TIME SYS CAME UP, IN DISK FORMAT.
192 ADSKUP: PUSHJ P,QCHNLT ;SET CREATION DATE, REF DATE AND CLEAR DUMP BIT
199 DPB TT,[UNREFD+UNREF(C)]
204 DELEWO: TLNN R,%CLSQ ;DELETE WHILE OPEN
205 JRST OPNL34 ;WRONG TYPE DEVICE
210 MOVE A,UNFN1(C) ;Get names of file being hacked.
213 PUSHJ P,MNGDIR ;If this is a sanctified dir
214 PUSHJ P,SYSDSK ; get SYS job to tattle about it.
217 MOVSI T,%QADEL ;SET DELETE BIT IN QSK CHNL
219 MOVSI T,UNCDEL ;AND IN FILE
224 ;RETURNS (1) FILE LENGTH IN BYTES (BYTE SIZE CURRENTLY OPEN IN)
225 ; (2) BITS PER BYTE (BYTE SIZE CURRENTLY OPEN IN)
226 ; (3) FILE LENGTH IN BYTES (BYTE SIZE WRITTEN IN)
227 ; (4) BITS PER BYTE (BYTE SIZE WRITTEN IN)
229 NFILLEN:PUSHJ P,QCHNLT
232 JRST OPNL34 ;NOT A FILE
235 JRST NFILL1 ;READ CHANNEL OR WRITE-OVER, GET FILE'S STORED LENGTH.
236 MOVE A,QFBLNO(R);NORMAL WRITE, GET ACCESS POINTER.
238 JRST NFILL2 ;NO BUFFER ACTIVE
239 ADD A,QMPBSZ(R) ;END OF CURRENT BUFFER
240 SUB A,QSMPRC(R) ;BACK UP TO CURRENT LOC
241 NFILL2: PUSHJ P,QUDULK
242 LDB B,[QSBSIZ(R)] ;CURRENT BYTE SIZE
243 MOVE D,B ;WRITTEN BYTE SIZE SAME AS CURRENT
244 MOVE C,A ;WRITTEN LENGTH SAME AS CURRENT
247 NFILL1: LDB TT,[UNDSCP+UNRNDM(C)]
249 HLL TT,QBTBLI(I) ;GET DESCRIPTOR POINTER
250 LDB E,[UNWRDC+UNRNDM(C)]
252 MOVEI E,2000 ;E GETS NUMBER OF WORDS IN LAST BLOCK
253 LDB D,[UNBYTE+UNREF(C)] ;D GETS BYTE INFO
254 ANDI C,-2000 ;C GETS BASE ADDR OF DIR
255 ADDI TT,UDDESC(C) ;TT GETS DESC PNTR
256 SETOM A ;INITIALIZE NUMBER OF BLOCKS IN FILE
257 PUSHJ P,NFLLN1 ;A GETS NUMBER OF BLOCKS IN FILE MINUS ONE
259 IMULI A,2000 ;NUMBER OF WORDS IN COMPLETE BLOCKS
260 ADD A,E ;ADD WORDS IN LAST BLOCK
261 PUSHJ P,QBDCD ;D GETS BYTE SIZE, E NUMBER OF RESIDUE BYTES
263 IDIV Q,D ;Q GETS BYTES PER WORD
264 MOVE C,A ;C WRITTEN LENGTH, A CURRENT (B.S. DIFFERENT)
265 IMUL C,Q ;CONVERT WORD LENGTH TO BYTES
266 SUB C,E ;C NOW HAS CORRECT WRITTEN LENGTH
267 IMUL E,D ;E GETS NUMBER OF RESIDUE BITS
268 LDB B,[QSBSIZ(R)] ;B GETS BYTE SIZE OPENED IN
269 IMULI A,@QSBYTE(R) ;A GETS LENGTH IN THOSE SIZE BYTES
270 IDIV E,B ;NUMBER OF RESIDUE BYTES, -ROUNDING DOWN-
271 SUB A,E ;ADJUST THE LENGTH
272 JRST POPJ1 ;RETURN VALUES IN A,B,C,D
274 NFLLN2: ADD A,B ; NEXT N BLOCKS
275 NFLLN1: ILDB B,TT ; GET NEXT DESC BYTE
276 JUMPE B,CPOPJ ; NO MORE
280 AOJA A,NFLLN1 ; SKIP-N, TAKE-1
282 JRST NFLLN1 ; IGNORE WRITE-PLACEHOLDER
283 REPEAT NXLBYT, IBP TT ; LOAD-ADDRESS, TAKE-1
286 ;DIRSIZ - READ OR SET DISK QUOTAS, READ # BLOCKS IN ALL FILES IN DIRECTORY.
287 ;1ST VALUE IS GRIM REAP QUOTA,,DIR SIZE
288 ;2ND VALUE IS 0 OR PACK#,,ALLOCATION FOR DIR ALLOCATED TO SPECIFIC PACK
289 ;LH OF 2ND ARG SETS GRIM REAP QUOTA; 3RD ARG SETS PACK#,,ALLOCATION
297 NDIRS1: MOVE B,UDALLO(C)
301 HLRZS D ;PACK ALLOCATED TO
304 MOVEI E,NQS-1 ;UPDATE ALLOC DRIVE NUM
307 NDIRS2: MOVEM E,QSALLO(H)
311 SUBTTL DISK OPEN ROUTINES
313 %DO==1,,525252 ;Special mode bits for disk opens.
314 %DOWOV==100000 ;Write over mode
315 %DONRF==10 ;Don't set ref-date
316 %DONLK==20 ;Don't chase links; actually open the link itself.
317 %DORWT==40 ;Make readers wait (used on opens for write or write-over).
320 TPLO: MOVE C,[SIXBIT /.LPTR./] ;PSEUDO LINE PRINTER (DISC)
323 AOS A,TPLFNO ;GENERATE RANDOM FILE NAME
327 COMO: SKIPA C,[SIXBIT /COMMON/] ;.OPEN ENTRY FOR "COM" DEVICE
328 SYSO: MOVSI C,(SIXBIT /SYS/) ; " FOR "SYS" DEVICE
329 TPLO2: MOVEM C,USYSN1(U)
333 QSKPO: MOVSI TT,-NQS ;PACK # OPEN
335 AOBJN TT,.-1 ;I <= PHYSICAL UNIT WITH SPECIFIED PACK
339 CAIE W,4 ;IF RENAME/DELETE, OK, DOESN'T TOUCH FILE ANYWAY
340 JRST OPNL16 ;OTHERWISE COMPLAIN PACK NOT MOUNTED
342 QSKUO: CAIGE I,NQS ;DISK UNIT # OPEN
343 SKIPE QACT(I) ;I <= UNIT #
344 JRST OPNL10 ;BAD UNIT # OR NOT ENGAGED
345 IFE MCOND DM,[ ;; Security check in reserved pack feature only on DM.
347 JUMPN W,QSKOB ;WRITE-OVER OR RENAME OK.
348 JUMPGE D,QSKOB ;READ OK.
349 SKIPE QRESRV(I) ;WRITE: IS PACK ON THIS DRIVE RESERVED?
350 JRST OPNL10 ;YES, CAN'T WRITE ON IT.
355 ;DNRF: DEVICE IS LIKE DSK: BUT DOESN'T SET REFERENCE DATE
356 DNRFO: TRO D,%DONRF/2 ;SET MODE BIT AND DROP INTO QSKO
358 ; Regular DSK: device
360 ; RH(D) has open mode, rotated 1 bit right.
361 ; W has operation code (0=r/w, 2=link, 4=del/rnm, 1=wov)
363 QSKO: MOVNI I,1 ;DSK OPEN, I <= # DETERMINED BY SYS
364 QSKOB: MOVEM I,EPDL(U) ;SAVE DISK #
367 JUMPE A,QSKOB2 ;IF RENAME OF OPEN FILE TRAP OUT
368 QSKOA: MOVE I,MDSK ;IS MFD IN?
369 PUSHJ P,QMCH1 ;READ IN MFD OF MASTER DISK
370 CLEARM QLD(U) ;LINK DEPTH
374 JUMPL D,OPNL11 ;MUST BE NORMAL READ
375 JRST QMLSTF ;USER WANT TO READ THE MASTER DIRECTORY
377 MFDCK: CAMN A,[SIXBIT /M.F.D./]
378 CAME B,[SIXBIT /(FILE)/]
382 SYSDS2: PUSHJ P,QFLD ;H <= PTR TO USER DIR TABLE
383 PUSHJ P,QSKO1 ;LOSER DIR NOT IN CORE
386 PUSHJ P,QUDLK ;RETURN WITH SOS OF QSNNR ON LSWPR
389 JRST QSKDP1 ;PAW OVER USER DIRECTORY
390 QSKDP2: PUSHJ P,QUDULK
392 JRST QSKDP9 ;NOT SPECIAL DIRECTORY FILE
395 JRST QLISTF ;USER WANTS TO READ HIS USER DIRECTORY
397 QSKDP9: JUMPN W,QSKDPY ;If doing IO?
398 SKIPL D ; and reading
399 JRST QSKDPZ ; then don't bother with "security".
400 QSKDPY: PUSHJ P,MNGDIR ;Else if this is a sanctified dir
401 PUSHJ P,SYSDSK ; get SYS job to tattle about it.
402 QSKDPZ: JUMPL D,QWRO ;WRITE
404 JRST QRNAM ;RENAME/DEL
406 JRST QALINK ;MAKE LINK
408 QWROR: JUMPE A,QPNL11 ;ALSO ENTER FOR VARIOUS WRITE OVER, COPY OVER MODES
410 PUSHJ P,QCHNF ;GET CHANNEL FOR READ
413 PUSHJ P,QUDLK ;LOCK USER DIR
414 PUSHJ P,QLOOK ;LOOK UP FILE
415 JRST [ PUSHJ P,QROR1C ;Not found => decide whethe error or wait.
416 POPJ P, ;Error (error code already set up).
417 PUSHJ P,QUDULK ;If retrying, first unlock directory,
418 PUSHJ P,LSWPOP ;Return the channel,
419 PUSHJ P,UDELAY ;Wait a little while,
420 JRST QWROR] ;Try again.
421 TRNE D,3 ;SKIP IF UNIT ASCII MODE
423 MOVE J,[440700,,5] ;BYTE SIZE IS 7 BITS
425 QSKO2: HLLZ J,QSBYTE(E) ;GET PROPER BYTE POINTER LH
427 TRNN D,%DONRF/2 ;3.4 BIT IN OPEN IMPLIES DONT SET REFERENCE DATE
428 PUSHJ P,QFREF ;"REFERENCE" FILE
431 HRRZM C,QUDFPR(E) ;SET UP PTR FROM CHNL TO FILE NAME AREA
432 LDB TT,[UNDSCP+UNRNDM(Q)] ;FOUND FILE SET UP CHNL
433 MOVEM TT,QDIRP(E) ;SET UP CHAR PTR TO DESC AREA
436 JRST QLINK ;FILE IS A LINK
438 SKIPE QLD(U) ;IF WE TRACED A LINK TO OPEN THE FILE, REMEMBER THAT.
443 LDB J,[UNPKN+UNRNDM(Q)] ;GET PACK NUMBER FILE IS ON
446 AOBJN I,.-1 ;TRANSLATE LOGICAL TO PHYSICAL DISK UNIT
447 JUMPGE I,QPKNF ;PACK NOT ON *
448 HRRZM I,QDSKN(E) ;SET CHNL DISK NUMBER
449 JUMPL D,QWROR1 ;REALLY WANT TO WRITE OVER, ETC
450 MOVEI TT,%QMRD ;PUT CHANNEL IN NORMAL READ MODE
452 QOEX1: PUSHJ P,QUDULK ;UNLOCK USER DIR
453 PUSHJ P,LSWDEL ;QUSR ENTRY
454 PUSHJ P,LSWDEL ;QSNNR ENTRY
461 JSP Q,OPSLC7 ;SET UP IOCHNM AND DEPART
467 QWROR1: SOJN W,OPNL12 ;NORMAL WRITE OVER MODE
468 HRRZS H ;CLEAR GARBAGE IN USER DIR NUM
469 HRRZS E ;CLEAR GARBAGE IN CHNL NUM
470 HRRZ J,QUDFPR(E) ;PICK UP LOCN OF FILE WITH U.F.D
471 MOVSI I,-NQCHN ;MAKE SURE THIS FILE NOT OPEN FOR READING
472 QROR1A: CAIE E,(I) ;DONT GET FAKED OUT BY OWN CHNL
480 QROR1B: AOBJN I,QROR1A
483 IORM TT,UNRNDM(Q) ;SET WRITE BIT
489 PUSH P,E ;CONVERT FROM ORIGINAL BYTE SIZE TO ONE OPENED IN NOW
490 LDB D,[UNBYTE+UNREF(Q)]
491 PUSHJ P,QBDCD ;GET INFO FROM ORIGINAL WRITE OF FILE
493 IDIV Q,D ;BYTES PER WORD
494 SUB Q,E ;# VALID BYTES
495 IMUL Q,D ;VALID BITS IN LAST WORD
496 POP P,E ;RESTORE QSK CHNL #
497 HRRZ R,QSBYTE(E);BYTES PER WORD IN NEW BYTE SIZE
498 LDB J,[QSBSIZ(E)] ;BITS PER BYTE IN NEW BYTE SIZE
499 IDIV Q,J ;NUMBER OF NEW-SIZE BYTES IN LAST WORD
500 SUB R,Q ;RESIDUE IN NEW-SIZE BYTES
501 LDB Q,[QSBSIZ(E)] ;NEW BYTE SIZE
502 PUSHJ P,QBENC ;RH(Q) GETS NEW BYTE INFO
504 DPB Q,[UNBYTE+UNREF(R)] ;CLOBBER FILE'S BYTE SIZE
514 DPB TT,[UNREFD+UNREF(Q)]
518 MOVSI TT,%QAMWO ;WRITE OVER MODE
519 IORM TT,QSRAC(E) ;LEAVE %QMIDL UNTIL FIRST .IOT SINCE
520 JRST QOEX1 ; THE USER WILL PROBABLY DO A .ACCESS
522 ;Call here if lookup fails on open.
523 ;Either signal some error and return,
524 ;or skip-return if caller should wait and retry the lookup.
525 ;Assumes H has dir slot, Q has address of filename block,
526 ;E has channel number allocated for this open.
528 QROR1C: HRRZ C,QSNLCN(H)
530 SKIPL Q ;SEE IF STILL POINTED INSIDE DIR
532 JRST QROR1D ;NO - REALLY FNF
534 CAMN A,UNFN1(Q) ;DO NAMES MATCH?
536 JRST QROR1D ;NO - REALLY FNF
537 HRRZ J,Q ;Find channel that has this file open.
540 HRRZS H ;Clear garbage in user dir num
541 HRRZS E ;Clear garbage in chnl num
543 QROR1E: CAIE E,(I) ;Dont get faked out by our own chnl.
549 ;Found the channel. Does it want us to wait?
552 JRST OPNL23 ;He didn't say so => get "file locked".
555 QROR1F: AOBJN I,QROR1E
556 JRST POPJ1 ;Cannot find channel => maybe was closed. Retry.
559 JRST OPNL4 ;FILE NOT FOUND
560 JRST OPNL47 ;LINK WAS FOUND, BUT NOT THE FILE IT POINTED TO
562 ;COME HERE FOR RENAME-WHILE-OPEN
563 QSKOB2: HRRZ A,B ;DO RENAME WHILE OPEN HERE TO AVOID
564 CAIL A,20 ;IN CASE SYS NAME HAS CHANGED
583 PUSHJ P,QGRLSC ;EITHER NAME > OR <?
584 JRST OPNL11 ;BOTH-BARF
585 PUSHJ P,QFNG ;ONE- COMPUTE EFFECTIVE FILE NAME
587 PUSHJ P,MNGDIR ;If RENMWOing in sanctified directory
588 PUSHJ P,SYSDSK ; Tattle.
589 MOVE I,Q ;IN CASE GO TO QRNAM4
590 LDB TT,[$QAMOD,,QSRAC(E)]
591 SKIPL QSCRW(E) ;SKIP IF WRITE BLOCK (WRITE FILE) MAYBE 0 FOR WRITEOVER
592 JUMPE TT,QRNAM4 ;JUMP IF READ FILE
599 SUBTTL PAW OVER USER DIRECTORY
601 QSKDP1: ANDCAB TT,QSNLCN(H)
609 ADDI C,(TT) ;ADDR OF BEGINNING OF NAME AREA
610 MOVEI D,2000(TT) ;D => FROM POINTER
611 MOVE I,D ;I => TO POINTER
612 HRLOI E,377777 ;PREVIOUS FN1 (BIT 4.9 COMPLEMENTED)
614 MOVEI J,0 ;J NEGATIVE => NEED SORT, NON-ZERO => DIR MODIFIED
615 QSKDP4: SUBI I,LUNBLK
616 QSKDP5: SUBI D,LUNBLK
623 JRST QSKDP5 ;NAME BLOCK FREE
625 QSKDP3: MOVE Q,UNRNDM(D)
627 JRST QSKDPR ;NOT OPEN FOR WRITE OR BEING DELETED
628 HLLOS J ;NEED TO WRITE OUT DIR
633 QSKDP7: PUSHJ P,QGRLSC ;DON'T CREATE ANY FILE WITH NAME OF < OR >
634 AOJA A,QSKDPA ;CHANGE BOTH JUST TO BE SURE
636 MOVE Q,QSNLCN(H) ;SEE IF THAT NAME EXISTS
637 MOVEI Q,2000-LUNBLK(Q) ;THERE MAY BE DUPLICATE ENTRIES
638 QSKDPU: CAMN A,UNFN1(Q) ;DURING THIS SEARCH BUT IT DOESN'T
639 CAME B,UNFN2(Q) ;MATTER
641 CAIE Q,(D) ;DON'T CHANGE NAME IF NOT DUPLICATE
642 QSKDPA: AOJA B,QSKDP7 ;FOUND IT. CHANGE SECOND NAME
643 QSKDPT: SUBI Q,LUNBLK
652 HRLZ Q,D ;RELOCATE FILE BLOCK
655 QSKDP6: JUMPL J,QSKDP4 ;ALREADY NEEDS SORT
656 MOVE B,UNFN2(D) ;MAY NOT HAVE YET IF GOT HERE FASTEST WAY
662 JRST QSKDP4 ;ORDER OK
668 QSKDP8: ADDI I,LUNBLK ;I POINTED TO EMPTY SLOT
675 SETZM (D) ;CLEAR VACATED AREA
679 QSKDPV: JUMPL J,QSKDPS ;SORT
684 QSKDPK: MOVE W,QSNLCN(H)
686 HLRZ A,UDALLO(W) ;IF THIS DIR HAS ALLOCATION
688 MOVEI B,NQS-1 ;CONVERT PACK # TO DRIVE #
692 QSKBK0: SETO A, ;ALLOCATED PACK NOT MOUNTED, USE ANY
693 MOVEM A,QSALLO(H) ;SAVE DRIVE # (-1 IF NONE)
698 QSKBK1: CAIL A,2000(W) ;COUNT BLOCKS USED
703 LDB B,[UNDSCP+UNRNDM(A)]
706 ADDI B,UDDESC(W) ;B GETS BYTE PNTR TO DESC
712 JRST [ADDM C,UDBLKS(W) ? JRST QSKBK4]
714 JRST [AOS UDBLKS(W) ? JRST QSKBK4]
719 QSKBK3: ADDI A,LUNBLK
730 QSKDPS: MOVEI T,LUNBLK
732 QSKDPB: MOVEI Q,(I) ;BEGINNING OF NAME AREA
734 MOVEI Q,2000-LUNBLK(TT) ;START AT END
739 TDZA J,J ;0 => SORTED -1 => MAKE ANOTHER PASS
750 QSKDPC: SKIPN A,UNFN1(Q)
755 QSKDPD: MOVE B,UNFN2(Q)
758 SKIPE E,(P) ;FIRST ENTRY
760 QSKDPG: MOVEM A,-2(P)
765 QSKDPF: JUMPL T,QSKDPJ
772 QSKDPH: REPEAT LUNBLK,[
780 QSKDPJ: CAMGE A,-2(P)
788 SUBTTL OPEN FOR WRITE
790 ;RETURNS WITH QUSR(E) AND QSNLCN(E) ON LSWPR
791 QWRO2: JUMPE A,QPNL11
793 SKIPGE I,EPDL(U) ;PICK UP DESIRED DISK UNIT
794 JRST QWRO2A ;SYSTEMS CHOICE
797 BUG ;WE LOST SOMEHOW...
799 SKIPL QDPWF(I) ;TUT IN BUT NOT PAWED OVER
800 TLNE TT,40000 ;TUT NOT IN
801 PUSHJ P,QTCH1 ;READ IN TUT OF DISK INVOLVED
802 PUSHJ P,QCHNF ;GET CHANNEL
807 MOVEM TT,QSBYTE(E) ;UNIT ASCII MODE, BYTE SIZE=7
808 PUSHJ P,QUDLK ;LOCK USER DIRECTORY
809 PUSHJ P,QGRLSC ;CHECK < AND >
811 PUSHJ P,QFNG ;REPLACE WITH COMPUTED EFFECTIVE NAME
812 PUSHJ P,QFREEF ;FIND FREE FILE NAME AREA AND STORE IN QDIRP(E)
813 JRST QFDF ;FILE DIR FULL
814 MOVSI TT,UNWRIT ;SET WRITE IN PROGRESS
817 DPB TT,[UNPKN+UNRNDM(Q)]
818 PUSHJ P,QAUTH ;SET FILE AUTHOR, MAY NOT PCLSR
821 SETOM QSCRW(E) ;SET CHNL WRITE SWITCH
827 JRST QWRO2B ;THIS DIR GOES ON A PARTICULAR UNIT
829 SKIPGE I,QWRU ;GET CURRENT WRITING UNIT
830 JRST QWRO2E ;NO CURRENT UNIT, GO FIND ONE
833 JRST QWRO2B ;ENOUGH ROOM ON PREFERRED UNIT
834 QWRO2E: SETOB T,I ;NOT MUCH SPACE LEFT TRY OTHER UNITS
836 QWRO2C: SKIPGE QACT(E) ;SKIP ON UNIT ACTIVE
838 IFN QRSRVP,SKIPN QRESRV(E) ;DONT CHOOSE THIS PACK IF RESERVED
839 CAML T,QSFT(E) ;NOTE QSFT IS -1 IF TUT NEVER BEEN READ IN
840 JRST QWRO2D ;OTHERWISE CONTAINS VALID BLOCK COUNT
843 QWRO2D: AOBJN E,QWRO2C
845 BUG ;NO ACTIVE UNRESERVED UNITS
847 JRST QWRO2B ;DON'T WRITE MFD IF UNCHANGED
854 QWRO: JUMPN W,QWROR ;REALLY WANT TO MODIFY OR OTHERWISE HACK AN EXISTING FILE
855 PUSHJ P,QWRO2 ;MAKING NEW FILE, DECIDE WHICH UNIT TO PUT IT ON
856 SETOM QMFTP(E) ;TRACK TO SCAN IN TUT
860 MOVEI TT,%QMWRT ;ENTER NORMAL WRITE MODE
868 SUBTTL File hacking tracking
870 ; MNGDIR checks the file name (sname in C)
871 ; Fails to skip if the file is an important system file.
872 ; Skips if the file is of the everyday sort.
875 IFN KL10P, CAME C,[SIXBIT /.KLFE./]
876 CAIN TT,'SYS ;A sys directory?
878 CAME C,[SIXBIT /ACOUNT/]
881 CAME C,[SIXBIT /DEVICE/]
882 CAMN C,[SIXBIT /CHANNA/]
884 AOS (P) ;Not a system directory. skip return.
887 ; SYSDSK notifies the SYS job to print a message on the
888 ; console about the file being hacked.
889 ; File names in C;A B, the opcode in W (or zero) specifies the hacking.
891 SYSDSK: JUMPE U,CPOPJ ;Avoid deadly embrace!
892 MOVSI T,SCLWRT ;Writing on SYS directory.
893 PUSHJ P,CWAIT ;Take turns like nice little lusers.
894 TDNE T,SUPCOR ;Wait for previous req to finish.
895 MOVE TT,W ;Check file operation code.
896 CAILE TT,4 ;If impossible opcode
897 SETZ TT, ; probably supposed to be R/W.
898 MOVEM TT,SWMOD ;Store opcode.
900 MOVEM TT,SWUNAM ;Luser.
905 MOVEM C,SWFN3 ;Sname.
906 IORM T,SUPCOR ;Notify the SYS job.
907 JRST CLKONJ ;Turn on the clock and return.
910 SUBTTL DIRECTORY ROUTINES
912 QFREEF: PUSH P,A ;Q_PTR TO USER DIR FREE FILE QDIRP(E)_PTR TO FREE DESC AREA
913 PUSH P,B ;GET FREE FILE AREA
915 MOVEI I,0 ;SIGNAL NO GC YET
916 QFREFA: SETZM QUDFPR(E) ;CLEAR SO WILL NOT POINT TO RANDOMNESS IN CASE OF G C
920 BUG ;FREE DESC POINTER OUT OF RANGE
923 CAIL Q,-UDDESC-7-LUNBLK(C)
924 JRST QAGARB ;NOT ENOUGH ROOM BETWEEN DESC AND NAME AREAS
925 PUSHJ P,QLGLK ;FIND WHERE FILE OUGHT TO GO
926 JRST QFREFF ;DIR WAS EMPTY
928 JRST QFREFE ;GOES AT END OF DIR
929 QFREFC: CAMN A,UNFN1(J)
933 TLNE C,UNIGFL ;* FILES MUST COME AFTER NON * FILES
934 JRST QFREFE ;OF SAME NAME
939 JRST QFREFF ;GOES AT BEGINNING
943 QFREFF: SUBI Q,LUNBLK ;Q -> NAME BLOCK FILE WILL GO IN
944 QFREFD: MOVNI T,LUNBLK ;ALLOCATE MORE SPACE FOR NAME AREA
946 HRRZ A,UDESCP(TT) ;FIRST FREE DESCRIPTOR LOC
947 DPB A,[UNDSCP+UNRNDM(Q)];STORE IN FILE AREA
948 MOVEM A,QDIRP(E) ;STORE IN CHANNEL
949 MOVEI B,6*UFDBPW+1 ;ENOUGH FOR A LINK WITH EVERY CHAR QUOTED PLUS ONE ZERO
950 ADDM B,UDESCP(TT) ;ALLOCATE MORE SPACE FOR DESC AREA
953 HRRZM B,QUDFPR(E) ;ASSOCIATE CHANNEL WITH FILE
955 SKIPL B,QDATE ;GET TIME AND DATE
958 MOVEM B,UNDATE(Q) ;SET CREATION DATE
961 DPB B,[UNREFD+UNREF(Q)] ;SET REFERENCE DATE
962 IDIVI A,UFDBPW ;GET WRD AND CHAR ADRS
969 BUG ;DESCRIPTOR AREA ALREADY OCCUPIED
974 BUG ;NOT FOLLOWED BY ZERO
978 MOVEM A,UNFN1(Q) ;SET FILE NAMES
982 QAGARB: JUMPL I,QNOFRE ;IF GC WAS ALREADY TRIED, DON'T TRY IT AGAIN - GIVE UP.
983 PUSHJ P,QGC ;GC. BTW, IT IS OK TO PCLSR HERE.
985 MOVNI I,1 ;SIGNAL GC HAS BEEN TRIED
988 ;MAKE ROOM FOR FILE BEFORE J. Q POINTS TO NEW EMPTY FILE SLOT
1004 QINSR1: HRRZ TT,QUDPR(A)
1014 QINSR2: AOBJN A,QINSR1
1022 ;DIR NOT IN CORE. GET IT FROM DISK, CREATE IT IF DOESN'T ALREADY
1023 ; EXIST, OR GIVE NO SUCH DIRECTORY ERROR.
1024 ;C HAS SNAME. RETURNS DIRECTORY NUMBER IN H.
1027 QSKOSW ;PREVENT TIMING ERROR IF TWO PCS SHOULD
1028 PUSHJ P,QFLD ; ATTEMPT TO BRING IN SAME DIRECTORY
1030 MOVEI T,2 ;SOMEONE ELSE BROUGHT IT IN, RELEASE QSKOSW
1031 JRST LSWPON ;BUT LEAVE QSNNR(H) LOCKED.
1035 PUSHJ P,QFL ;LOOK UP DIR IN MFD, RET TRACK IN J
1036 JRST QSKON ;NON EXISTENT
1037 PUSHJ P,QFLDF ;FIND FREE LOSER DIR SLOT
1039 PUSHJ P,QCHNF ;FIND FREE CHNL (TO READ IN DIR)
1040 MOVEM C,QSNUD(H) ;SET USER NAME IN DIR SLOT
1041 MOVEM J,QSLGL(E) ;REQUEST READ IN OF USER DIR FROM TRACK IN J
1045 PUSHJ P,LSWPON ;RELEASE QSKOSW, LEAVE SOSSET OF QSNNR(H)
1046 POP P,I ;GO AWAY WILL HANG UP WAITING IN QUDLK
1047 POP P,J ;DIR IS LOCKED BUT NOT ON LSWPR, PI WILL UNLOCK AFTER READIN
1050 QNOFRE: POP P,I ;NO FREE FILES AVAIL
1053 QPNL24: PUSHJ P,OPNL24
1056 QPNL20: PUSHJ P,OPNL20
1058 PUSHJ P,OPNL47 ;FOUND LINK, BUT IT POINTS TO NON-EXISTENT DIRECTORY
1061 AUTOCR: ;AUTOMATICALLY CREATED DIRECTORIES
1062 IFN TPLP+UNSPLP,SIXBIT /.LPTR./ ;FOR TPL SPOOLING
1063 SIXBIT /.MSGS./ ;FOR MESSAGES TO ALL LOSERS
1064 SIXBIT /.MAIL./ ; Programs like to write mail here
1065 SIXBIT /CRASH/ ; Programs like to dump themselves here
1066 SIXBIT /.TEMP./ ; Programs like to write randomness here
1069 QSKON: JUMPE C,QPNL20 ;DON'T ALLOW ZERO USER NAME
1072 QSKONA: CAMN C,AUTOCR(TT)
1075 CAMN A,[SIXBIT /..NEW./]
1076 CAME B,[SIXBIT /(UDIR)/]
1079 BUG INFO,[DSK: DIR ],SIXBIT,C,[CREATED BY ],SIXBIT,UNAME(U),SIXBIT,JNAME(U)
1082 JRST QPNL24 ;NO MFD SLOTS AVAILABLE
1086 QSKONE: PUSHJ P,QFLDF ;FIND FREE DIR SLOT
1090 JRST [PUSHJ P,LSWPOP ;QMDRO
1091 PUSHJ P,LSWPOP ;QSNNR
1092 PUSHJ P,UDELAY ;HOPEFULLY MEMORY WILL APPEAR SHORTLY
1095 SOS NQFUS ;NO TIMING ERR DUE TO QSKOSW
1097 DPB J,[MUR,,MEMBLT(A)]
1098 DPB H,[MNUMB,,MEMBLT(A)]
1109 MOVE B,QACTB ;NOW PUT UFD INTO MFD
1111 MOVE TT,MDNAMP(B) ;LOOK FOR A FREE SLOT
1113 QSKONC: TRNN TT,1777
1123 QSKOND: MOVNI TT,LMNBLK ;NO FREE SLOTS, SO EXTEND DOWNWARD
1127 SUBI TT,2000-2*NUDSL ;GET DISK BLOCK NUMBER
1128 IFN KA10P, SKIPGE TT
1129 IFE KA10P, CAIGE TT,2 ; Don't clobber 'HOM' blocks
1130 BUG ;TOO MANY UFDS (NQFUS CHECK DIDN'T WORK)
1133 MOVE TT,QACTB ;UNLOCK UFD AND CAUSE IT TO GET WRITTEN
1135 PUSHJ P,QMULK ;UNLOCK MFD
1143 QALINK: MOVE I,MDSK ;ENTER WITH QSNNR ON LSWPR
1145 PUSHJ P,QWRO2 ;MAKES NEW FILE WITH MINIMUM OF 37 BYTES OF DESC SPACE
1146 MOVSI A,UNLINK ; AND ADDS QUSR AND QSNLCN ON LSWPR
1147 IORM A,UNRNDM(Q) ;SET LINK BIT
1148 MOVE A,E ;QSK CHANNEL NUMBER
1149 MOVE C,SRN5(U) ;SNAME LINKED TO
1152 MOVE C,SRN3(U) ;FN1 LINKED TO
1155 MOVE C,SRN4(U) ;FN2 LINKED TO
1158 MOVE E,A ;QSK CHANNEL NUMBER FOR QCHNRT
1159 MOVEI R,EPDL(U) ;DON'T CLOSE A REAL IOCHNM WORD
1160 PUSHJ P,QSOCL4 ;CLOSE CHNL & FILE
1161 PUSHJ P,LSWDEL ;DELETE QUSR, HAS BEEN SETOM'ED
1162 PUSHJ P,LSWDEL ;DELETE QSNRR, HAS BEEN SOS'ED
1165 LDEP: MOVEI E,6 ;STORE SIXBIT FROM C INTO LINK DESC
1166 LDEPL: MOVEI B,0 ;GET NEXT CHAR
1168 JUMPE B,LDEPS ;*THIS ALLOWS EMBEDDED BLANKS.
1174 SOS E ;NUMBER OF CHARACTERS LEFT IN WORD
1175 JUMPN C,LDEPL ;JUMP IF ANY MORE NON-BLANK CHARS TO STORE
1177 JUMPE E,POPJ1 ;JUMP IF STORED 6 CHARACTERS
1178 POPJ P, ;STORED FEWER, NEED TERMINATOR
1180 LDEPS: MOVEI D,': ;THIS CHAR NEEDS TO BE QUOTED
1184 ;LINK ENCOUNTERED DURING LOOKUP
1186 QLINK: TRNE D,%DONLK/2 ;CHECK 3.5 BIT IN OPEN MODE
1187 JRST QOLINK ;JUMP IF DON'T CHASE LINKS MODE
1190 JRST OPNL27 ;LINK DEPTH EXCEEDED
1191 PUSH P,E ;SAVE XR NEEDED BY LSWPOP OF QUSR ENTRY
1202 JUMPE J,QL3 ;END DESC
1204 JRST QL4 ;QUOTE NEXT CHAR
1206 TLZA I,770000 ;TERMINATE THIS WORD
1210 QL4: ILDB J,TT ;GET CHAR THAT WAS QUOTED
1213 QL3: EXCH A,C ;END OF DESC REACHED
1214 EXCH A,B ;MAKE A FN1 B FN2 C SNM
1217 PUSHJ P,QUDULK ;UNLOCK DIR
1218 POP P,E ;RESTORE XR USED BY LSWPOP OF QUSR ENTRY
1219 PUSHJ P,LSWPOP ;QUSR ENTRY
1220 PUSHJ P,LSWPOP ;QSNNR ENTRY
1221 PUSHJ P,OPBRK ;IF TRYING TO BE PCLSRED, SUBMIT
1224 QOLINK: MOVSI TT,%QALNK ;OPENING UP A LINK
1225 IORM TT,QSRAC(E);DON'T ALLOW FILE-ONLY OPERATIONS SUCH AS IOT
1226 JUMPL D,QWROR1 ;LEAVE RH(QSRAC)=%QMIDL SO PI LEVEL WON'T MESS WITH IT
1227 JRST QOEX1 ;AND FINISH OPENING
1231 QMCH1: CONO PI,UTCOFF
1234 AOJE TT,QMCH2 ;NOT ON WAY IN
1235 QMCH3: CONO PI,UTCON
1245 CAME TT,[SIXBIT /M.F.D./]
1246 BUG HALT,[MFD CLOBBERED]
1247 QMCH1A: MOVEI E,2000-LMNBLK*NUDSL(E)
1248 IFN KA10P, SETZM NQFUS
1250 MOVNI TT,2 ;PROTECT DEC 'HOM' BLOCKS SO KLDCP OR 8080
1251 MOVEM TT,NQFUS ; CAN FIND ITS CRUFT
1253 QMCH1E: LDB TT,[1200,,E]
1260 QMCH2: SOS QMDRO ;INDICATE ON WAY IN
1263 BUG ;DON'T WANT TO WAIT FOR CHANNEL?
1265 MOVEI TT,MFDBLK ;MFD TRACK
1274 QTCH1: CONO PI,UTCOFF
1277 JRST QTCH2 ;GO READ IT IN
1279 QTCH1A: PUSHJ P,QTLOCK ;TO MAKE SURE IT'S IN
1281 JRST QTULK ;ALREADY PAWED OVER
1289 IMULI E,DECADE ;ROUND SWAPPING ALLOC TO MULTIPLE OF A DECADE
1292 PUSH P,E ;FIRST TRACK OF NON-SWAPPING (FILE) AREA
1293 MOVE E,QTUTP(T) ;ROUND TUT POINTER TO MULTIPLE OF A DECADE
1297 CAMGE E,(P) ;KEEP IT WITHIN THE FILE AREA
1303 BUG HALT,[PACK ID ],OCT,E,[IN TUT FOR UNIT ],DEC,I,[DIFFERS FROM HARDWARE PACK ID],OCT,QPKID(I)
1305 IFE DC10P, MOVEM E,QPKID(I)
1314 CLEARM QSFTS(I) ;FREE SPACE IN SWAPPING AREA
1322 AOS QSFT(I) ;BLOCK IN NON-SWAPPING AREA
1324 AOS QSFTS(I) ;BLOCK IN SWAPPING AREA
1334 QTCH2: SETOM QDPWF(I)
1338 BUG ;DON'T WANT TO WAIT FOR CHANNEL?
1341 MOVEI TT,MFDBLK ;TELL PI LEVEL TO READ IT ALL IN
1344 LDB TT,[121000,,QTUTO(I)]
1351 ;ROUTINE TO ACCESS TUT
1352 ;CALL WITH DISK UNIT NUMBER IN I, BLOCK NUMBER IN D
1353 ;RETURNS IN D AN LDB-STYLE POINTER TO THE TUT AND IN B THE BYTE
1354 ;THAT YOU WOULD GET BY LDB'ING THAT POINTER.
1356 ;CALLER MUST LOCK TUT
1358 TUTPNT: MOVE B,QTUTO(I)
1361 BUG ;BLOCK NUMBER NOT IN RANGE COVERED BY TUT
1371 QSTRT1: CONSO DC0,DSKCHN
1372 SETOM QHUNGF ;SOMEONE PUSHED RESET BUTTON, RECOVER AT PI LEVEL
1373 CONO DC0,DCSET+DCIENB+DSKCHN ;ENABLE IDLE INTERRUPT
1375 IFN RP10P+RH10P+RH11P,[
1382 IFN RP10P+RH10P+RH11P,[ ;START DISK WITH UTC ALREADY OFF
1383 QSTRT1: SETOM QGTBZY ;NOTE: TURNS UTC BACK ON BUT NOT CLOCK
1384 IFN RP10P, CONSO DPC,20 ;ONLY IF DISK IDLE
1385 IFN RH10P, CONSO DSK,%HIBSY
1386 IFN RH11P, IORDQ TT,%HRCS1
1387 IFN RH11P, TRNE TT,%HXRDY
1392 ;TRY TO FLUSH UNNEEDED UFDS FROM CORE.
1393 ;ARG IN C IS ROUTINE TO FREE THE MEMORY.
1394 ;CALL WITH UDRSW SIEZED, OR WITH PI 2 IN PROGRESS AND UDRSW NOT LOCKED BY ANYONE
1395 ;CLOBBERS H, TT. DOESN'T SKIP.
1396 QDFLS: MOVSI H,-QNUD
1397 QDFLS1: SKIPE QSNUD(H)
1399 QDFLS2: AOBJN H,QDFLS1 ;CAN'T FLUSH IF SLOT NOT USED OR CHANNELS OPEN IN DIR
1404 JRST QDFLS2 ;CAN'T FLUSH IF LOCKED OR NOT WRITTEN OUT
1405 PUSHJ P,QDFCHK ;CHECK THAT NO POINTERS TO THIS DIRECTORY REMAIN
1406 CLEARM QSNUD(H) ;FLUSH
1411 PUSHJ P,(C) ;RETURN THE MEMORY
1413 JRST QDFLS2 ;TRY FLUSHING SOME MORE
1415 ;CALL WITH UFD SLOT# IN H, WHEN YOU THINK THAT UFD IS FREE.
1419 QDFCH1: SKIPGE QUSR(C)
1424 BUG ;IT WASN'T REALLY FREE, MAYBE QSNNR IS SCREWED UP?
1430 ;FIND A FREE UFD SLOT, RETURN INDEX IN H. PUTS QSNNR ON LSWPR.
1438 PUSH P,C ;ALL UFD SLOTS IN USE, TRY FLUSHING SOME
1445 PUSHJ P,LSWPOP ;UDRSW
1446 PUSHJ P,UDELAY ;WAIT 1/2 SECOND THEN TRY AGAIN, INCLUDING QDFLS
1449 QFLDF1: SKIPN QSNNR(H) ;SLOT ALREADY GOBBLED
1450 SKIPE QSNUD(H) ;OR ALREADY OCCUPIED
1451 AOBJN H,QFLDF1 ;MEANS CAN'T TAKE IT
1453 BUG ;NONE FREE, QFUD OUT OF PHASE WITH REALITY
1456 MOVSI TT,600000 ;DOUBLE LOCK
1460 PUSHJ P,LSWPOP ;UDRSW
1466 QFLDRT: SKIPL A,AC0S+H(U)
1471 JUMPG T,CPOPJ ;HOW DID SOMEONE ELSE GET IT?
1473 AOS QFUD ;READ-IN NEVER STARTED, SLOT BECOMES FREE
1474 POPJ P, ;OK TO LEAVE 600000,, SET IN QSNLCN
1477 ;IF IN CORE, SET H TO UFD SLOT#, AOS QSNNR, PUT ON LSWPR, AND SKIP.
1478 ;IF DIRECTORY NOT IN CORE, NO SKIP. CLOBBERS T,TT.
1481 QFLD1A: MOVSI H,-QNUD
1482 QFLD1: CAME C,QSNUD(H)
1484 JUMPGE H,LSWPOP ;JUMP ON FAILED TO FIND USER.
1485 QFLD2A: AOSG QSNNR(H)
1486 BUG ;MUST HAVE GOTTEN NEGATIVE SOMEHOW
1487 PUSHJ P,LSWPOP ;UDRSW
1490 ;THIS IS AN ATTEMPT TO FIND A BUG.
1502 ;C <=SYS NAME, RETURNS TRACK ADDR OF DIR IN J, SKIPS IF FINDS LOSER
1511 ADD Q,MDNAMP(Q) ;PTR TO USER AREA
1512 QFL1: LDB J,[1200,,Q]
1519 QFL2: SUBI J,2000-LMNBLK*NUDSL ;J <= TRACK ADDR OF USER DIR
1525 ;ROUTINE TO ASSIGN A DISK CHANNEL.
1526 ;ARGS: U USER TO GO IN QUSR, H UFD SLOT# TO GO IN QUDPR, I DSK# TO GO IN QDSKN
1527 ;RETURNS QSK CHNL INDX IN E.
1528 ;DOESN'T DO A LOSSET OF QCHNRT, BUT CALLER MAY WANT TO.
1529 ;CLOBBERS T. NEVER SKIPS.
1531 QCHNF: PUSHJ P,SWTL ;PREVENT ANYONE ELSE FROM ALLOCATING CHANNELS
1535 JRST QCH2 ;SOME CHANNELS ARE AVAILABLE, GO FIND ONE
1536 PUSHJ P,LSWPOP ;QCHSW
1541 QCH2: SKIPGE QSRAC(E) .SEE %QALOK
1546 BUG ;WHERE DID THAT FREE CHANNEL GO?
1548 QCH1: HRRZS E ;CHANNEL ALLOCATED, INITIALIZE VARIABLES
1552 SETOM QSLGL(E) ;IN CASE OF WRITE-OVER ON 0-LENGTH FILE.
1559 SETZM QSRAC(E) .SEE %QMIDL
1563 MOVE T,[444400,,1] ;ASSUME BYTES=WORDS, WILL BE FIXED LATER
1567 SETZM QUDFPR(E) ;NOT YET SET UP TO ANY PARTICULAR FILE
1568 MOVEM U,QUSR(E) ;CHANNEL IS NOW IN-USE
1573 ;LOSSET ROUTINE TO RETURN TENTATIVELY ASSIGNED QSK CHNL
1574 ;E HAD BETTER CONTAIN THE QSK CHANNEL NUMBER AT "ALL" TIMES
1575 QCHNRT: SKIPL T,AC0S+E(U)
1578 HRRZ A,U ;LSWPOP MESSES WITH LH(U)
1585 SUBTTL DELETE, RENAME
1586 ;COME HERE FOR DELETE, OR RENAME NOT WHILE OPEN, ON DISK.
1588 QRNAM: SKIPN SRN3(U)
1608 JRST QROR1C ] ;GIVE FILE NOT FOUND OR FILE LOCKED
1613 JRST QPNLBN ;FILE ALREADY EXISTS
1615 QRNAM4: PUSHJ P,QLOOK
1617 CAME I,Q ;ALLOW RENAME THAT DOESN'T CHANGE NAMES.
1620 MOVSI TT,UNDUMP ;SAY FILE NOT DUMPED.
1622 MOVNI E,1 ;TELL QFREF NOT TO CLOBBER NON-EX DISK CHNL.
1623 PUSHJ P,QFREF ;"REFERENCE" FILE
1624 PUSHJ P,QRELOC ;STORE NEW NAMES IN DIR
1625 QRNAM2: MOVE TT,QACTB
1627 QRNAM1: MOVE U,USER ;U MAY NOT HAVE USER IF CAME HERE FROM LOGOUT
1631 QGRLSC: CAME A,[SIXBIT />/] ;SKIP NONE IF BOTH A+B ARE SPECIAL
1632 CAMN A,[SIXBIT /</] ;ONCE IF ONE IS
1634 CAME B,[SIXBIT />/] ;AND TWICE IF NEITHER
1641 ;MOVE FILE POINTED TO BY Q SO THAT NEW NAMES A AND B WILL BE IN
1650 PUSHJ P,QLGLK ;SEE WHERE FILE MUST GO
1653 QRLOCK: CAIL J,2000(TT)
1664 QRLOCJ: HRRZ Q,-3(P) ;WHERE FILE IS NOW
1667 JRST QRLOCS ;SAME PLACE
1668 REPEAT LUNBLK, PUSH P,.RPCNT(Q)
1672 QRLOCC: SUBI TT,LUNBLK
1675 BLT D,2*LUNBLK-1(TT)
1679 REPEAT LUNBLK, POP P,LUNBLK-.RPCNT-1(J)
1690 QRLOCE: MOVSI TT,-NQCHN
1691 QRLOCF: HRRZ E,QUDPR(TT)
1703 QRLOCG: AOBJN TT,QRLOCF
1719 QRLOCD: MOVNI D,LUNBLK
1724 QRLOCI: HRRZM J,QUDFPR(TT)
1727 QRLOCS: MOVEM A,UNFN1(Q)
1737 LDB J,[UNPKN+UNRNDM(Q)]
1738 QDELTA: MOVSI I,-NQS
1741 JUMPGE I,QPKNF6 ;PACK OF FILE NOT MOUNTED
1742 QDEL5: PUSHJ P,QUDULK
1744 JRST QDFNF ;GONE AWAY BETWEEN LOCKS
1747 QDEL5A: ;DELETE LINK
1748 MOVE I,MDSK ;RANDOM EXISTANT UNIT
1751 QPKNF6: PUSHJ P,QUDULK
1752 PUSHJ P,QPKNFP ;MAYBE JUST TUT NOT IN YET?
1753 JRST QDEL ;YUP, GOT IT NOW, TRY AGAIN
1754 PUSHJ P,QUDLK ;NO, FILE IS ON NOT-MOUNTED PACK
1755 PUSHJ P,QLOOK ;SO GET IT AGAIN
1756 JRST QDFNF ;GONE AWAY BETWEEN LOCKS, LOSE
1757 ;AND DELETE IT WITHOUT HACKING TUT
1758 QDFPK: LDB A,[UNDSCP+UNRNDM(Q)] ;POINTER TO DESCRIPTION AREA
1759 PUSHJ P,QSQSH ;REMOVE ENTRY
1772 QNFDL3: REPEAT NXLBYT,[IDPB C,A
1777 QAUTH: PUSH P,B ;STORE UFD INDEX OF FILE'S CREATOR
1778 PUSH P,C ;THIS IS NOT ALLOWED TO PCLSR. WE SEARCH THE MFD
1779 PUSH P,J ;WITHOUT LOCKING IT WHICH SHOULD BE ALL RIGHT SINCE
1780 PUSH P,I ;UFD'S DON'T MOVE AROUND AND THE MFD IS WIRED IN 1 PLACE IN CORE.
1784 JRST QAUTH1 ;UNAME = SNAME
1786 SKIPA ;NOT FOUND IN MFD
1789 MOVEI J,5 ;STRIP OFF ANY NUMERICS
1790 MOVE TT,[440600,,UNAME(U)]
1800 SKIPA ;NO NON-LETTERS
1802 QAUTH3: PUSHJ P,QFL0
1803 SKIPA C,HSNAME(U) ;CAN'T CONVERT UNAME IN ANY FORM, TRY HSNAME AS LAST RESORT
1806 SETOM J ;CAN'T ENCODE AUTHOR AT ALL
1807 QAUTH1: DPB J,[UNAUTH+UNREF(Q)]
1816 ;Q=0 => LOOK UP FILE TO DELETE
1817 ;Q .NE. 0 => DELETE FILE POINTED TO BY QUDFPR OF CHNL IN D
1818 ;H MUST HAVE DIR SLOT INDEX
1820 QDLA1: PUSHJ P,SLUGH
1827 SETO D, ;NO ASSOCIATED CHANNEL
1828 QDLA3: LDB A,[UNLNKB+UNRNDM(Q)]
1829 LDB TT,[UNPKN+UNRNDM(Q)]
1831 JUMPE A,QDELA1 ;ON DIFFERENT DISK (DIDN'T LOCK RIGHT TUT TRY AGAIN)
1836 JRST QDEL2 ;IGNORE CHANNEL (IF ANY) WHOSE CLOSING CAUSED THIS
1838 SKIPL QSCRW(J) ;ONLY LOOK AT READ CHNLS
1845 MOVSI TT,%QADEL ;FOUND CHNL WITH THIS FILE OPEN
1846 IORM TT,QSRAC(J) ;DELETE FILE WHEN THIS CHNL CLOSED
1847 MOVSI TT,UNCDEL ;SET DELETED BIT
1849 QDEL4: MOVE TT,QACTB
1853 QDEL4B: PUSHJ P,QTULK
1858 QDLA2: MOVE Q,QUDFPR(D) ;COMPUTE FILE ADR FROM CHNL IN D
1859 ADD Q,QSNLCN(H) ;DIR MAY HAVE MOVED
1865 QCDLWO: PUSH P,R ;OUTPUT CLOSE BUT FILE WAS DELEWO'ED
1866 SETZM QSCRW(D) ;FAKE OUT ERROR CHECK AT QSQSH6
1868 QSICLD: MOVE H,QUDPR(D) ;ENTRY FROM INPUT CLOSE, FILE WAS DELETED
1877 BUG ;FILE ISNT THERE?
1879 MOVE H,QUDPR(D) ;DIRECTORY NUMBER
1880 SETOM QUSR(D) ;FREE THE DISK CHANNEL
1884 QDELA1: PUSHJ P,QDEL4B ;NOT OUR DISK IN J
1886 MOVE J,TT ;DISK ITS REALLY ON
1887 QDELA2: MOVSI I,-NQS ;TRANSLATE PACK # IN J TO DRIVE # IN I
1893 QSOCLD: PUSH P,D ;DELETE FILE WHEN CLOSING OVER IT
1895 LDB J,[UNPKN+UNRNDM(Q)]
1903 QPKNF1: PUSHJ P,QPKNFP ;MAYBE TUT NOT IN YET?
1904 JRST QDELA2 ;YUP, TRY AGAIN
1907 JRST QUDULK ;GONE AWAY BETWEEN LOCKS
1908 JRST QDFPK ;GO DELETE OFF OF NON-MOUNTED PACK
1910 QDL2: PUSHJ P,QTULK ;DELETE LINK
1912 PUSHJ P,LSWPON ;UNLOCK QCHSW
1913 QDLINK: LDB E,[UNDSCP+UNRNDM(Q)]
1922 QDL1: DPB B,E ;CLEAR OUT THE CHAR
1924 IDPB B,E ;CLEAR A QUOTED CHAR WITHOUT LOOKING AT IT
1927 PUSHJ P,QSQSH ;REMOVE ENTRY
1933 QDEL2: AOBJN J,QDEL1 ;CHECK NEXT DISK CHANNEL
1934 MOVE C,UNRNDM(Q) ;NOT OPEN, SO REALLY DELETE IT
1941 HLL C,QBTBLI(D) ;GET DESCRIPTOR POINTER IN C AND TT
1944 PUSHJ P,NFLLN1 ;A GETS NUMBER OF BLOCKS IN FILE
1946 SKIPN D,QSFBT(H) ;SEE IF ENOUGH QSFBT STORAGE EXISTS
1948 QDEL10: HLRE B,(D) ;NUMBER OF FREE LOCATIONS IN THIS PAGE
1949 ADD A,B ;DECREASE LOCATIONS NEEDED
1952 QDEL11: JUMPLE A,QDEL12 ;JUMP IF SUFFICIENT STORAGE EXISTS
1953 PUSHJ P,TCALL ;GET MORE
1955 JRST [ MOVE U,USER ;U MAY NOT HAVE USER IF CAME FROM LOGOUT
1956 PUSHJ P,LSWCLR ;HAVE TO WAIT FOR MEMORY
1957 PUSHJ P,MQTEST ;AVOID DEADLOCKS BY UNLOCKING EVERYTHING
1961 DPB D,[MUR,,MEMBLT(A)]
1967 EXCH A,QSFBT(H) ;ADD TO FRONT OF LIST
1969 MOVE A,(P) ;GET BACK NUMBER OF BLOCKS NEEDED
1970 JRST QDEL10 ;SEE IF THERE ARE ENOUGH NOW
1972 QDEL12: POP P,A ;GET RID OF BLOCKS COUNT
1973 PUSHJ P,QSQSH ;REMOVE ENTRY, CANNOT PCLSR AFTER THIS
1974 CLEARB J,D ;J GETS NUMERIC TRACK NUMBER, D BYTE POINTER TO TUT
1975 MOVE TT,QTUTO(I) ;D ZERO SO WILL HALT IF DESC DOESN'T START WITH LOAD-ADDR!
1976 MOVE Q,QSFBT(H) ;Q -> AOBJN POINTER FOR STORING BLOCK NUMBERS
1977 QDEL3: ILDB B,C ; INTO QSFBT AS DESCRIPTORS ARE ZEROED OUT
1978 MOVEI A,0 ;I DISK, C BP TO DESCRIPTOR, A,B,E TEMP.
1980 JUMPE B,QDEL4 ;END OF FILE DESCRIPTION
1986 BUG ;OOPS, OUT OF QSFBT STORAGE
1987 SKIPL E,(Q) ;PICK UP AOBJN POINTER
1988 JRST [ MOVE Q,1(Q) ;THIS PAGE FULL, TRY NEXT
1990 MOVEM J,(E) ;STORE DISK,,BLOCK FOR LATER FREEING
1992 MOVEM E,(Q) ;INCREMENT POINTER
1993 MOVE E,QSNLCN(H) ;DECREASE DIR'S BLOCKS-USED
1999 BUG ;TUT SHOWS TRACK NOT USED
2000 AOS J ;DO NEXT BLOCK IN CONTIGUOUS GROUP
2004 IFN NXLBYT-2, .ERR THIS ROUTINE AND OTHERS KNOW IMPLICITLY THAT NXLBYT=2
2005 QDEL6: MOVEI D,0 ;LOAD ADDRESS
2009 DPB A,C ;A HAS ZERO FROM QDEL3
2016 ADD D,[TUTBYT_14,,] ;MAKE INTO ILDB-TYPE POINTER
2025 QDEL7A: MOVEI B,1 ;LOAD ADDRESS OR SKIP AND TAKE, SO ONLY ONE TRACK
2028 QDFNF: PUSHJ P,OPNL4
2031 QDELB: CONO PI,UTCON
2034 ;PERFORM BLOCK-FREEING SPECIFIED BY QFBTS
2035 QDLFBT: CONO PI,UTCOFF ;PROTECT QFBTS
2041 HRRZ T,(B) ;FIRST FREE LOCATION
2042 SUBI T,2(B) ;NUMBER OF LOCATIONS TO DO
2045 AOBJP A,QDLFB9 ;A NOW -> BLOCKS TO FREE, & CHECK FOR EMPTY
2046 SETO I, ;NO TUT LOCKED YET
2047 QDLFB1: HLRZ J,(A) ;DISK NUMBER
2048 CAMN J,I ;MAKE SURE RIGHT TUT IS LOCKED
2054 QDLFB2: HRRZ D,(A) ;BLOCK NUMBER TO FREE
2056 CAIGE B,TUTMNY ;USED IN "MANY" FILES(1,2,...,TUTMNY,TUTLK)
2057 SOJL B,[JRST 4,.] ;HALT IF TUT SHOWS TRACK NOT USED
2058 JUMPN B,QDLFB3 ;NOT LAST USE
2059 HRRZ T,(A) ;BLOCK NUMBER AGAIN
2063 AOS QSFTS(I) ;TRACK IN SWAPPING AREA
2064 QDLFB3: DPB B,D ;DECREASE USAGE COUNT IN TUT
2067 QDLFB9: MOVEI A,-1(A) ;GET AN ADDRESS ON THAT PAGE
2068 LSH A,-10. ;DONE WITH THIS PAGE, FREE IT
2069 PUSHJ P,TMEMR ;RETURN PAGE TO FREE AND TRY FOR MORE
2073 ;REMOVE HOLE FROM NAME AREA AT Q
2089 QSQSH1: SUBI C,LUNBLK
2098 REPEAT LUNBLK,SETZM .RPCNT(A)
2102 SUBI C,(TT) ;INDEX OF DELETED FILE
2103 HRRZI TT,-LUNBLK(A) ;INDEX OF OLD BEGINNING OF NAME AREA
2105 QSQSH3: HRRZ B,QUDPR(A)
2114 JRST QSQSH6 ;PNTR TO FLUSHED HOLE, CHECK IF READ CHNL
2115 CAIG B,(C) ;IF AFTER DELETED FILE DON'T RELOCATE
2119 JRST QSQSH4 ;READ CHNL
2123 BUG ;CHNL WRITING BUT BEING WRITTEN BIT NOT SET
2124 QSQSH4: AOBJN A,QSQSH3
2131 QSQSH6: MOVE B,QSRAC(A) ;FOUND PNTR TO DELETED FILE
2132 TLNE B,%QADEL ;SKIP IF NOT DELETE AFTER CLOSE
2133 SKIPGE QSCRW(A) ;ALSO ERROR IF NOT READ CHNL
2135 JRST QSQSH4 ;WAS DELETE AFTER CLOSE ON READ CHNL
2137 SUBTTL DIRECTORY LOOK UP, > FEATURE
2139 ;A contains the FN1 and B contains the FN2.
2140 ;H is the index of the directory slot. The dir must be locked.
2142 ;Returns the address of the filename block in Q.
2145 ;Internally, J and Q point to the bottom and top of the
2146 ;area of the dir we are still searching.
2147 ;Bit 4.9 of J is set to indicate one of the names is ">".
2148 ;C used as a flag: sign bit says creating a file.
2149 ;Bit 1.1 of C says FN2 is > or <.
2151 ;Look for place to create new file,
2152 ;and generate new version for >.
2153 QFNG: MOVEM Q,EPDL3(U)
2155 ;Look for existing files only
2159 MOVEI Q,2000-LUNBLK(J)
2164 JRST QLOOKA ;4.9 BIT OF J SET IF >
2172 JRST POPJJ ;J IS OFF THE END OF THE BLOCK
2175 QLK1: CAMN A,UNFN1(Q)
2179 TLNN C,UNIGFL ;BEING WRITTEN OR DELETED
2181 SUBI Q,LUNBLK ;SEARCH THROUGH * FILES
2193 ;REFERENCE FILE POINTED TO BY Q
2194 QFREF: LDB C,[UNREFD+UNREF(Q)]
2195 CAME E,[-1] ;IF A DISK CHNL IN USE,
2196 HRLM C,OLDRDT(E) ;SAVE OLD REF DATE IN DSK CHNL VAR
2197 SKIPGE T,QDATE ; If date unknown
2198 POPJ P, ; don't clobber
2199 HLRZ T,T ; Just get date part
2200 CAMN C,T ; If same as old date
2201 POPJ P, ; no need to do anything
2202 DPB T,[UNREFD+UNREF(Q)]
2203 MOVE T,MDSK ;MAKE MDSK WRITE OUT
2208 QLOOKA: CAME B,[SIXBIT /</]
2210 JRST POPJJ ;MUST BE READ RETN FILE NOT FOUND
2211 QLOOK1: JUMPGE C,QLOOK9
2213 TLO J,400000 ;IF WRITING, TURN "<" INTO ">"
2217 PUSH P,[-1] ;BEST INDEX
2218 PUSH P,[SETZ] ;BEST "NUMERIC" PART
2219 PUSH P,[SETZ] ;BEST ALPHA PART
2226 JUMPGE C,[ SKIPGE -2(P) ;FILE LOCKED, REMEMBER IT IF WE HAVE NO BETTER,
2227 HRRM Q,-2(P) ; BUT DON'T CONSIDER IT IF READING
2228 JRST QLOOK3 ] ;BUT IF WRITING, CONSIDER ALL FILES
2229 SKIPE TT,@QLKI1+1(C)
2230 QLOOK6: TRNE TT,77 ;RIGHT ADJ
2236 QLOOK8: LDB D,[600,,TT]
2239 JRST QLOOK7 ;NOT A DIGIT
2240 QLOK5B: TRNE I,77 ;RIGHT ADJ LOW NON NUM PART
2244 QLOK5A: TLC TT,400000 ;AVOID CAM LOSSAGE
2247 JRST QLOK5D ;FIRST MATCH
2248 JUMPGE J,QLOK5E ;GET LEAST
2249 CAMGE TT,-1(P) ;GET GREATEST
2254 JRST QLOOK3 ;NOT AS GOOD
2255 QLOK5D: HRRZM Q,-2(P)
2258 QLOOK3: SUBI Q,LUNBLK
2261 QLOK5E: CAMLE TT,-1(P)
2269 QLOOK7: LSHC TT,-6 ;LOW DIGIT NOT NUMERIC
2270 JUMPN TT,QLOOK8 ;NO NUMERIC DIGITS AT ALL ("BIN", MAYBE?)
2271 JUMPL J,QLOK5B ;IF LOOKING FOR GREATEST, LET THIS BE LEAST
2272 MOVNI TT,1 ;GREATEST IF LOOKING FOR LEAST
2275 QLOOK2: JUMPL C,QFNG1 ;REALLY WANT TO MAKE F.N.'S FOR WRITE
2277 POP P,C ;BEST "NUMERIC" PART
2283 MOVE A,UNFN1-1(Q) ;ACTUAL MATCHED FILE NAMES
2285 SOJGE Q,POPJJ1 ;FOUND A FILE THAT WASN'T LOCKED
2290 JRST QFNG2 ;NOT FOUND START W/ 1
2297 JRST QFNG4 ;REACH END OF NUMERIC FIELD
2302 QFNG5A: TLNE TT,770000
2307 QFNG2: MOVSI TT,(SIXBIT /1/)
2308 QFNG3A: MOVEM TT,A(C) ;STORE INTO A OR B AS APPRO
2322 QFNG4: TLNN TT,770000 ;SKIP ON ALREADY 6 CHAR NAME
2327 QFNG4B: TLNN I,770000
2332 QLKI1: CAME B,UNFN2(Q)
2336 QPKNF: MOVE C,QSNUD(H)
2337 PUSHJ P,QUDULK ;UNLOCK DIR
2338 PUSHJ P,LSWPOP ;QUSR ENTRY
2339 PUSHJ P,LSWPOP ;QSNNR ENTRY
2342 PUSHJ P,OPNL16 ;PACK NOT MOUNTED
2345 QPKNFP: MOVSI I,-NQS
2346 QPKNF3: SKIPGE QACT(I)
2351 JRST QPKNF2 ;PACK NOT IN OR NOT PAWED OVER
2352 QPKNF4: AOBJN I,QPKNF3
2355 QPKNF2: JRST QTCH1 ;MAYBE THIS UNIT HAS GOODIES
2357 QFDF: PUSHJ P,OPNL5 ;FILE DIR FULL ON WRITE
2360 QPNL13: PUSHJ P,OPNL13
2363 QPNL22: PUSHJ P,OPNL22
2367 QPNL11: PUSHJ P,OPNL11
2370 ;ROUTINE TO FIND PLACE IN DIRECTORY WHERE A B WOULD GO
2371 ;SKIPS ONLY IF DIRECTORY CONTAINS AT LEAST ONE FILE
2372 ;FOR INSERTION, FILE GOES BEFORE PNTR RETURNED IN J
2373 ;RETURNS PNTR IN Q TO BEGINNING OF NAME AREA
2374 ;(ONLY WORKS FOR LUNBLK = 5)
2375 QLGLK: HRRZ J,QSNLCN(H)
2379 POPJ P, ;DIRECTORY EMPTY
2384 ADDI J,600 ;128. NAME BLOCKS FROM END
2385 REPEAT 7,[ ;THIS CODE DELIBERATELY NOT INDENTED. NEED 4 DIMENSIONS.
2393 ADDI J,<1_<7-.RPCNT>>*LUNBLK
2394 SUBI J,<1_<6-.RPCNT>>*LUNBLK
2407 QLGL2: ADDI J,LUNBLK
2418 ;CALL BY JSP E,QLGLE
2419 QLGLE: MOVE D,UNFN2(J)
2427 SUBTTL LOCKING ROUTINES
2429 QMLOCK: PUSHJ P,LSWTL
2442 QTLOCK: PUSHJ P,LSWTL
2455 QUDLK: PUSHJ P,LSWTL
2469 QBTBLI: 440600,, ;IF GOING TO ILDB
2479 TBTBLI: REPEAT 1+TUTEPW, TUTBP-<.RPCNT*TUTBYT*010000,,>
2481 SUBTTL DIRECTORY GARBAGE COLLECTOR
2483 ; MOVE H, directory number
2484 ; lock the directory
2486 ; return if directory full.
2489 ; All pointers to directory relocated appropriately.
2491 ; Called from disk open routines if a new file is to be created
2492 ; and there are less than 6+LUNBLK words in the free area of the directory.
2493 ; Called from QSBWG if %QAFUL is set in QSRAC.
2494 ; %QAFUL means "must have successful GC before committing another track to this file."
2497 ; This GC allocates an extra block of core for temporary storage.
2498 ; If no memory is free in low half, waits without unlocking directory.
2499 ; Can possibly PCLSR. No deadly embrace to not unlock directory since
2500 ; it can't be flushed from core anyway and it's not holding anything else in.
2502 QAPBMN==NXLBYT+3 ;minimum number of descriptor bytes which
2503 ; must be available at the end of a file to
2504 ; commit another track to the file.
2505 ;1 for a take-N, NXLBYT+1 for jump, 1 for ending zero.
2506 QAPBMX==36. ;maximum number of descriptor bytes to allocate at a time.
2508 QGC: IRPC X,,ABCDQIJTR
2512 ;Old GC prints message on system console. Any reason to with fast one?
2514 ; validate the directory
2516 QGC00: SKIPL A,QSNLCN(H)
2517 BUG ;directory not locked
2519 MOVEM C,LASTGC ;save name of last dir GCed
2521 BUG ;directory clobbered
2524 BUG ;name pointer out of bounds
2527 CAIL D,-UDDESC*UFDBPW(C)
2528 BUG ;descriptor/name overlap
2530 ; Get a block of core to use for temporary storage.
2531 ; The block is left in the "in-process" state.
2536 JRST [ PUSHJ P,UDELAY ;no core available in low half
2537 JRST QGC00 ] ;so wait, then loop back to beginning
2539 MOVEI B,1(A) ;zero it out
2543 EXCH Q,A ;A -> directory, Q -> temporary core
2546 ; Scan the directory and count:
2548 ; J files open for writing
2549 ; R active bytes of descriptor
2553 MOVEI B,2000(A) ;end of name area
2554 ADD A,UDNAMP(A) ;start of name area
2556 JRST QGC19 ;jump if all files done
2559 BUG ;zero name block?
2560 AOJA I,QGC12 ;file exists
2562 QGC11: ADDI A,LUNBLK ;advance to next file
2563 AOJA R,QGC10 ;also count the zero byte that ends the descriptor
2565 QGC12: MOVE C,UNRNDM(A)
2568 ANDI C,.BM UNDSCP ;get descriptor ptr (undscp has pos=0)
2571 ADDI C,UDDESC-2000(B)
2575 QGC13: ILDB T,C ;get byte of descrip
2578 AOJA R,QGC13 ;1-byte desc
2579 REPEAT NXLBYT, IBP C ;multi-byte desc
2583 QGC14: ILDB T,C ;count bytes of link descriptor
2586 AOJA R,[IBP C ;quoted
2591 ; Compute number of bytes of descriptor to add after each
2592 ; file open for output. If > QAPBMX, set to QAPBMX.
2593 ; If < QAPBMN, take directory-full exit.
2595 QGC19: MOVE C,I ;save number of files
2596 IMULI I,LUNBLK*UFDBPW ;number of bytes in name area
2597 ADDI R,UDDESC*UFDBPW(I) ;R := total number of bytes claimed
2598 MOVEI A,2000*UFDBPW-1
2599 SUB A,R ;A := number of bytes left
2601 IDIV A,J ;number of bytes available to extend open files
2603 JRST QGC69 ;if < minimum, dir. full
2605 MOVEI A,QAPBMX ;limit to at most QAPBMX bytes at a time
2608 ; A = number of bytes of room to leave after each file open for writing
2609 ; B -> name block under consideration
2610 ; C -> old descriptors
2611 ; D = disk channel number under consideration. Also D = C+1
2612 ; J counts new descriptor bytes generated
2613 ; Q -> new descriptors (in temporary core block)
2614 ; R -> base of directory
2617 HRRZ R,QSNLCN(H) ;old dir
2618 ADDI Q,UDDESC ;new dir
2625 QGC20: CAIL B,2000(R)
2626 JRST QGC40 ;all files done
2627 LDB C,[UNDSCP UNRNDM(B)] ;get old desc ptr
2628 DPB J,[UNDSCP UNRNDM(B)] ;store new desc ptr
2630 ; Loop over all disk channels, relocating the ones that point to this file
2633 QGC31: HRRZ T,QUDPR(D)
2636 AOBJN D,QGC31 ;not in use or not same directory
2637 JUMPGE D,QGC39 ;jump if all disk channels done
2640 JRST QGC32 ;not same file
2641 MOVE T,J ;relocate descriptor pointer
2644 QGC32: AOBJN D,QGC31
2646 QGC39: IDIVI C,UFDBPW ;make desc pntr into byte pointer
2652 QGC21: ILDB T,C ;copy descriptor bytes of a file into temporary core
2663 QGC22: ILDB T,C ;copy descriptor bytes of a link into temporary core
2672 QGC23: MOVE T,UNRNDM(B)
2675 ADD J,A ;file being written, increase desc area
2680 QGC25: ADDI B,LUNBLK ;next file
2681 AOJA J,QGC20 ;also account for final zero at end of descriptor
2683 ; Paranoia: check that all disk channels to this directory look OK
2685 QGC40: MOVEM J,UDESCP(R) ;store free-desc pointer
2686 LDB A,[1200,,Q] ;last word used by descriptors
2689 ANDI Q,-2000 ;base of temp core block again
2691 QGC41: HRRZ T,QUDPR(A)
2694 AOBJN A,QGC41 ;channel not in use, or to some other dir
2695 JUMPGE A,QGC49 ;all channels done
2696 SKIPN B,QUDFPR(A) ;get file open on this channel
2697 JRST QGC42 ;channel not set up to any particular file
2700 BUG ;file pointer screwed
2702 SKIPL J,QDIRP(A) ;get descriptor pointer
2704 BUG ;descriptor pointer screwed
2705 LDB C,[UNDSCP UNRNDM(B)]
2706 CAIGE B,2000-LUNBLK(R) ;skip if last file in dir
2707 LDB D,[UNDSCP UNRNDM+LUNBLK(B)] ;else get desc pntr for next file
2708 CAIL B,2000-LUNBLK(R)
2709 MOVEI D,2000*UFDBPW ;but if last file, get infinity
2710 CAML J,C ;verify that QDIRP points to this file
2713 QGC42: AOBJN A,QGC41 ;do next channel
2715 ; If you thought that was paranoid, get a load of this:
2717 QGC49: MOVE B,UDNAMP(R)
2719 QGC50: CAIL B,2000(R)
2721 LDB C,[UNDSCP UNRNDM(B)]
2723 IDIVI C,UFDBPW ;NOTE if UNDSCP = 0 we depend on bytes
2724 HLL C,QBTBL(D) ; off left end of word LDB'ing as zero
2728 BUG ;descriptor not preceeded by zero
2730 TRZ J,#.BM UNDSCP ;LH(J) flags, RH(J) just desc pntr
2737 REPEAT NXLBYT, IBP C
2749 QGC53: TLNE J,UNWRIT ;RH(J) has desc pntr to the zero that ends the file
2750 ADDI J,QAPBMN ;if being written, needs room for one more track
2751 CAIL B,2000-LUNBLK(R) ;now set D to point to next descriptor area
2752 SKIPA D,UDESCP(R) ;do this instr if last file in dir
2753 LDB D,[UNDSCP UNRNDM+LUNBLK(B)] ;else get next file's desc pntr
2755 BUG ;descriptors overlap
2759 ; Copy the descriptors back into the directory
2761 QGC60: MOVSI C,UDDESC(Q) ;make BLT pointer to copy it back
2763 MOVE B,UDNAMP(R) ;use same BLT to zero out the free area
2770 QGC69: LDB A,[121000,,Q] ;core block number of temporary page
2771 PUSHJ P,TMEMR ;return it
2772 MUINP ;verifying that it is the right one.
2778 SUBTTL INTERPRET DESCRIPTORS
2780 QFNTR: MOVE H,QUDPR(A) ;BYTE # IN Q CHNL # IN A
2781 PUSHJ P,QUDLK ;DONT SKIP IF OFF FILE
2782 MOVE T,QSNLCN(H) ;RETN BLOCK IN QSLGL(A) AND QSBI(A) DIR PNTR IN QDIRP(A)
2783 ADD T,QUDFPR(A) ;FIRST ADR OF BLOCK IN QFBLNO(A)
2784 LDB TT,[UNDSCP+UNRNDM(T)] ;CHAR ADR OF FILE BEG
2785 MOVEM TT,QDIRP(A) ;SKIPS IF FINDS BLOCK AND LEAVES USER DIR LOCKED
2788 CLEARB J,QSLGL(A) ;J HAS ORG OF FIRST NON-EX-BLOCK IF OFF END OF FILE
2789 QFNT1A: PUSHJ P,QFNT1
2790 JRST QUDULK ;OFF END OF FILE RETN NOT SKIPPING
2792 JRST QFNT7 ;LOCATED BLOCK CONTAINING WORD
2796 QFNTN: MOVE H,QUDPR(A) ;LIKE ABOVE BUT SCAN FORWARD ONLY FROM CURRENT SPOT
2799 CAIA ;EOF, DON'T SKIP RETURN
2804 QFNT1: SKIPE QSBI(A) ;DECODE NEXT BLOCK, CHNL IN A, SKIP UNLESS EOF.
2805 JRST QFNT2 ;BLOCK # IN QSLGL FILE ADR IN J (TAKE N PENDING)
2806 QFNT3: PUSHJ P,QMPDCH ;GOBBLE NEXT CHR OF DESC IN R (POINTED TO BY QDIRP) INCR QDIRP
2807 CAIN R,UDWPH ;ALSO RET BYTE PNTR IN TT
2809 JUMPN R,QFNT8 ;NOT OFF END OF FILE
2816 JRST QFNT6 ;SKIP AND TAKE
2820 QFNT5: MOVEI J,2000 ;ACTIVE BYTES IN BLOCK
2825 QFNT7: MOVSI T,%QALBK ;SET UP PROC LAST BLOCK FLG AND RETN
2826 ANDCAM T,QSRAC(A) ;CLEAR LAST BLOCK OF FILE BIT
2828 JRST QFNT7A ;NOT LAST BLOCK
2829 ILDB R,TT ;GET NEXT CHR IN DIR
2831 IORM T,QSRAC(A) ;PROCESSING LAST BLOCK
2832 QFNT7A: AOS QSBI(A) ;FAKE OUT PI ROUTINE WHICH WILL TRY TO INCREMENT
2836 QFNT4: MOVEI J,0 ;LOAD ADR
2845 QFNT6: MOVEI J,1-UDTKMX(R)
2850 SUBTTL DISK CHANNEL DATA AREAS
2852 QBFP: BLOCK NQCHN ;BUFFER LIST LH LAST RH FIRST
2853 ;READ: PI IN MP OUT. WRITE: MP IN PI OUT.
2854 SINLST: BLOCK NQS ;SWAP-IN LISTS FOR EACH DISK
2855 SOUTLS: BLOCK NQS ;SWAP-OUT LISTS FOR EACH DISK
2857 ;READ/WRITE LISTS LINK THROUGH MLO IN MEMBLT.
2858 ;LH(MEMPNT) HAS DISK ADDR, RH(MEMPNT) HAS # BYTES IN BLOCK IF FILE READ
2859 ;MWC IN MEMBLT HAS WORD COUNT IF WRITE (FOR EXTRA-WORDS)
2861 QFCHN: NQCHN ;NUMBER OF FREE QSK CHNLS (NOT COUNTING DIR WRITE AND SWAP CHANNELS)
2863 QUSR: REPEAT NQCHN,-1 ;USER
2864 DWUSR: -1 ;0 IF DIR WRITE ACTIVE
2865 SWUSR: REPEAT NQS,-1 ;0 IF SWAP XFER ACTIVE
2866 QDIRP: BLOCK NQCHN ;CHAR ADR PNTR TO DESC AREA FOR FILE
2867 QSLBLK: BLOCK NQCHN+NQS+1 ;LAST BLOCK NUMBER OF FILE WRITTEN
2868 QSLGL: BLOCK NQCHN ;LAST QSGL
2869 QSGL: REPEAT NQCHN+NQS+1,-1 ;-1 IDLE + ACTIVE TRACK
2870 ;LAST NQS+1 FOR FD WRITE AND SWAPPING
2871 QSBI: BLOCK NQCHN ; COUNT CONSECUTIVE BLOCKS
2872 QSBFS: BLOCK NQCHN ;NUMBER OF BUFFS THIS CHNL +1 IF EOF AT PI WITH QSBFS=0
2873 QPCLSR: BLOCK NQCHN ;PCLSR STATUS OF MAIN PROGRAM - LOAD SYSTEM CALL
2874 QSMDN: BLOCK NQCHN ;MAIN PRGM ACTIVE BUFFER NUM
2875 OLDRDT: BLOCK NQCHN ;STORAGE FOR PREVIOUS REFERENCE DATE
2876 QSRAC: BLOCK NQCHN+1
2877 REPEAT NQS, %QMSWP ;SWAPPING CHANNELS START OUT IN SWAP MODE
2879 %QALOK==400000 ;4.9 CHNL LOCKED (NOT USED)
2880 %QAEFR==200000 ;4.8 EOF REACHED READ
2881 %QAEFW==100000 ;4.7 EOF WRITE
2882 %QACTH==40000 ;4.6 DONT RELOAD. CORE JOB HUNG ON ACTIVE BUFFER
2883 %QAFUL==20000 ;4.5 GC DIR BEFORE COMMITTING ANOTHER BLOCK TO FILE
2884 %QADEL==10000 ;4.4 DELETE WHEN CLOSED
2885 %QAACC==4000 ;4.3 FILE ADDRESS ALTERED BY .ACCESS OR OTHERWISE
2886 %QAPAR==2000 ;4.2 NON RECOV PARITY ERR (OR OTHER DISK ERR) AT PI
2887 %QAOUT==1000 ;4.1 ASSOC USER OUT DONT RELOAD (NOT IMPLEM.)
2888 %QALBK==400 ;3.9 READ CHNL PROCESSING LAST BLOCK FLAG
2889 %QAMPU==200 ;3.8 UPDATE QSMPRP, QSMPRC ON NEXT BUFFER GOBBLE
2890 %QAWOV==100 ;3.7 FILLING OUT LAST BLK OF FILE IN WRITE OVER MODE PAST ORIG EOF
2891 %QALNK==40 ;3.6 FILE IS REALLY A LINK
2892 %QALOP==20 ;3.5 LINKS WERE TRACED IN OPENING THIS FILE.
2893 %QARWT==10 ;3.4 MAKE WOULD-BE READERS WAIT (RATHER THAN GETTING FILE LOCKED ERROR)
2894 %QAFNY==4 ;3.3 "FUNNY BLOCK", WORD COUNT IN LAST WORD
2895 $QAMOD==220200 ;3.2-3.1 READ/WRITE MODE 0 NORMAL 1 WRITE OVER 2 COPY OVER WRITE
2896 %QAMWO==1 ;3.1=1 => WRITE-OVER MODE.
2897 %QM==777777 ;RH CHANNEL MODE. INDEX INTO ACTION TABLES USED AT PI LEVEL.
2898 .SEE %QMIDL ;FOR TABLE OF CHANNEL MODES
2900 QDSKN: BLOCK NQCHN ;DISK UNIT NUMBER
2901 DWSKN: 0 ;DISK WRITING DIR ON
2902 SWSKN: REPEAT NQS,.RPCNT ;DISK SWAP XFER
2903 QSCRW: BLOCK NQCHN ;0 READ -1 WRITE
2906 QSCABN: BLOCK NQCHN ;ACTIVE BUFFER NUMBER PI LEVEL OR -1 IF NONE
2907 DWABN: -1 ;DISK D.W. A.B.N
2908 SWABN: REPEAT NQS,-1 ;SWAP ABN
2909 QUDPR: BLOCK NQCHN ;NUMBER OF ASSOCIATED USER DIR PNTR
2910 QUDFPR: BLOCK NQCHN ;RELATIVE PNTR TO FILE AREA, ZERO IF NO PARTICULAR FILE
2911 QMPTN: BLOCK NQCHN ;HAS LAST TRACK STORED IN DIRECTORY
2912 QMPTC: BLOCK NQCHN ;MAIN PRGM TRACK COUNT
2913 QMTTR: BLOCK NQCHN ;TRACK RESERVED OR -1
2914 QMFTP: BLOCK NQCHN+1 ;TRACK NUMBER FOR SCAN FOR FREE TRACKS IN TUT ON WRITE
2915 REPEAT NQS,NUDSL; DITTO FOR SWAP CHANNELS
2916 QERRS: BLOCK NQCHN+NQS+1 ;NUMBER ERRORS TRYING LAST OP
2917 QSMPRP: BLOCK NQCHN ;MAIN PRGM BYTE POINTER
2918 QSMPRC: BLOCK NQCHN ;M.P. COUNT (BYTES LEFT IN BUFFER)
2919 QSBYTE: BLOCK NQCHN ;LH BYTE PNTR (P=44), RH BYTES PER WORD
2920 QSBSIZ==300600,,QSBYTE ;BYTE POINTER TO CHANNEL BYTE SIZE
2921 QFBLNO: BLOCK NQCHN ;BYTE # IN FILE OF BEG OF BLOCK BEING PROCESSED AT M.P. LEVEL
2922 QRADAD: BLOCK NQCHN ;DESIRED BYTE ADR (LOOKED AT IF %QAACC OR %QAMPU IN QSRAC SET)
2923 QPIBSZ: BLOCK NQCHN ;NUMBER OF BYTES IN BLOCK ACTIVE AT P.I. LEVEL (READ)
2924 ;BIT 4.9 => GET FROM LAST WORD IN BLOCK (%QAFNY)
2925 QMPBSZ: BLOCK NQCHN ;NUMBER OF BYTES IN MN PROG ACTIVE BUFFER
2926 QLDPTR: BLOCK NQCHN .SEE NLDSBQ ;DURING SBLK LOADING, HOLDS THE AOBJN POINTER
2927 ;INTO USER CORE FOR DOING A DISK TRANSFER ON.
2928 QSMMP: BLOCK NQS ;MMP ADDRESS OF BLOCK ACTIVE ON SWAPPING CHANNEL
2930 ;VARIABLES FOR CURRENT TRANSFER
2932 QSDU: -1 ;UNIT TRANSFERING DATA, -1 IF NONE.
2933 QSDCH: -1 ;CHNL READY TO BE TRANSFERED ON QSDU
2934 QERS1: -1 ;ERR VERIFY SWITCH -1 NO ERR 0 EXPECTING COMPLETION OF VERIFY OP
2935 QDWIP: 0 ;NUMBER OF DIR WRITE IN PROGRESS 4.9=1=>MASTER
2938 QSDU1: -1 ;QSDU FOR OTHER CONTROLLER
2939 QSDCH1: -1 ;ASSOCIATED CHANNEL
2940 QTUNT1: -1 ;UNIT TO TRANSFER NEXT
2941 QTCHN1: -1 ;CHANNEL TO TRANSFER NEXT
2946 LQTM1: 0 ;TIME LAST TRANSFER STARTED
2949 ;MASTER FILE DIRECTORY
2951 QMDRO: -1 ;ORIGIN OF MASTER DIR 4.9 IF LOCKED
2954 ;4.5, 4.4, 4.3, ... CHANGED + NOT WRITTEN UNIT 0, 1, 2, ...
2955 ;3.2=1 NOT RECONCILED (NQFUS NOT SET UP)
2956 ;3.1-3.5 MUST BE ZERO (AT LEAST AFTER ITS RECONCILED)
2957 QAMDNO: -1 ;ASCENDING MASTER DIRECTORY NUMBER, -1 NOT SET UP
2958 NQFUS: 0 ;NUMBER OF FREE LOSER SLOTS IN MFD
2960 ;TRACK UTILIZATION TABLES
2962 QTUTO: REPEAT NQS,-1 ;ADDRESS OF TUT. LH SIMILAR TO QMDRO
2964 ;4.8 READ-IN NOT STARTED YET
2965 ;4.6 NOT READ IN YET
2966 ;CHANGED AND NOT WRITTEN ON UNIT
2967 ;0 = 4.5 1 = 4.4 2 = 4.3 3 = 4.2 4 = 4.1
2969 ;3.1-3.5 MUST BE ZERO
2970 QDPWF: BLOCK NQS ;-1 TUT NOT RECONCILED (CALL QTCH1)
2971 QTWRTM: BLOCK NQS ;TIME TUT LAST WRITTEN
2972 QSFT: REPEAT NQS,-1 ;NUMBER TRACKS FREE IN USER AREA
2973 QSFTS: BLOCK NQS ;NUMBER TRACKS FREE IN SWAPPING AREA
2974 QPKNM: BLOCK NQS ;NAME OF PACK
2975 QPKID: REPEAT NQS,-1 ;PACK ID OF DISK ON DRIVE
2977 QRESRV: REPEAT NQS,-1 ;NON-ZERO => PACK ON THIS DRIVE RESERVED. SET FROM TUT.
2978 ;NOT 0 AND NOT -1 => SIXBIT DEVICE NAME FOR "SECONDARY" PACK
2980 NTBL: ;NUMBER OF BLOCKS IN TUT ON THIS DRIVE
2981 IFE T300P, REPEAT NQS, NTUTBL
2983 REPEAT T300P, NTUTBL
2984 REPEAT NQS-T300P, NTUTB1
2987 ;POSITIONER VARIABLES (INDEXED BY PHYSICAL DRIVE)
2989 QSKT1: REPEAT NQS,-1 ;CHANNEL POSITIONER SET FOR OR -1 IF NONE
2990 QRCAL: REPEAT NQS,0 ;-1 IF RECALIBRATING
2991 QSPPS: REPEAT NQS,-1 ;INTENDED POSITIONER POSITION (NOT USED???)
2992 QSEEK: BLOCK NQS ;-1 IF SEEKING
2993 QPOS: REPEAT NQS,-1 ;CURRENT CYLINDER
2994 QPOSGL: BLOCK NQS ;CYLINDER TRYING TO POSITION TO
2996 QRCTIM: BLOCK NQS ;RECALIBRATE TIMEOUT IN HALF SECONDS. THE ATTNS
2997 ];DC10P ; TEND TO GET LOST FOR SOME REASON
2999 ;MISCELLANEOUS DISK VARIABLES
3001 QACT: REPEAT NQS,0 ;ONLY USE UNITS WITH 0
3002 QACTB: 0 ;4.5 UNIT 0 ACT 4.4 1 ACT 4.3 2 4.2 3 4.1 4
3004 QWBUFS: 0 ;TOTAL NUMBER OF WRITE BUFFERS ACTIVE
3006 QWBFMX: 10.*DC10P+15.*RP10P+30.*RH10P+20.*RH11P ;MAX # ALLOWED. SHOULD BE
3007 ; ABOUT 1 SEC DISK XFER.
3008 QHUNGF: 0 ;-1 => DISK CONTROL HUNG, PI LEVEL SHOULD RESET, RECALIBRATE, RETRY
3009 NTQHNG: BLOCK NQS ;NUMBER OF TIMES TRANSFER HUNG ON THIS UNIT
3011 QTUNT: 0 ;UNIT TO TRANSFER ON NEXT
3013 QLCHN: 0 .SEE QINT2C
3014 QWRU: -1 ;DEFAULT WRITE UNIT (-1 if there isn't a default unit yet)
3015 MDSK: 0 ;DRIVE # OF MASTER DISK
3016 QACTTM: -1 ;SETOM ON READ OR WRITE DATA TRANSFER
3017 ;AOS AT SSLCK IF + OK TO WRITE DIRS
3018 ;IE DON'T TIE UP DISK TO WRITE DIR UNLESS THINGS ARE QUIET
3019 QDWFAR: -10. .SEE QINT3 ;WRITE DIRS SOME OF THE TIME ANYWAY
3020 LQTM: 0 ;TIME AT WHICH LAST COMMAND GIVEN TO DISK
3021 QFTTHR: 600. ;IF FREE TRKS ON QWRU GOES BELOW THIS, SWITCH TO UNIT WITH MOST FREE TRACKS
3022 QRDAHD: IFE MCOND DM,[0] .ELSE 2 ;NUMBER OF BLOCKS TO READ AHEAD
3024 LASTGC: 0 ;NAME OF LAST DIRECTORY TO GET GC'ED
3028 QNUD==40. ;NUMBER USER DIRECTORIES
3030 QFUD: QNUD ;NUMBER OF FREE UFD SLOTS
3032 QSNUD: BLOCK QNUD ;USER NAME OR 0 IF FREE
3033 QSNLCN: BLOCK QNUD ;4.9 LOCKED, 4.8 ALSO NOT IN CORE RH CORE ADR
3034 .SEE DCHBT ;4.6 =1 NOT PAWED OVER 4.5 CHNGD AND NOT WRITTEN ON UNIT 0
3035 ;4.4 UNIT 1 4.3 UNIT 2 4.2 UNIT 3 4.1 UNIT 4
3036 ;3.9 UNIT 5 3.8 UNIT 6 3.7 UNIT 7
3037 %QUDWM==40 ;3.6 WRITE IMMEDIATELY ON MASTER DISK
3038 ;@ + XR BITS MUST = 0
3040 QSNNR: BLOCK QNUD ;NUMBER PC'S LOOKING AT THIS IE
3041 ;+1 FOR FILE OPEN AND USER IN CORE(?)
3042 QSNMI: BLOCK QNUD ;TRACK N OF USER DIR IF NOT NEWLY CREATED
3043 QSFBT: BLOCK QNUD ;FREED-BLOCKS-TABLE. HEAD OF A LIST OF PAGES,
3044 ;THREADED THROUGH THE SECOND WORD AND ENDING WITH
3045 ;ZERO. FIRST WORD IS AOBJN POINTER TO FREE PART
3046 ;OF PAGE. FROM THIRD WORD UP TO BELOW WHERE AOBJN
3047 ;POINTS ARE WORDS UNIT,,BLOCK WHICH RECORD DISK
3048 ;BLOCKS TO BE FREED ONCE THE DIR HAS BEEN WRITTEN
3049 ;OUT TO THE MASTER DISK. ELIMINATES REUSED ADDRESS
3050 ;PROBLEMS BY GUARANTEEING THAT IF THE SYSTEM SHOULD
3051 ;CRASH AT ANY TIME, THERE CANNOT BE TWO DIRECTORIES
3052 ;ON DISK THAT BOTH POINT TO THE SAME BLOCK.
3055 QSALLO: BLOCK QNUD ;-1 OR DRIVE # DIRECTORY ALLOCATED TO
3060 UDRSW: -1 ;USER DIR AREA LOCKED
3062 QCHSW: -1 ;CHNL AREA LOCKED
3064 QSKOSW: -1 ;QSKO1 LOCKED (USER DIR READIN)
3067 ;LIST OF PAGES CONTAINING BLOCKS WHICH CAN NOW BE FREED. MOVED TO
3068 ;HERE FROM QSFBT WHEN THE DIR IS WRITTEN OUT. THE ACTUAL FREEING
3069 ;IS DONE BY THE CORE JOB.
3073 ;VARIABLES FOR SYSTEMS CONCEPTS DISK CONTROL
3076 QRCSW: 105 ;- NO READ COMPARE 0 COMPARE WRITES + COMPARE ALL
3077 QCST: 0 ;CONI DC0, AT QINT
3078 QERST: 0 ;HAS CONI DC1, BITS WHEN AN ERROR HAPPENS
3079 PKIDM: 0 ;-1 WAITING FOR PACK ID TO BE READ
3080 RPKID: -1 ;PACK ID READ INTO HERE BY DISK CONTROL
3081 QDRSTS: 0 ;DRIVE STATUS WORD STORED BY DISK CONTROL
3084 0 ;FOR BLT INTO QXWDS
3089 QCHPR2: DCOPY (-2000_2&37774)
3090 DCOPY (-NXWDS_2&37774)QXWDS
3091 QCHPR4: DHLT ;OR DRC
3092 QCHPR3: DCCOMP (-2000_2&37774)
3093 DCCOMP (-NXWDS_2&37774)QXWDS
3096 GPKID: DSPC+DSCRHD+DSWNUL+DUNENB+TUTCYL_11.+TUTSRF_6+TUTSEC
3099 QRECAL: DSPC+DSRCAL+DUNENB
3102 ;VARIABLES FOR DEC RP10 DISK CONTROL
3105 QERST: 0 ;CONI DPC, ON ERROR
3106 QERDTI: 0 ;DATAI DPC, ON ERROR
3107 QCST: 0 ;CONI DPC, AT QINT
3108 QCHPRG: 0 ;SEEK COMM
3109 IFN KA10P, QIOWD: -2000,, ;XFER DATA (HRRM ADR-1 IN RH)
3117 QGTBZY: 0 ;FLAG FOR SOFTWARE AT INT
3120 QRCSW: 0 ;NON-ZERO TO ENABLE READ-COMPARING
3121 RDCPHS: 0 ;0 NORMAL, -1 DOING OPERATION WHICH SHOULD BE READ-COMPARED
3122 ; AFTERWARD, + DOING READ-COMPARE
3124 RCIOWD: BLOCK 2 ;CHANNEL PROGRAM FOR READ INTO QRCBUF
3125 ];KA10P ;ON KL WE HAVE TO PUT IT IN THE EPT!
3129 ;VARIABLES FOR DEC RH10 DISK CONTROL
3132 QCHPRG: 0 ;DATA TRANSFER COMMAND
3133 QCHPGA: 0 ;ADDRESS (CYL IN LH, TRACK-SECTOR IN RH)
3134 NCSHI: 0 ;NUMBER OF CACHE INVALIDATES
3135 NCSHIL: 0 ;NUMBER OF LOOPS WAITING FOR CACHE INVALIDATES
3136 NCSHU: 0 ;NUMBER OF CACHE UNLOADS
3137 NCSHUL: 0 ;NUMBER OF LOOPS WAITING FOR CACHE UNLOADS
3138 QERST: 0 ;CONI AT LAST ERROR (LEAVE THIS THROUGH QECPAT IN SAME ORDER)
3139 0 ;DATAI AT LAST ERROR
3140 QERSTS: 0 ;%HRSTS AT LAST ERROR
3141 QERER1: 0 ;%HRER1 AT LAST ERROR
3142 QERER2: 0 ;%HRER2 AT LAST ERROR
3143 QERER3: 0 ;%HRER3 AT LAST ERROR (IBM WOULD CALL THIS A CHANNEL LOGOUT AREA)
3144 QERDCL: 0 ;%HRDCL AT LAST ERROR
3145 QECPOS: 0 ;%HRPOS AT LAST ERROR
3146 QECPAT: 0 ;%HRPAT AT LAST ERROR
3147 QCST: 0 ;CONI AT LAST INTERRUPT
3148 QGTBZY: 0 ;FLAG FOR SOFTWARE-CAUSED INTERRUPT
3149 QECCS: BLOCK NQS ;NUMBER OF ECC CORRECTED ERRORS, PER DRIVE
3150 QECCAD: BLOCK NQS ;DISK ADDRESS OF MOST RECENT ECC CORRECTED ERROR
3151 RHDATO: -1 ;LAST DATAO DSK, FOR DEBUGGING
3152 ECCPAG: BLOCK 8 ;TEMP FOR SAVING PAGE MAP VARS AT QECC (WITH SPM)
3153 NQDRE: BLOCK NQS ;# MASSBUS TIMEOUTS PER DRIVE.
3154 NQSATN: BLOCK NQS ;# SPURIOUS ATTENTIONS IN MID-TRANSFER
3155 NQEATN: BLOCK NQS ;# ATTENTIONS REPORTING ERRORS
3158 ;VARIABLES FOR DEC RH11 DISK CONTROL (ON THE KS10 UNIBUS)
3161 QCHPRG: 0 ;DATA TRANSFER COMMAND
3162 QCHPGA: 0 ;ADDRESS (CYL IN LH, TRACK-SECTOR IN RH)
3163 QIOWD: 0 ; BA,,WC for RH11
3164 QCST: 0 ;CS1 AT LAST INTERRUPT
3165 QGTBZY: 0 ;FLAG FOR SOFTWARE-CAUSED INTERRUPT
3167 QERST:: ;Gubbish saved at last error
3168 QERCS1: 0 ; CS1 Control & Status 1
3169 QERCS2: 0 ; CS2 Control & Status 2
3170 QERSTS: 0 ; STS Drive status
3171 QERBA: 0 ; BA Unibus address for transfer
3172 QERWC: 0 ; WC Word count for transfer
3173 QERER1: 0 ; ER1 Error 1
3174 QERER2: 0 ; ER2 Error 2
3175 QERER3: 0 ; ER3 Error 3
3177 QECPOS: 0 ; POS ECC position
3179 QECPAT: 0 ; PAT ECC pattern
3180 QERMAP: 0 ? 0 ; Unibus map to disk buffer
3182 QECCS: BLOCK NQS ;NUMBER OF ECC CORRECTED ERRORS, PER DRIVE
3183 QECCAD: BLOCK NQS ;DISK ADDRESS OF MOST RECENT ECC CORRECTED ERROR
3185 NQSATN: BLOCK NQS ;# SPURIOUS ATTENTIONS IN MID-TRANSFER
3186 NQEATN: BLOCK NQS ;# ATTENTIONS REPORTING ERRORS
3187 NQOFFL: BLOCK NQS ;# TIMES DISK WENT OFFLINE
3190 DIRHNG: 0 ;LH POINTS TO LIST OF DIRHNG DEVICE CHANNELS,
3191 ;CHAINED THROUGH LH'S OF IOCHNM WORDS.
3192 ;0 MEANS END OF LIST
3193 ;MODIFY ONLY WITH THE CLOCK OFF.
3194 ;EACH DIRHNG DEVICE CHANNEL'S IOCHST WORD RH CONTAINS THE
3195 ;TRACK NUMBER OF THE DIRECTORY IT IS LOOKING AT.
3202 QATTNS: REPEAT NQS,500000+.RPCNT_14,,1_<10-.RPCNT>
3203 ;WORDS TO CLEAR ATTNS AND SELECT DRIVES
3209 DCHBT: 20000,, ;BIT SET IF DIR NOT WRITTEN OUT ON UNIT
3217 IFL .-DCHBT-NQS,.ERR YOU BETTER FIND ANOTHER BIT FOR QACTB,QSNLCN,QTUTO
3220 QTRAN: 0 ;FORMERLY MAPPED 203 CYL VIRTUAL DRIVES TO 406 CYL CALCOMPS
3221 1 ;4.9 => 2ND HALF OF PHYSICAL DRIVE
3222 2 ;(DOESN'T DO ANYTHING NOW THAT MEMOWRECKS ARE GONE,
3223 3 ; BUT KEEP AROUND IN CASE EVER NEEDED AGAIN.)
3228 IFL .-QTRAN-NQS, .ERR BARF AT QTRAN
3231 SUBTTL DISK CLOSE ROUTINES
3237 ANDCAM Q,QSRAC(A) ;FLUSH RANDOM ACCESS HACKERY
3238 PUSHJ P,QICLW1 ;WAIT FOR INPUT TO STOP
3240 TLNE TT,%QADEL ;DELETE?
3242 MOVE H,QUDPR(D) ;DIRECTORY NUMBER
3245 QICLX: SOSGE QSNNR(H) ;FREE DIRECTORY CHANNEL HAD BEEN USING
3251 QICLW1: MOVE D,A ;IDLE CHANNEL AND FLUSH READ BUFFERS
3259 QSICL3: HLLZS QSRAC(D) .SEE %QMIDL ;STOP PI
3261 QSICL5: PUSHJ P,QSBRB1 ;RETURN M.P. BUFFER IF ANY
3262 QOCL7: HRRZ A,QBFP(D) ;ALSO ENTER TO RETURN UNUSED READ BUFFER ON WRITE OVER MODE
3263 QSICL2: JUMPE A,QSICL6
3264 LDB C,[MLO,,MEMBLT(A)]
3270 QSICL6: SETZM QBFP(D)
3273 QSICL4: MOVEI A,%QMRD1 ;STOP PI AFTER THIS BLOCK
3276 SKIPL QSGL(D) ;WAIT FOR CHANNEL TO DEACTIVATE
3281 QOCL: PUSHJ P,QSOCL5 ;CLEAN UP THE DISK CHANNEL
3282 QSOCL4: MOVE D,A ;ENTRY FROM QALINK
3283 QSOCL6: MOVE Q,QUDFPR(D)
3288 JRST QCDLWO ;DELETED (PRESUMABLY VIA DELEWO)
3289 MOVE A,UNFN1(Q) ;Get names of file being hacked.
3291 PUSHJ P,QLOOK ;FILING OVER ANYTHING?
3295 CAMN I,Q ;BEING WRITTEN BITS WENT AWAY?
3296 BUG ;TRYING TO DELETE THE FILE WE'RE WRITING
3297 PUSHJ P,QSOCLD ;YES FLUSH IT
3298 PUSHJ P,QUDLK ;RELOCK DIR UNLOCKED BY QSOCLD ETC
3299 JRST QSOCL6 ;MAKE SURE ONE HASN'T REAPPEARED WHILE DIR UNLOCKED
3301 QSOCL5: LDB H,[$QAMOD,,QSRAC(A)]
3302 JUMPN H,QOCL6 ;DONT HACK ACTIVE WD COUNT IN WRITEOVER MODE
3303 QOCL6A: MOVN D,QSMPRC(A) ;- NUMBER OF BYTES IN BLOCK NOT USED
3304 ADDB D,QMPBSZ(A) ;ADJUST BYTE COUNT OF LAST BLOCK TO REFLECT WHATS USED
3305 CLEARM QSMPRC(A) ;SO WILL BE A NOOP IF PCLSR OUT AND COME BACK THRU HERE
3306 QOCL4: MOVSI Q,%QAEFW
3307 IORM Q,QSRAC(A) ;SET EOF BIT FOR QSBWW AND QUDS
3309 SKIPL QSMDN(A) ;NO M.P. BUFFER ANYWAY
3310 JUMPE D,QOCL1 ;ABOUT TO WRITE NULL BLOCK, DON'T
3311 QOCL5: PUSHJ P,QSBWW
3313 PUSHJ P,[ SKIPGE QSCRW(T) ;WAIT FOR CHANNEL EITHER LEAVING WRITE MODE
3314 SKIPN QSBFS(T) ;OR WRITING OUT ALL ITS BUFFERS, I.E. PI LEVEL
3315 JRST POPJ1 ;ISN'T GOING TO DO ANYTHING MORE TO IT.
3318 SKIPE QBFP(A) ;MAKE SURE IF QSBFS NON-ZERO THAT IS ONLY EOF
3319 BUG ;NOT A BUFFER SITTING AROUND FORGOTTEN
3320 QOCL3: MOVE H,QUDPR(A)
3322 SKIPN D,QMPTC(A) ;SKIP ON NEXT "N" STILL PENDING
3324 PUSHJ P,QUDS ;STORE IT AWAY
3328 QOCL6: SKIPGE QSCRW(A) ;WAIT FOR CHANNEL TO IDLE OR HANG UP IN READ
3341 SOS B,QSBFS(A) ;COMPENSATE FOR EXTRA AOS ON EOF READ
3345 JRST QOCL6A ;HACKING LAST BLOCK PAST EOF, UPDATE ACTIVE WD COUNT
3348 QOCL1: PUSHJ P,QSBRB ;DISCARD BUFFER
3352 AOS QSFT(D) ;RESTORE TRACK
3355 QSOCL3: MOVE Q,QUDFPR(D)
3359 ANDCAM T,UNRNDM(Q) ;CLEAR WRITE IN PROG
3361 MOVE T,UDNAMP(TT) ;MAKE SURE IT GOES BEFORE * FILE OF SAME NAME
3364 JRST QSOC3E ;NO PREV FILE
3366 QSOC3A: SUBI J,LUNBLK
3369 JRST QSOC3B ;PREV FILE HAS DIFFERENT NAME
3374 REPEAT LUNBLK, PUSH P,.RPCNT(J)
3378 REPEAT LUNBLK, POP P,LUNBLK-.RPCNT-1(Q)
3382 QSOC3D: HRRZ A,QUDPR(T)
3390 QSOC3F: AOBJN T,QSOC3D
3391 QSOC3E: SETOM QUSR(D) ;FREE THE DISK CHANNEL
3396 CAMN C,[SIXBIT /.LPTR./]
3397 IORM TT,SUPCOR ;CLOSING FILE ON TPL DEVICE SO SET FLAG FOR SYS JOB
3399 CAMN C,[SIXBIT/.MAIL./]
3400 AOS NQMFWR ;CLOSING FILE ON .MAIL. => BUMP COUNT TO WAKE MAILER DEMON
3402 CAMN C,[SIXBIT/.XGPR./]
3403 AOS NXGPFW ;WAKE XGPSPL
3405 MOVE A,QSNMI(H) ;TELL DIRHNG DEVICE ABOUT IT
3407 MOVE TT,QACTB ;DIR CHANGED (AT LEAST WRITE-IN-PROG BIT TURNED OFF)
3413 SETZM (R) ;CLEAR IOCHNM WORD.
3416 QSOC3B: ADDI J,LUNBLK
3419 QOCLR: MOVE Q,QSRAC(A) ;CLOSE UNIT ASCII OUTPUT
3421 TLNN Q,%QAMWO+%QALNK
3422 PUSHJ P,QOCLPD ;PUT NEEDED PADDING UNLESS NOT A FILE OR NOT AT END
3425 QOCLPD: LDB Q,[360600,,QSMPRP(A)] ;NUMBER OF BITS NOT WRITTEN IN LAST WORD
3427 POPJ P, ;LAST WORD NOT WRITTEN AT ALL
3428 LSH Q,18.+6 ;FILL THOSE BITS WITH ^CS
3431 SKIPLE QSMPRC(A) ;INHIBIT STORE IF NO BUFFER ETC.
3435 SUBTTL DISK INTERRUPT ROUTINES
3437 OVHMTR QIN ;DISK INTERRUPT LOW-LEVEL
3444 TRNN TT,200000 ;END OF CYLINDER
3449 IDIVI D,NBLKSC ;IS IT LEGITIMATE?
3450 SKIPL QSDU ;IF NO TRANSFER IN PROGRESS, IGNORE
3451 CAIN E,NBLKSC-1 ;IS LEGITIMATE FOR LAST BLOCK IN CYLINDER
3453 BUG PAUSE,[MAYBE DISK CONTROL IS WRITING ALL OVER THE DISK AGAIN]
3455 TDNE TT,[17177700] ;ANY ERRORS?
3458 SKIPGE QSDU ;DONT CLOB CMD BUF TO CLR ATTS DURING DATA XFER
3459 TRNN R,776 ;ANY ATTNS
3461 LDB I,[11000,,R] ;YES,FIND WHICH DRIVE
3462 JFFO I,.+1 ;CLOBBERS Q
3465 QINTAT: DATAO DPC,QATTNS(Q) ;CLEAR ATTNS
3468 JRST QRECAT ;NOT ON CYLINDER, RECALIBRATE
3473 JRST QRECAT ;SEEK TO THE WRONG PLACE (CALCOMPS LIKE TO DO THIS)
3474 MOVEM A,QPOS(Q) ;REMEMBER WHERE IT IS AT
3477 JRST QINT ;TRY AGAIN
3479 QINTA: SKIPGE Q,QSDU
3480 JRST QINT1 ;NOT EXPECTING DATA COMPLETION - FIND NEW TRANSFER
3483 JRST DSKEX ;TRANSFER STILL IN PROGRESS, DISMISS
3487 JRST QHE ;XFER HUNG, RECALIBRATE AND RETRY
3488 JRST QINTA1 ;TRANSFER COMPLETE...
3491 CONI DPC,TT ;THIS LOOKS REDUNDANT BUT APPARENTLY IS NECESSARY
3492 ;DUE TO TIMING OF THE DISK-NOT-READY CONDITION
3493 CONO DPC,175700+DSKCHN ;RESET CONDITIONS
3496 CONSZ DPC,20 ;WAIT FOR UNBUSY
3498 MOVE Q,QSDU ;FOR QOVR
3500 TRNE TT,20000 ;OVERRUN
3502 TRNE TT,2000 ;NOT READY
3504 TDNE TT,[12010700] ;BITS 14,16,23,27-29 ARE LOSERS
3505 BUG HALT,[DSK: TOTALLY FATAL ERROR, CONI=],OCT,QERST
3506 TLNE TT,5 ;WD OR SECTOR PARITY ERROR
3508 TRNE TT,1000 ;WRITE LOCKED
3510 TRNE TT,40000 ;SEARCH FAILED
3512 TRNN TT,100000 ;POWER FAILURE
3514 CONSZ DPC,100000 ;TRY IT AGAIN
3518 QINTE1: TLNE R,10 ;FILE UNSAFE--NEED OPERATOR INTERVENTION
3519 BUG PAUSE,[DSK: FILE UNSAFE UNIT ],DEC,Q
3522 TLNE R,110 ;POSITION FAILURE (OR PROCEEDED FILE UNSAFE)
3524 AOS NQSE(Q) ;SPURIOUS ERROR
3527 QIRWRE: BUG PAUSE,[DSK: WRITE LOCKED UNIT ],DEC,Q
3530 QNRDY: LDB Q,[410300,,R] ;WHICH DPC
3532 SKIPGE QRCAL(Q) ;NOT SEEKING OR RECALIBRATING IS ERROR
3534 BUG PAUSE,[DSK: UNIT ],DEC,Q,[NOT READY]
3541 SKIPL PKIDM ;GETS SPURIOUS DIPE WHEN READING PACK ID
3542 CONSO DC1,7777 ;RUMOR THAT DSSERR DOESN'T ALWAYS SET
3547 QINTA: SKIPGE Q,QSDU
3548 JRST QINT1 ;NOT EXPECTING DATA COMPLETION, FIND NEW TRANSFER
3549 CONSZ DC0,DSSRUN+DSSACT
3550 JRST DSKEX ;ACTIVE OR RUN, TRANSFER IN PROGRESS, DISMISS
3551 AOSN PKIDM ;SKIP IF NOT FINISHED READING PACK ID
3554 JRST QHE ;XFER HUNG, RECALIBRATE AND RETRY
3556 JRST QEROK ;OK ON VERIFY
3557 JRST QINTA1 ;TRANSFER COMPLETE...
3560 CONO DC0,DCCLR+DCERR+DSKCHN ;CLEAR ERRORS
3563 CONSZ DC0,DSSRUN+DSSACT
3564 JRST .-1 ;ACTIVE OR RUN?
3566 JRST QERL1 ;VERIFY ALSO LOST
3567 TRNE TT,DOFFL+DPROT+DDOBSY+DNXM+DCPERR
3568 JRST QINTE1 ;REALLY LOST BIG
3571 TRNE TT,DWTHER+DFUNSF ;SEEK INC, END DISK, WATCHDOG, OR UNSAFE
3572 JRST QHE ;TRY TO RECALIBRATE
3574 TRZ TT,DRLNER ;IGNORE LENGTH ERROR IF READING PACK #
3575 TRNE TT,DIPE+DRLNER+DRCER+DCKSER
3579 AOS NQSE ;SPURIOUS ERROR (NOT LENGTH ERROR IN PKIDM)
3580 JRST QINTX ;SPURIOUS ERROR
3582 QINTE1: TRNE TT,DOFFL
3583 BUG PAUSE,[DSK: UNIT ],DEC,Q,[OFFLINE]
3585 BUG PAUSE,[DSK: UNIT ],DEC,Q,[WRITE PROTECTED]
3587 BUG PAUSE,[DSK: DATAO WHEN BUSY]
3589 BUG PAUSE,[DSK: MEM PAR OR NXM ERROR]
3593 CONO DC0,DCCLR+DCCATT+DSKCHN ;CLEAR ATTENTION
3594 LDB Q,[DSATDN Q] ;ATTENTION DRIVE NUMBER
3599 CONO DC0,DCCLR+DCATEB+DSKCHN ;CLEAR ATTENTION ENABLE
3602 ;THIS IS CALLED EVERY HALF SECOND
3603 QRCTMO: MOVEI Q,NQS-1
3609 BUG INFO,[DSK: RECAL TIMEOUT UNIT],DEC,Q
3611 CONO DC0,DCCLR+DCATEB+DSKCHN ;CLEAR ATTENTION ENABLE I GUESS
3617 ;;; RHCLRC(Q) Clear controller errors and select drive Q
3618 ;;; RHSLCT(Q) Select drive Q
3619 ;;; RHCMD(A) Command in A to current drive
3620 ;;; RHCLRD Clear current drive
3621 ;;; RHCHEK Check for immediate bad news
3622 ;;; All return CS1 in A
3624 RHSLCT: IOWRQ Q,%HRCS2
3625 RHCHEK: IORDQ A,%HRCS1
3626 TRNE A,%HXTRE+%HXMCP
3627 BUG HALT,[DSK: MASSBUS ERROR, CS1=],OCT,A
3630 RHCLRC: IOWRQ Q,%HRCS2 ; Must select drive before clearing controller
3631 MOVEI A,%HXTRE+%HXIE+%HMNOP
3633 RHCLRD: MOVEI A,%HXIE+%HMCLR
3645 TRNE TT,%HXTRE+%HXMCP
3647 TRNN TT,%HXSC ; Perhaps some drive needs attention?
3648 JRST QINT0 ; Not unless SC is set!
3651 QINT0: SKIPGE Q,QSDU
3652 JRST QINT1 ; Not expecting completion of transfer.
3654 JRST DSKEX ; Transfer still in progress.
3656 JRST QHE ; Transfer hung, recalibrate and retry.
3657 PUSHJ P,RHSLCT ; Select that drive.
3658 IORDQ A,%HRSTS ; Get its status.
3659 TRNE A,%HSERR ; Just in case %HXTRE didn't get set (by
3660 JRST QINTE ; analogy with RH10)...
3661 JRST QINTA1 ; Transfer complete...
3663 QINTAT: MOVNI Q,-35.(B)
3667 IOWRQ A,%HRATN ; Turn off attention bit.
3671 JRST [ AOS NQSATN(Q) ; Ignore attention in mid-transfer.
3674 JRST QINTA2 ; Ignore this drive.
3676 IORDQ B,%HRSTS ; Get status of drive with attention.
3677 TRC B,%HSMOL+%HSDPR+%HSRDY
3678 TRNN B,%HSMOL+%HSDPR+%HSRDY+%HSVV
3679 PUSHJ P,QOFFL ; Went offline and came back online
3680 TRNE B,%HSERR+%HSPIP
3681 JRST [ PUSHJ P,RHCLRD ; Drive barfing not during transfer
3682 AOS NQEATN(Q) ; so clear it
3683 JRST .+1] ;THEN CLEAR SEEK AND RECALIBRATE FLAGS
3684 SETZM QSEEK(Q) ;POSITIONING COMPLETION
3685 IFDEF %HRCCY,[ ;Current Cyl register only on RP disks
3687 MOVEM A,QPOS(Q) ;UPDATE CURRENT CYLINDER
3689 SETOM QSKT1(Q) ;SEEK TO WRONG PLACE
3692 MOVE A,QPOSGL(Q) ;On RMxx, jump to conclusion
3695 SETZM QRCAL(Q) ;NO LONGER RECALIBRATING
3696 JRST QINT0 ;IF NO XFER ACTIVE, MAYBE CAN START ONE ON
3699 QINTA2: SETOM QSKT1(Q) ;DON'T TRUST POS
3702 ; Went offline and came back online
3703 QOFFL: TRC B,%HSMOL+%HSDPR+%HSRDY ;Recover %HRSTS
3708 BUG INFO,[DSK: UNIT #],DEC,Q,[CAME BACK ONLINE, CS1=],OCT,A,[STS=],OCT,B,[ER1=],OCT,C,[ER2=],OCT,D,[ER3=],OCT,E
3711 BUG INFO,[DSK: UNIT #],DEC,Q,[CAME BACK ONLINE, CS1=],OCT,A,[STS=],OCT,B,[ER1=],OCT,C,[ER2=],OCT,D
3715 MOVEI A,%HMCLR ;Clear the drive
3717 MOVEI A,%HMRDP ;I said, clear the drive!
3720 IOWRQ A,%HROFS ;No offset, 18 bits, ECC on, HCI off
3721 MOVEI A,%HMACK ;Turn %HSVV back on so drive will work
3726 IRPS X,,[CS1 CS2 BA WC POS PAT] ; First get status of controller
3730 IORDQ A,UBAPAG+QUBPG_1 ; Unibus map counts as part of
3731 MOVEM A,QERMAP ; controller status.
3732 IORDQ A,UBAPAG+QUBPG_1+1
3734 SKIPGE Q ; Try hard to guess the drive.
3735 LDB Q,[$HYDSK QERCS2]
3736 PUSHJ P,RHCLRC ; Clear controller errors and select drive
3737 ; so that we can read its status too.
3738 TRNN A,%HXRDY ; Why would controller be busy? (RH10
3739 BUG ; code checks for this...)
3741 IRPS X,,[STS ER1 ER2]
3745 MOVE A,QERCS1 ; A: CS1
3746 MOVE R,QERCS2 ; R: CS2
3747 IFDEF %HRER3,[ ; Disks with ER2 -and- ER3
3750 SKIPN QERER2 ; Bad news
3754 IFNDEF %HRER3,[ ; Disks with just ER2
3758 TRNN A,%HXMCP ; Real bad news
3759 TRNE R,%HYWCE+%HYPE+%HYNED+%HYNEM+%HYPGE+%HYMXF
3760 BUG HALT,[DSK: UNIT #],DEC,Q,[LOSING. CS1=],OCT,A,[ CS2=],OCT,R
3761 TRNE R,%HYDLT+%HYMDP ; Data bus losing?
3763 MOVE A,QERSTS ; Check Drive Status
3764 TRC A,%HSVV+%HSRDY+%HSDPR+%HSMOL ; Better be all on!
3765 TRCE A,%HSVV+%HSRDY+%HSDPR+%HSMOL
3768 JRST [ AOS NQSE(Q) ; Spurious?
3770 MOVE B,QERER1 ; Check the main error register
3771 TRNE B,#<%H1ECC+%H1DTE+%H1CRC+%H1HCE+%H1ECH+%H1FER+%H1PAR>
3772 JRST UNSAFE ; Those not listed above are considered "hard"
3773 CAIN B,%H1ECC ; Correct correctable error if that is the
3774 JRST QECC ; only problem.
3775 PUSHJ P,QINTER ; Else print message and reset drive
3776 TRNE B,%H1DTE+%H1CRC+%H1HCE+%H1FER ; These require recalibration
3778 TRNE B,%H1ECC+%H1ECH+%H1PAR ; These require reread
3780 JRST QOVR ; No error bits set? (How can this
3781 ; happen?) Go and retry...
3783 ;;; Controller error:
3784 QINTE1: BUG INFO,[DSK: ERR UNIT #],DEC,Q,[CS1=],OCT,QERCS1,[CS2=],OCT,QERCS2
3789 QINTER: BUG INFO,[DSK: ERR UNIT #],DEC,Q,[ER1=],OCT,QERER1,[ER2=],OCT,QERER2,[ER3=],OCT,QERER3,[STARTING DISK ADDR=],OCT,QCHPGA
3792 QINTER: BUG INFO,[DSK: ERR UNIT #],DEC,Q,[ER1=],OCT,QERER1,[ER2=],OCT,QERER2,[STARTING DISK ADDR=],OCT,QCHPGA
3794 JRST RHCLRD ; Reset error status in drive
3796 ;;; Come here for drive unsafe and similar bad things. May be set to
3797 ;;; either halt or attempt retry (via USFHLT variable). Note that when we
3798 ;;; get here the state of the drive has not yet been disturbed.
3799 UNSAFE: SKIPE USFHLT
3800 BUG PAUSE,[DSK: TOO MANY ERRORS]
3801 MOVEI A,2 ;HALT IF ANOTHER ERROR WITHIN 1/2 - 1 SECOND
3803 PUSHJ P,QINTER ;GIVE ERROR MESSAGE AND RESET DRIVE
3805 JRST QHE ;RECALIBRATE AND RETRY
3806 JRST QREC ;Just recalibrate, no transfer to retry
3808 QECC: PUSHJ P,RHCLRD ; Reset drive
3809 CAME Q,QSDU ; ECC error better be for transfer in
3812 TRNN A,10 .SEE %HMRED
3813 BUG ; ECC error should only happen during read.
3814 LDB A,[$UPPAG QERMAP]
3816 DPB A,[.PAREP+EXEUMP] ; Point parity error page at buffer.
3817 CLRPT 400000+PAREP_12 ; Get it into our map now.
3818 CLRPT 401000+PAREP_12 ; Both halves...
3820 SUBI J,1000+QUBPG_14 ; Correct to relative byte address of start
3822 TRNE J,770777 ; Should always be aligned on sector boundary
3823 BUG ; and within a single block, right?
3824 LSH J,-2 ; J: Address of first word of losing sector
3826 MOVE A,QECPOS ; Get error position
3827 SOJL A,QDE ;HARDWARE POS IS OFF BY 1; IF 0 NOT CORRECTABLE
3828 IDIVI A,36. ;CONVERT TO WORD NO AND BIT NO
3830 JRST [ ADDI B,36. ;LAST WORD IN SECTOR - HACK IT TO AVOID NXM
3832 ADDI J,400000+PAREP_12(A) ; J: Address of losing word-pair
3833 ; (In parity error page.)
3834 MOVE U,B ;SAVE BIT NUMBER
3835 MOVS B,(J) ;GET FIRST LOSING WORD
3836 MOVS C,1(J) ;GET SECOND LOSING WORD
3837 MOVE D,QECPAT ;GET ERROR PATTERN
3838 SETZ E, ;MAKE INTO DOUBLE-WORD
3839 ROTC D,(U) ;ALIGN IT
3840 XOR B,D ;FIX THE BAD BITS
3842 MOVSM B,(J) ;PUT CORRECTED DATA BACK
3845 DPB A,[.PAREP+EXEUMP] ;FLUSH THE DISK BUFF FROM MAP
3846 CLRPT 400000+PAREP_12
3847 CLRPT 401000+PAREP_12 ; Both halves...
3849 AOS QECCS(Q) ;LOG THE LOSS
3850 LDB E,[111000,,QERBA] ; E: Number of sectors transferred (including
3851 SUBI E,QUBPG_3 ; ECC sector)
3853 LDB B,[$HASEC A] ;Compute disk address of failing sector:
3855 IDIVI B,NSECS ; C: sector
3861 HLRZ A,A ; A: cylinder
3862 MOVE D,QSDCH ; D: chnl
3863 BUG INFO,[DSK: ECC CORRECTED ERROR, UNIT #],DEC,Q,[CYL ],DEC,A,[HEAD ],DEC,B,[SEC ],DEC,C,[QSRAC],OCT,QSRAC(D)
3865 JRST QINTA1 ;XFER COMPLETE
3867 LDB B,[$HASEC QCHPGA] ;NOW DETERMINE WHERE TO RESUME TRANSFER
3870 DPB C,[$HASEC QCHPGA]
3871 LDB C,[$HATRK QCHPGA]
3873 DPB C,[$HATRK QCHPGA] ;NO NEED TO IDIVI A,NHEDS SINCE NEVER CROSS
3876 HRL E,QERWC ; Reassemble "iowd" from
3877 HRR E,QERBA ; saved parts. (Don't trust stuff saved
3878 MOVEM E,QIOWD ; in controller more than we have to.)
3879 HRRZ C,QSDCH ;FOR QECCX
3880 JRST QECCX ;MORE TO DO, CONTINUE XFER
3893 MOVSI A,%HRATN ;FIND DRIVES NEEDING ATTENTION
3896 QINT0: SKIPGE Q,QSDU
3897 JRST QINT1 ;NOT EXPECTING COMPLETION OF TRANSFER
3899 JRST DSKEX ;NO COMPLETED TRANSFER
3901 JRST 4,.-1 ;TRANSFER STILL IN PROGRESS??
3903 JRST QHE ;XFER HUNG, RECALIBRATE AND RETRY
3904 MOVSI A,%HRSTS(Q) ;SOMETIMES %HSERR SETS AND %HIERR DOESN'T!
3908 JRST QINTA1 ;XFER COMPLETE...
3910 QINTAT: MOVNI Q,-35.(B) ;LOW BIT IS DRIVE 0
3912 MOVEI A,1 ;TURN OFF ATTENTION (DRIVE MAY BE LOSING
3913 LSH A,(Q) ;IN SUCH A WAY THAT READING %HRSTS DOESN'T CLEAR ATTN)
3917 JRST [ AOS NQSATN(Q) ;IGNORE ATTN IN MID-TRANSFER
3919 MOVSI A,%HRSTS(Q) ;GET STATUS OF DRIVE WITH ATTENTION
3920 PUSHJ P,RHGET ;THIS ALSO CLEARS THE ATTENTION BIT
3922 JRST QINTA2 ;IGNORE THIS DRIVE
3923 TRNE A,%HSERR+%HSPIP
3924 JRST [ MOVSI A,%HRDCL(Q)
3925 HRRI A,%HMCLR ;DRIVE REPORTING ERROR NOT DURING TRANSFER
3926 PUSHJ P,RHSET ;SO CLEAR THE DRIVE
3928 JRST .+1 ] ;THEN CLEAR SEEK AND RECALIBRATE FLAGS
3929 SETZM QSEEK(Q) ;POSITIONING COMPLETION
3932 MOVEM A,QPOS(Q) ;UPDATE CURRENT CYLINDER
3934 SETOM QSKT1(Q) ;SEEK TO WRONG PLACE
3935 SETZM QRCAL(Q) ;NO LONGER RECALIBRATING
3936 JRST QINT0 ;IF NO XFER ACTIVE, MAYBE CAN START ONE ON THIS UNIT NOW
3938 QINTA2: SETOM QSKT1(Q) ;DON'T TRUST POS
3941 ;INPUT FROM MASSBUS - ADDRESS IN LH(A), RETURNS DATA IN A
3943 RHGET: TLZA A,%HRLOD
3945 ;OUTPUT TO MASSBUS - ADDRESS IN LH(A), DATA IN RH(A)
3949 MOVEM A,RHDATO ;SAVE FOR REBUGGING
3950 MOVEI A,5 ;WAIT 3 USEC FOR BUS CYCLE
3954 BUG HALT,[DSK: MASSBUS ERROR, DATAO=],OCT,RHDATO,[DATAI=],OCT,A
3955 ANDI A,177777 ;RETURN 16-BIT REGISTER CONTENTS
3960 CONO DSK,%HOCLR+%HORAE+%HOATN+DSKCHN ;RESET CONTROLLER SO DRIVE STATUS MAY BE READ
3962 JRST .-1 ;SOMETIMES CONTROLLER IS BUSY??
3965 SKIPGE Q ;TRY HARD TO GUESS THE RIGHT DRIVE!
3966 LDB Q,[$HCDRV R] ;CURRENTLY SELECTED DRIVE
3967 IRPS X,,[%HRSTS %HRER1 %HRER2 %HRER3 %HRDCL %HRPOS %HRPAT]
3968 MOVSI A,X(Q) ;GET STATUS OF DRIVE
3970 MOVEM A,QERST+.IRPCNT+2
3972 SKIPN QERER2 ;FILE UNSAFE
3976 AOS NQDRE(Q) ;THIS BIT SUSPECTED OF BEING SET RANDOMLY.
3977 ;;CHECK FOR IRRECOV (?) HARDWARE LOSSAGE. EVEN MORE SO THAN 'UNSAFE'
3978 TDNE TT,[%HIILF+%HISDE+%HINXM+%HIDRE+%HIILC+%HIPWR]
3979 BUG HALT,[DSK: UNIT ],DEC,Q,[ LOSING. RH10 CONI= ],OCT,QERST
3980 IFN KS10P, .ERR So whats this all about?
3982 TLNN TT,(%HIDPE+%HICPE) ;IF CHANNEL DETECTS PARITY ERROR, CAUSE
3983 JRST QINTE0 ;PROCESSOR PARITY SWEEP WHICH WILL PROBABLY
3984 MOVSI A,SCLPAR ;CRASH THE SYSTEM ANYWAY. BEATS LOOPING!
3985 TDNN A,SUPCOR ;BUT DON'T CAUSE CLKB1E+7 HALT
3987 BUG CHECK,[DSK: MEM PAR ERR, QICWA/],OCT,QICWA,OCT,QICWA+1,[QIOWD/],OCT,QIOWD
3990 TDNE TT,[%HIOVR+%HICOV+%HIDPE+%HICPE+%HIBPE]
3991 JRST QINTE1 ;OVERRUN OR PARITY ON CONTROL BUS OR CHANNEL BUS - RETRY
3992 MOVE A,QERSTS ;DRIVE EXCEPTION, CHECK DRIVE STATUS
3993 TRC A,%HSVV+%HSRDY+%HSDPR+%HSMOL ;THESE BITS BETTER ALL BE ON
3994 TRCE A,%HSVV+%HSRDY+%HSDPR+%HSMOL
3995 BUG ;DRIVE TURNED OFF? MAYBE 11 HACKING THIS DRIVE?
3997 JRST [ AOS NQSE(Q) ;SPURIOUS?
3999 MOVE B,QERER1 ;CHECK THE MAIN ERROR REGISTER
4000 TRNE B,#%H1SOF ;ANY HARD ERRORS?
4002 CAIN B,%H1ECC ;IF JUST A CORRECTABLE ERROR,
4003 JRST QECC ;GO CORRECT IT
4004 PUSHJ P,QINTER ;OTHER SOFT ERROR, PRINT MESSAGE AND RESET DRIVE
4005 TRNE B,010620 ;SEARCH ERROR, OR HEADER READ OR FORMAT ERROR OR DRIVE TIMING
4006 JRST QHE ;REQUIRES RECALIBRATE
4007 TRNE B,100110 ;BUS PARITY OR ECC "HARD"
4008 JRST QDE ;REQUIRES RE-READ, GIVE UP AFTER N
4009 JRST QOVR ;NO ERROR BITS, PRINT MESSAGE AND RETRY
4012 QINTE1: BUG INFO,[DSK: ERR UNIT #],DEC,Q,[CONI=],OCT,QERST,[DCL=],OCT,QERDCL
4016 QINTER: BUG INFO,[DSK: ERR UNIT #],DEC,Q,[ER1=],OCT,QERER1,[ER2=],OCT,QERER2,[ER3=],OCT,QERER3,[STARTING DISK ADDR=],OCT,QCHPGA
4017 MOVSI A,%HRDCL(Q) ;NOW RESET ERROR STATUS IN DRIVE
4021 ;COME HERE FOR DRIVE UNSAFE AND SIMILAR BAD THINGS. MAY BE SET TO
4022 ;EITHER HALT OR ATTEMPT RETRY (VIA USFHLT VARIABLE). NOTE THAT WHEN
4023 ;WE GET HERE THE STATE OF THE DRIVE HAS NOT YET BEEN DISTURBED.
4024 UNSAFE: SKIPE USFHLT
4025 BUG PAUSE,[DSK: TOO MANY ERRORS]
4026 MOVEI A,2 ;HALT IF ANOTHER ERROR WITHIN 1/2 - 1 SECOND
4028 PUSHJ P,QINTER ;GIVE ERROR MESSAGE AND RESET DRIVE
4029 JRST QHE ;RECALIBRATE AND RETRY
4031 QECC: MOVSI A,%HRDCL(Q) ;RESET ERROR STATUS IN DRIVE
4034 CAME Q,QSDU ;CORRECT AN ECC ERROR
4035 BUG ;BARF ... NO TRANSFER IN PROGRESS
4038 BUG ;BARF ... SHOULDN'T HAPPEN DURING WRITE
4039 SKIPN A,QICWA+1 ;GET ADDRESS OF LAST WORD READ
4040 JRST 4,.-1 ;CHANNEL OUGHT TO HAVE STORED CONTROL WORD BY NOW
4042 TDZ J,[177+.BM $DFCWA] ;J := ADDRESS OF FIRST WORD IN LOSING SECTOR
4043 LDB A,[$DFCAD QIOWD]
4045 SOS H,A ;# WORDS SUCCESSFULLY XFERED.
4046 CAIL H,0 ;CHECK IF CHANNEL STORED BAD ADDRESS
4048 JRST QDE ;THIS SHOULD NEVER HAPPEN, BUT IT DOES, FREQUENTLY
4049 MOVE A,QECPOS ;GET ERROR POSITION
4050 SOJL A,QDE ;HARDWARE POS IS OFF BY 1; IF 0 NOT CORRECTABLE
4051 IDIVI A,36. ;CONVERT TO WORD NO AND BIT NO
4053 JRST [ ADDI B,36. ;LAST WORD IN SECTOR - HACK IT TO AVOID NXM
4055 ADD J,A ;J := ADDRESS OF LOSING WORD-PAIR
4057 ANDI J,1777 ;GET ADDR OF PAR ERR PAG
4058 ADDI J,400000+2000*PAREP ;IN EXEC ADDRESS SPACE
4059 IORI A,600000 ;MAKE THAT PAGE POINT TO THE DISK BUFFER
4060 DPB A,[.PAREP+EXEUMP]
4061 SPM ECCPAG ;GET IT INTO OUR MAP.
4063 MOVE U,B ;SAVE BIT NUMBER
4064 MOVS B,(J) ;GET FIRST LOSING WORD
4065 MOVS C,1(J) ;GET SECOND LOSING WORD
4066 MOVE D,QECPAT ;GET ERROR PATTERN
4067 SETZ E, ;MAKE INTO DOUBLE-WORD
4068 ROTC D,(U) ;ALIGN IT
4069 XOR B,D ;FIX THE BAD BITS
4071 MOVSM B,(J) ;PUT CORRECTED DATA BACK
4074 DPB A,[.PAREP+EXEUMP] ;FLUSH THE DISK BUFF FROM MAP
4077 AOS QECCS(Q) ;LOG THE LOSS
4080 LSH E,-7 ;NUMBER OF SECTORS TRANSFERRED (INCLUDING ECC SECTOR)
4081 LDB B,[$HASEC A] ;GET DISK ADDR OF FAILING SECTOR
4087 DPB B,[$HATRK A] ;NO NEED TO DIVIDE BY NHEDS SINCE NEVER CROSS CYLINDERS
4091 BUG INFO,[DSK: ECC CORRECTED ERROR, UNIT ],DEC,Q,[CYL ],DEC,A,[HEAD ],DEC,B,[SEC ],DEC,C,[QSRAC],OCT,QSRAC(D)
4092 LDB B,[$HASEC QCHPGA] ;NOW DETERMINE WHERE TO RESUME TRANSFER
4095 DPB C,[$HASEC QCHPGA]
4096 LDB C,[$HATRK QCHPGA]
4098 DPB C,[$HATRK QCHPGA] ;NO NEED TO IDIVI A,NHEDS SINCE NEVER CROSS CYLINDERS
4099 HRRZ C,QSDCH ;FOR QECCX
4100 LDB A,[$DFCWA QICWA+1] ;LAST CONTROL WORD PROCESSED
4101 SUBI A,1 ;CRETINOUS DF10
4103 BUG ;CHANNEL STORED BAD ADDRESS?
4105 MOVEI A,200(H) ;# WORDS ALREADY DONE.
4106 DPB A,[$DFWC A] ;PUT IT IN BOTH FIELDS.
4107 ADDB A,@QICWA ;ADVANCE C.W. TO REMAINING STUFF
4109 JRST QECCX ;MORE TO DO, CONTINUE XFER
4110 AOS QICWA ;ELSE ADVANCE TO NEXT C.W.
4112 JRST QECCX ;MORE TO DO, CONTINUE XFER
4113 JRST QINTA1 ;XFER COMPLETE
4117 T3INT: SETZM DSCDON ;CLEAR DONE FLAG THAT GOT US HERE
4118 SKIPGE QSDU1 ;OPERATION COMPLETE?
4119 JRST QINT1 ;NO, GO FIND SOMETHING TO DO
4120 HRRZ Q,DSCDRV ;YES, GET DRIVE OPERATION WAS ON
4123 CAME Q,QSDU1 ;TERMINATION ON DRIVE WE EXPECTED?
4124 BUG ;DRIVE NUMBER CLOBBERED?
4125 SETZM QRCAL(Q) ;PRESUMABLY NOT RECALIBRATING ANY MORE.
4126 MOVE A,DSCCMD ;COMMAND THAT JUST COMPLETED
4127 CAIN A,%DMREC ;WAS IT A RECALIBRATE?
4128 JRST QINT1E ;IF SO, CONTROLLER IS IDLE NOW
4129 MOVE C,QSDCH1 ;CHANNEL
4130 HRLZ E,DSCFLT ;CHECK FOR ERRORS
4132 JUMPE E,QINTI ;OPERATION COMPLETED UNEVENTFULLY
4133 MOVE D,DSCHED ;GET DISK ADDRESS AS CYL,,HEAD_9+SECTOR
4137 SKIPN QERRS(C) ;PRINT ONLY ONCE, NOT ON RETRIES
4138 BUG INFO,[DSK: T-300 ERR UNIT ],DEC,Q,[FAULT=],OCT,DSCFLT,[STATUS=],OCT,DSCSTS,[CMD=],OCT,DSCCMD,[CYL-SURF-SEC=],OCT,D
4139 TRZE E,%DSRTR+%DSECC ;THESE ARE NOT ERRORS
4141 JUMPE E,QINTI ;OPERATION COMPLETED SUCCESSFULLY (WITH INTERVENTION OF 2561)
4143 TRZ T,%DSECH+%DSIDE+%DSHCE
4144 JUMPN T,T3INT2 ;CONSIDER USING ERROR RECOVERY FEATURES
4145 TRNE A,%DMRED ;IF COMMAND IS A READ
4146 TRNE A,10 ;AND WE HAVEN'T TRIED THEM ALL
4148 AOS NQSE(Q) ;COUNT "SOFT ERRORS" (NOT "SPURIOUS" IN T-300 CASE)
4149 AOJA A,T3IO1 ;GO RETRY OPERATION USING NEXT FEATURE
4151 T3INT2: TLNN E,-1 ;ANY FAULT? PROBABLY UNRECOVERABLE BUT TRY RECALIBRATE
4152 TRNE E,%DSIDE+%DSHCE+%DSSKE+%DSOFL+%DSFLT ;DISK CONDITION THAT CALLS FOR RECAL
4154 JRST T3DE ;TRY OPERATION AGAIN. PROBABLY WILL LOSE BUT TRY.
4157 OVHMTR QSC ;DISK SCHEDULER (AND HIGHER-LEVEL INTERRUPT STUFF)
4159 QINTA1: SKIPL C,QSDCH ;XFER COMPLETE
4160 QINTI: SKIPGE A,QSCABN(C) ;CHANNEL IN C
4161 BUG ;MEMBLT INDEX IN A
4162 MOVE R,A ;BUFFER ADDRESS IN R
4163 IFN KL10P,[ ;QSRAC IN D, QSK# IN Q
4164 SKIPL QSCRW(C) ;IF READ, FLUSH CACHE AGAIN
4165 JRST [ PUSHJ P,CSHSWP ;SINCE USER MIGHT HAVE TOUCHED ABS PAGE
4167 MOVE A,R ;A WAS CLOBBERED
4171 SKIPL QSCRW(C) ;ON KS, CAN ONLY CLEAR THE WHOLE CACHE
4179 TLNE D,%QAPAR ;IGNORE IF LOSING ANYWAY (E.G. SEARCH ERR)
4184 SKIPE TT,RDCPHS ;NEED TO READ-COMPARE?
4185 JRST QRC1 ;READ-COMPARE STARTING OR FINISHED
4190 XCT .+1(D) ;INVOKE COMPLETION HANDLER
4192 %QMIDL::JRST 4,QINT1 ;IDLE - SHOULDN'T BE ACTIVE
4193 %QMRD:: JRST QRDFIN ;READ
4194 %QMWRT::JRST QWRFIN ;WRITE
4195 %QMWOV::JRST QWOVFN ;WRITE-OVER MODE
4196 %QMRD1::JRST QRD1FN ;READ BLOCK AT A TIME MODE
4197 JRST 4,QINT1 ;ILL CODE
4198 %QMUDR::JRST QUDRIN ;USER DIR IN
4199 %QMMDR::JRST QMDRIN ;MASTER DIR IN
4200 %QMTTR::JRST QTUTIN ;TUT IN
4201 %QMUDW::JRST QUFDWF ;USER DIR WRITE
4202 %QMMDW::JRST QMFDWF ;MASTER DIR WRITE
4203 %QMTTW::JRST QTUTWF ;TUT WRITE
4204 %QMSWP::JRST QSWPFN ;SWAP FINISHED
4205 JRST 4,QINT1 ;ILL CODE
4206 JRST 4,QINT1 ;ILL CODE
4207 JRST 4,QINT1 ;ILL CODE
4209 IFN %QMMAX-20, .ERR %QMMAX MUST BE A POWER OF 2
4212 ;CHANNEL DIDN'T TRANSFER EXACTLY 2000 WORDS
4213 QDFLOS: MOVEI D,1777(R) ;EXPECTED TERMINATION ADDRESS
4214 HRRZ B,QICWA+1 ;ACTUAL TERMINATION ADDRESS
4218 BUG HALT,[DSK: CHANNEL TRANSFERRED UP TO ],OCT,B,[RATHER THAN],OCT,D,[DISK IS CLOBBERED NOW.]
4220 QDFLZ1: BUG PAUSE,[DSK: CHANNEL TRANSFERRED UP TO ],OCT,B,[RATHER THAN],OCT,D
4224 ;;; SOFTWARE READ-COMPARE ROUTINES
4227 IFE RP10P+RH10P, .ERR READ-COMPARE ONLY CODED FOR RP-10 AND RH10
4228 ;IFE KA10P, .ERR READ-COMPARE ONLY CODED FOR KA-10
4230 ;;; REGULAR OPERATION COMPLETE, DO A READ-COMPARE TO BE SURE
4232 IFN T300P, CAIGE Q,T300P ;NO READ/COMPARE IF THIS IS T-300 CONTROLLER
4233 TLNE D,%QAPAR ;GIVING UP WITH FATAL ERR?
4234 JRST QRC0 ;NO READ-COMPARE THEN
4235 JUMPG TT,QRC2 ;JUMP IF READ-COMPARE COMPLETED
4236 MOVE E,QSGL(C) ;DISK BLOCK
4237 PUSHJ P,QPOSR ;E GETS DATAO WORD
4239 IOR E,[DREADC+7000+RCICWA] ;MAKE READ COMMAND
4240 CONO DPC,175700+DSKCHN
4241 MOVE T,[-2000,,QRCBUF-1] ;STORE CHANNEL PROGRAM
4247 DATAO DPC,E ;START DISK
4250 MOVE T,[-2000_4,,QRCBUF-1] ;DF10-C CHANNEL PROGRAM
4257 CONSZ 200000 ;IT'S INEFFICIENT, BUT WHAT THE HELL
4259 CONO DSK,%HOCLR+%HORAE+%HOATN+DSKCHN
4261 HRR A,E ;HEAD AND SECTOR (CYL DOESN'T CHANGE)
4263 MOVEI A,%HMRED+<RCICWA_6>
4265 PUSHJ P,RHSET ;START DISK
4267 MOVEM T,RDCPHS ;RDCPHS POSITIVE MEANS DOING RD/CMP NOW
4268 JRST DSKEX ;AWAIT COMPLETION
4270 ;;; READ-COMPARE COMPLETED. CHECK IT.
4271 QRC2: SPM PARPG ;SET UP MAP TO PAGE BEING READ/WRITTEN
4272 MOVEI T,600000+PMCSHM(A)
4273 DPB T,[.PAREP+EXEUMP]
4275 MOVEI H,0 ;H DIFFERENCE COUNT
4277 PUSH P,A ;WILL DO COMPARE LOOP IN ACS
4280 MOVSI E,-2000 ;E ADDRESS WITHIN PAGE
4281 MOVSI D,[ MOVE T,400000+PAREP*2000(E) ;A
4290 MOVSI E,-2000 ;E ADDRESS WITHIN PAGE
4291 MOVE T,400000+PAREP*2000(E)
4295 QRC3: JUMPGE E,QRC5 ;JUMP IF DONE
4296 JUMPG H,QRC4 ;COMPARE ERROR, REPORT IT
4299 MOVE T,-1(P) ;SAVED C
4300 BUG INFO,[DSK: READ-COMPARE ERROR #],DEC,NQCMPE(Q),[UNIT=],DEC,Q,[BLK=],OCT,QSGL(T)
4302 .ELSE BUG INFO,[DSK: READ-COMPARE ERROR #],DEC,NQCMPE(Q),[UNIT=],DEC,Q,[BLK=],OCT,QSGL(C)
4305 CAIG H,4 ;ONLY REPORT FIRST 4 BAD WORDS
4306 BUG INFO,[DSK: READ-COMPARE DIFFERENCE ],OCT,T,OCT,400000+PAREP*2000(E),OCT,QRCBUF(E)
4316 MOVEI T,0 ;CLEAR MAP
4317 DPB T,[.PAREP+EXEUMP]
4319 JUMPE H,QRC0 ;NO DIFFERENCE, I/O OPERATION IS DONE
4320 CAILE H,4 ;FAILED, DO IT ALL OVER AGAIN
4321 BUG INFO,[DSK: READ-COMPARE DIFFERENCES TOTAL],DEC,H
4325 QUFDWF: MOVE TT,QDWIP
4326 CAMN Q,MDSK ;WRITTEN TO MASTER DISK?
4327 SKIPN E,QSFBT(TT) ;AND HAVE SOME BLOCKS TO FREE?
4329 SETZM QSFBT(TT) ;YES, TRANSFER THEM TO QFBTS LIST
4330 MOVE T,E ;E FINDS LAST OF LIST, T RPLACD'D IN THERE
4331 EXCH T,QFBTS ;NCONC QSFBT ONTO FRONT OF QFBTS
4337 AOS NCORRQ ;WAKE UP CORE JOB IF QFBTS HAD BEEN EMPTY
4344 QTUTWF: AOS T,QSGL(C) ;NEXT BLOCK TO GO OUT
4345 AOS QSCABN(C) ;FROM NEXT CORE PAGE
4346 CAIGE T,MFDBLK ;SKIP IF DONE
4347 JRST QINT1E ;WRITE MORE
4351 QDWF: MOVSI E,(SETZ) ;UNLOCK DIR THAT WAS WRITTEN
4352 IOR E,DCHBT(Q) ;COPY ON THIS DISK IS NOW UP TO DATE
4355 HLLZS QSRAC(C) .SEE %QMIDL ;IDLE THE CHANNEL
4357 JRST QINT1A ;DON'T COUNT THIS AS DISK ACTIVITY
4359 QUDRIN: MOVE TT,QUDPR(C) ;USER DIR IN OK
4361 CAME D,QSNUD(TT) ;COMPARE UNAME IN DIR WITH RQ'ED
4363 TLO R,40000 ;NOT PAWED OVER
4367 MOVEI R,MU23UD ;USER DIRECTORY
4371 PUSHJ P,QDIRCK ;VERIFY NOT TOTALLY BASHED TO BEGIN WITH
4372 POP P,C ;CLOBBERS A,B,I
4374 QINTU4: DPB R,[MUR,,MEMBLT(A)]
4375 DPB TT,[MNUMB,,MEMBLT(A)]
4376 QTUTI1: SETOM QUSR(C) ;FREE THE DISK CHANNEL
4380 QMDRIN: TLO R,2 ;NOT RECONCILED
4381 MOVEM R,QMDRO ;MASTER DIRECTORY IN
4383 CAME TT,[SIXBIT /M.F.D./]
4384 BUG HALT,[MFD CLOBBERED]
4387 BUG HALT,[MFD HAS WRONG NUMBER OF DIRECTORIES]
4388 MOVE TT,(R) ;ASCENDING DIR #
4390 MOVEM TT,QAMDNO ;FIRST DISK IN STORE ASCENDING #
4391 MOVEI R,MU23MD ;MASTER DIRECTORY
4395 QTUTIN: AOS T,QSGL(C) ;NEXT BLOCK TO COME IN
4396 AOS QSCABN(C) ;INTO NEXT CORE PAGE
4397 CAIGE T,MFDBLK ;SKIP IF DONE
4398 JRST QINT1E ;READ MORE
4399 HRRZS QTUTO(Q) ;UNLOCK TUT, BUT QDPWF IS STILL SET
4402 QSWPFN: MOVE Q,QDSKN(C)
4404 JRST QSWPF2 ;SWAP READ ERROR (I HOPE)
4405 MOVSI E,MMPTMP ;PAGE NO LONGER IN TRANSIT
4407 BUG ;ALREADY WASN'T?
4411 PUSHJ P,IMEMR ;SWAP-OUT COMPLETE, RETURN MEMORY
4414 MOVSI E,MMPWOD ;PAGE HAS BEEN WRITTEN ON DISK. AND NO LONGER
4415 IORB E,@QSMMP(Q) ;BEING PAGED BEHIND.
4418 MOVE A,QSMMP(Q) ;WE'RE SUPPOSED TO RETURN THE MMP ENTRY
4420 QSWPF2: SETOM SWUSR(Q) ;SWAPPING IDLE
4424 ;SOME ERROR CHECKING
4427 JUMPE TT,QSWPF3 ;ON INITIAL-SWAP-IN, ADDRESS IN MMP IS SUPPOSED TO BE ZERO
4428 LDB TT,[$MMPUN,,(E)]
4434 QSWPF3: LDB TT,[MMMPX,,MEMBLT(A)]
4438 MOVEI TT,MURUSR ;SWAP IN OF PAGE COMPLETED
4439 DPB TT,[MUR,,MEMBLT(A)]
4443 JRST QSWPF2 ;CAN'T PUT IN MAPS IF CIRPSW NOT AVAILABLE.
4444 MOVSI D,(TDNE T,) ;SET UP CHECK USED BY PRIVELEGED USER FEATURE
4448 MOVE C,[2200,,MEMPNT(A)]
4449 PUSHJ P,PPIUM ;PUT PAGE INTO USERS' MAPS
4454 QWOVFN: CLEARM QSCRW(C) ;WRITE OVER SWITCH TO READ MODE
4457 HRRI D,%QMIDL ;TRYING TO CLOSE, STOP CHANNEL
4459 AOS QWBUFS ;COMPENSATE FOR EXTRA SOS BELOW
4461 QWRFIN: TLNN D,%QACTH ;WRITE COMPLETE, RETURN BUFFER
4471 QRD1FN: HLLZS QSRAC(C) .SEE %QMIDL ;BLOCK-AT-A-TIME READ COMPLETE, IDLE THE CHANNEL
4473 QRDFIN: MOVEI B,.BM MLO ;NORMAL READ COMPLETED
4474 ANDCAM B,MEMBLT(A) ;THREAD ONTO CHANNEL LIST
4477 DPB A,[MLO,,MEMBLT(B)]
4481 SKIPL B,QPIBSZ(C) ;GET BYTE COUNT OF BLOCK
4483 HRRZ B,1777(R) ;FUNNY BLOCK, GET FROM LAST WORD
4484 HRRZ TT,QSBYTE(C) ;AND MAKE SURE IT'S NOT TOO BIG
4488 QRDFN1: HRRZM B,MEMPNT(A) ;PASS TO MAIN PROGRAM
4490 IFE DMDSK, LDB B,[XWBLK QXWDS]
4491 .ALSO MOVEM B,QSLBLK(C)
4493 ;XFER COMPLETE, DEACTIVATE CHANNEL
4495 QINT1B: SETOM QACTTM
4496 QINT1A: SETOM QSGL(C)
4499 IFE DC10P, SETOM QSKT1(Q)
4514 ;ACTIVATE CHANNELS, LOOK FOR SEEKS AND TRANSFERS TO BE DONE
4517 SETOM QTUNT ;NO UNIT SELECTED YET
4518 IFN T300P, SETOM QTUNT1
4519 MOVE C,QTCHN ;START SCAN IN SUITABLE PLACE
4523 QINT2L: CAIGE C,NQCHN ;IF DIR-WRITE OR SWAP CHANNEL, DON'T CHECK QUSR
4525 SKIPGE D,QSRAC(C) .SEE %QALOK
4526 JRST QINT2C ;CHANNEL LOCKED OR NOT OPEN, SKIP IT
4529 JRST QINT4 ;JUMP IF CHANNEL ACTIVE ALREADY
4530 TLNE D,%QACTH+%QAOUT
4531 JRST QINT2C ;CHANNEL BLOCKED BY CORE JOB, DON'T ACTIVATE
4534 XCT .+1(D) ;INVOKE ACTIVATE HANDLER
4536 %QMIDL::JRST QINT2C ;IDLE - DON'T ACTIVATE
4537 %QMRD:: JRST QRDACT ;READ
4538 %QMWRT::JRST QWRACT ;WRITE
4539 %QMWOV::JRST QWRACT ;WRITE OVER
4540 %QMRD1::JRST QRDACT ;READ 1 BLOCK
4541 JRST 4,QINT2C ;ILL CODE
4542 %QMUDR::JRST QDRACT ;UFD READ
4543 %QMMDR::JRST QDRACT ;MFD READ
4544 %QMTTR::JRST QDRACT ;TUT READ
4545 %QMUDW::JRST 4,QINT2C ;UFD WRITE - SHOULDN'T LEAVE THIS MODE AROUND
4546 %QMMDW::JRST 4,QINT2C ;MFD WRITE - ..
4547 %QMTTW::JRST QINT5 ;TUT WRITE - MAY BE WRITING SECOND PAGE
4548 %QMSWP::JRST SWPACT ;SWAP
4549 JRST 4,QINT2C ;ILL CODE
4550 JRST 4,QINT2C ;ILL CODE
4551 JRST 4,QINT2C ;ILL CODE
4554 ; ACTIVATION ROUTINES
4556 SWPACT: SKIPL SWUSR(Q)
4557 BUG ;SWAPPING ALREADY ACTIVE ON THIS DISK
4560 MOVEI B,0 ;CHECK FIRST FOR SWAP IN OR OUT
4561 CAIGE A,6 ;ACCORDING TO AVAIL MEM
4563 SKIPN @SWAPL(B) ;IF NO TRAFFIC THAT DIRECTION, CHECK THE OTHER.
4566 JUMPE E,QINT2C ;NO SWAPPING TRAFFIC THIS DISK.
4567 LDB A,[MLO,,MEMBLT(E)] ;TAKE BLOCK OFF LIST
4569 SETZM @SWAPL(B) ;LAST BLOCK, LIST IS NOW EMPTY
4570 HRRM A,@SWAPL(B) ;SET NEW FIRST BLOCK
4571 LDB D,[MMMPX,,MEMBLT(E)]
4572 ADD D,MMPEAD ;GET MMP ADDRESS
4573 LDB TT,[410200,,(D)]
4575 BUG ;THIS PAGE SHOULD BE MARKED IN TRANSIT
4581 HRRZM E,QSCABN+NQCHN+1(Q)
4582 CLEARM SWUSR(Q) ;CHNL ACTIVE
4584 MOVEM E,QSGL+NQCHN+1(Q) ;DISK BLOCK
4585 HRRZS QSRAC+NQCHN+1(Q) .SEE %QMSWP
4586 MOVNM B,QSCRW+NQCHN+1(Q) ;DIRECTION
4587 CLEARM QERRS+NQCHN+1(Q) ;NO ERRORS (YET)
4588 JRST QINT4 ;CHANNEL SUCCESSFULLY ACTIVATED
4591 ; MORE ACTIVATION ROUTINES
4593 QRDACT: TLNE D,%QAACC ;ACTIVATE READ CHANNEL
4594 JRST QINT2C ;NOT IF USER HACKING RANDOM ACCESS NOW
4598 JRST QINT2C ;USER DIRECTORY OUT OR LOCKED
4601 AOS A ;A := TOTAL NUMBER OF BUFFERS
4602 CAMLE A,QRDAHD ;HOW MUCH SHOULD BE READ AHEAD
4603 JRST QINT2C ;BLOATED, DON'T ACTIVATE
4605 JRST QINT4A ;BLOCKS LEFT FROM LAST TIME
4606 QINT4B: PUSHJ P,QIDRCH ;GET NEXT DESC BYTE IN A, ALSO RET BYTE PNTR IN TT
4609 JUMPE A,QEOF ;REACHED READ EOF
4613 JRST QINT4D ;SKIP AND TAKE
4614 MOVEM A,QSBI(C) ;TAKE NEXT N
4617 QINT4G: MOVEM E,QSGL(C)
4619 ANDCAM B,QSRAC(C) ;CLEAR PROCESSING LAST BLOCK IN FILE BIT
4621 IMULI A,2000 ;NUMBER OF BYTES IN A FULL BLOCK
4623 MOVSI D,%QAFNY ;FUNNY FILE
4627 MOVEM A,QPIBSZ(C) ;SET FUNNY BIT
4629 JRST QINT4 ;IF MORE BLOCKS FOLLOW DON'T CHECK EOF
4630 PUSHJ P,QIDRCH ;GET NEXT DESCR BYTE
4631 SOS QDIRP(C) ;CORRECT PNTR
4633 MOVE A,QUDFPR(C) ;THIS IS LAST BLOCK
4635 LDB D,[UNBYTE+UNREF(A)]
4637 IMUL D,E ;NUMBER OF UNUSED BITS IN LAST WORD
4638 LDB E,[QSBSIZ(C)] ;(DEPEND ON DIVIDE ROUNDING DOWN)
4639 IDIV D,E ;NUMBER OF UNUSED BYTES (IN SIZE OPEN)
4640 LDB E,[UNWRDC+UNRNDM(A)];NUMBER OF USED WORDS IN LAST BLOCK
4643 IMULI E,@QSBYTE(C) ;CONVERT TO NUMBER OF BYTES
4644 SUB E,D ;NUMBER OF VALID BYTES IN BLOCK
4645 HRRM E,QPIBSZ(C) ;STORE BYTE COUNT OF LAST BLOCK
4646 IORM B,QSRAC(C) .SEE %QALBK
4650 QINT4D: MOVEI E,1-UDTKMX(A) ;SKIP N AND TAKE 1
4654 QWRACT: SKIPN I,QBFP(C) ;ACTIVATE WRITE CHANNEL
4655 JRST QINT2C ;END OF WRITE LIST FOR NOW
4657 LDB H,[MLO,,MEMBLT(I)]
4660 SETZM QBFP(C) ;LAST BLOCK, LIST NOW EMPTY
4665 QDRACT: MOVE E,QSLGL(C) ;ACTIVATE DIRECTORY-READ CHANNEL
4667 ; JRST QINT4 ;DROPS THROUGH
4669 QINT4: SKIPL QSCABN(C) ;SKIP IF NEED MEMORY
4671 PUSHJ P,IOMQ ;GET MEMORY FOR READ BUFFER
4673 QINT5A: MOVEM A,QSCABN(C)
4675 DPB D,[MUR,,MEMBLT(A)]
4676 DPB C,[MNUMB,,MEMBLT(A)]
4679 IFN DC10P, MOVE TT,QTRAN(Q)
4681 SKIPN QSEEK(TT) ;IGNORE SEEKING DRIVE
4682 SKIPGE QRCAL(TT) ;IGNORE RECALIBRATING DRIVE
4684 IFN T300P,[ ;IGNORE IF FOR CONTROLLER THAT IS NOT READY
4687 SKIPL QTUNT1 ;NOTE CODE HERE IS SIMILAR TO THAT AT QINT2F
4688 JRST QINT2C ;T-300 CONTROLLER BUSY OR ALREADY COMMITTED
4689 HRRZM Q,QTUNT1 ;WILL TRANSFER ON THIS UNIT
4690 HRRZM C,QTCHN1 ;FOR THIS CHANNEL
4691 JRST QINT2C ] ;T-300 CODE IS SIMPLIFIED SINCE NO SEEK OVERLAPS
4697 JRST QINT2F ;ALREADY SET FOR ME
4699 JRST QINT2C ;SET FOR SOME OTHER CHNL
4700 HRRZM C,QSKT1(TT) ;AVAILABLE, SET IT FOR ME
4701 PUSHJ P,QPOSR ;CONVERT DISK ADDRESS TO PHYSICAL
4702 IFN DC10P,[ ;AND INITIATE SEEK
4704 CONSZ DC0,DSSRUN+DSSACT
4708 MOVE TT,QTRAN(Q) ;PRETEND SEEK ALREADY COMPLETE
4711 JRST QINT2F ;DON'T WAIT FOR SEEK, START TRANSFER RIGHT AWAY
4714 TLO E,(DSEEKC) ;DSK SEEK
4721 JRST QINT2F ;IF WE'RE THERE, DON'T SEEK
4725 JRST QINT2C ;THIS ONE SEEKING, GO GET ANOTHER
4728 PUSHJ P,RHSLCT ; Select drive
4730 IOWRQ A,%HRADR ; Set track and sector
4732 IOWRQ A,%HRCYL ; Set cylinder
4734 JRST QINT2F ; On cylinder, don't seek
4737 PUSHJ P,RHCMD ; Start seeking
4739 JRST QINT2C ; Start other drives now?
4742 MOVSI A,%HRCYL(Q) ;STORE ADDRESS IN DRIVE
4748 HLRZ TT,E ;GET CYLINDER PART OF ADDRESS
4750 JRST QINT2F ;ON CYLINDER, DON'T SEEK
4752 MOVSI A,%HRDCL(Q) ;START SEEK
4756 JRST QINT2C ;THIS ONE SEEKING, START OTHER DRIVES
4760 ;CALL HERE TO SWEEP THE CACHE. CORE PAGE # IN R.
4761 ;INSTRUCTION AT CALL+1 SHOULD SKIP IF READING INTO CORE.
4762 ;CLOBBERS A,B,D,E,TT.
4764 CSHSWP: SETZB A,B ;A COUNTS WAIT TIME, B IS SWEEP INSTRUCTION
4766 TLOA B,(SWPUO (R)) ;WRITE - UNLOAD PAGE FROM CACHE
4767 MOVSI B,(SWPIO (R)) ;READ - CLEAR PAGE FROM CACHE
4768 LSH R,1 ;HARDWARE PAGES ARE 1/2 K
4769 XCT B ;SWEEP FIRST HALF-PAGE
4770 MOVE D,[CONSZ 200000]
4773 PUSHJ P,D ;WAIT IN ACS TO MINIMIZE MBOX INTERFERENCE
4774 AOS R ;SWEEP SECOND HALF-PAGE
4778 AOSA NCSHU ;COUNT NUMBER OF TIMES THIS DONE
4780 JRST [ ADDM A,NCSHUL ? JRST .+2 ]
4781 ADDM A,NCSHIL ;AND COUNT NUMBER OF LOOPS IN ACS
4786 ;VARIOUS EXITS FROM CHANNEL-CHECKING ROUTINES
4788 QINT2F: SKIPL QTUNT ;THIS CHANNEL IS READY TO TRANSFER
4789 JRST QINT2C ;ALREADY FOUND A TRANSFER
4790 HRRZM Q,QTUNT ;WILL TRANSFER ON THIS UNIT
4791 HRRZM C,QTCHN ;FOR THIS CHANNEL
4792 QINT2C: CAMN C,QLCHN ;CONTINUE CHANNEL SCAN
4793 JRST QINT2E ;UNLESS CHECKED ALL CHANNELS
4794 QINT2D: CAIL C,NQCHN+1+NQS-1 ;SKIP IF NOT TIME TO WRAP AROUND
4796 AOJA C,QINT2L ;CHECK ANOTHER
4801 SKIPL Q,QTUNT1 ;FOUND XFER FOR T-300?
4804 SKIPGE Q,QTUNT ;FOUND XFER?
4807 ;Q DISK TO TRANSFER ON, C CHANNEL. START (OR RESTART) TRANSFER ON THEM.
4808 QDE1: MOVE R,QSCABN(C)
4817 IFE T300P, MOVEM C,QSDCH
4824 SKIPGE B,QSCRW(C) ;LOAD R/W STATUS IN B
4829 QINT6A: IORI T,7000+QICWA ;DON'T STOP FOR PARITY ERRORS (PLUS INITIAL CHNL ADR)
4831 DPB Q,[DUNFLD+QCHPRG]
4833 DPB R,[121000,,QIOWD]
4834 LDB E,[100300,,R] ;MA15-17
4836 DPB E,[410300,,QIOWD] ;SET UP HIGH ADDR BITS.
4849 CONO DPC,175700+DSKCHN
4851 SETZM RDCPHS ;ASSUME NO READ-COMPARE WANTED
4853 SETOM RDCPHS ;REMEMBER TO READ-COMPARE LATER
4862 BUG ;DONT DO ANYTHING IF NOT WHERE YOU SHOULD BE
4864 DATAO DPC,QCHPRG ;ENTRY ON OVERRUN
4879 QHUNG: CONO DPC,DCLEAR+20+DSKCHN ;DISK NOTICED TO BE HUNG, RESET IT
4880 SETOM QHUNGF ;TELL P.I. LEVEL TO RETRY OPERATION
4883 BUG INFO,[DSK: HUNG ON UNIT ],DEC,QSDU,[QCHPRG=],OCT,QCHPRG
4890 QINT6A: MOVEM T,QCHPRG
4892 LSH R,1 ; Set up Unibus map for RH11 to point at
4893 TRO R,%UQVAL+%UQFST ; the block in question.
4894 IOWRQ R,UBAPAG+QUBPG_1
4896 IOWRQ R,UBAPAG+QUBPG_1+1
4897 MOVE E,[-4000,,QUBPG_14]
4902 QOVR: IORDQ TT,%HRCS1 ; Enter here to recover from PI level lossage
4907 QECCX: ;; Enter here from ECC correction code
4908 PUSHJ P,RHCLRC ; Clear controller errors and select drive
4911 JRST DSKEX ; Punt if not positioned in right place
4912 IOWRQ TT,%HRCYL ; Store cylinder in drive
4914 IOWRQ TT,%HRADR ; Store track and sector
4916 IOWRQ TT,%HRWC ; Store halfword count
4918 IOWRQ TT,%HRBA ; Store Unibus base address
4934 QHUNG: MOVEI A,%HYCLR ; Sock controller in jaw
4937 PUSHJ P,RHSLCT ; Select drive
4938 PUSHJ P,RHCLRD ; Redundantly clear drive
4941 BUG INFO,[DSK: HUNG ON UNIT #],DEC,QSDU,[ADDR=],OCT,QCHPGA
4949 QINT6A: IORI T,QICWA_6 .SEE $HCICWA
4953 LSH R,10. ;ASSEMBLE DF10-C CONTROL WORD
4962 QOVR: CONSZ DSK,20 ;ENTER HERE FOR RECOVER FROM PI HALT, OVERRUN
4968 QECCX: SETZM QICWA+1 ;ENTER HERE FROM ECC CORRECTION CODE
4969 CONO DSK,%HOCLR+%HORAE+%HOATN+DSKCHN
4972 JRST DSKEX ;DONT DO ANYTHING IF NOT WHERE YOU SHOULD BE
4973 MOVSI A,%HRCYL(Q) ;STORE ADDRESS IN DRIVE
4982 SETZM RDCPHS ;ASSUME NO READ-COMPARE WANTED
4984 SETOM RDCPHS ;REMEMBER TO READ-COMPARE LATER
4999 QHUNG: CONO DSK,%HOCLR+%HORST+%HOSTP+DSKCHN ;HUNG, CLEAR CONTROLLER
5004 HRRI A,%HMCLR ;CLEAR DRIVE
5006 BUG INFO,[DSK: HUNG ON UNIT ],DEC,QSDU,[ADDR=],OCT,QCHPGA
5012 QINT6A: MOVEM T,QCHPRG
5014 DPB R,[DCBN+QCHPR2] ;MEM BLOCK #
5015 DPB R,[DCBN+QCHPR3] ;FOR POSSIBLE READ COMPARE
5017 PUSHJ P,QPOSR ;QPOSR ALSO STORES MAPPED UNIT IN QCHPRG
5019 CLEARM QCHPR4 ;STORE DHALT FOR NO RCC
5021 JRST QINT6S ;SWAPPING CHNL
5025 CAIE C,NQCHN ;ALWAYS R COMPARE DIR WRITES
5026 SKIPLE QRCSW ;SKIP ON NOT READ COMP EVERYTHING
5029 JUMPL B,QINT6B ;RCC WRITES
5033 JRST QINT6C ;NOT DIR READ
5034 QINT6B: TLZ E,340000 ;CHANGE TO READ COMPARE
5036 QINT6C: SETOM QERS1 ;ERR VERIFY IND
5037 QOVR: CONSZ DC0,DSSRUN+DSSACT
5039 DATAO DC0,[DJMP QCHPRG] ;ENTRY ON OVERRUN
5040 QOVR1: CONO DC0,DCSET+DCIENB+DSKCHN ;INTERRUPT WHEN DONE
5048 JUMPL B,QINT6B ;RCC WRITES
5049 JRST QINT6C ;NOT READS
5051 QHUNG: CONO DC0,DCCSET+DSKCHN ;HUNG, CLEAR CONTROLLER
5055 BUG INFO,[DSK: HUNG ON UNIT ],DEC,QSDU,[QCHPRG=],OCT,QCHPRG
5060 MOVE T,[QXWDS-1,,QXWDS]
5063 JRST QNT6W2 ;SWAP OR DIR WRITE
5066 MOVEM T,QXWDS+XWSYSN
5075 LDB T,[MWC,,MEMBLT(R)]
5079 IFN DC10P, MOVSI T,(DWRITE)
5080 IFN RP10P, MOVSI T,(DWRITC)
5081 IFN RH10P, MOVEI T,%HMWRT
5082 IFN RH11P, MOVEI T,%HMWRT
5086 T3IO: MOVEM C,QSDCH1 ;THIS IS MORE OR LESS QINT6A FOR T-300
5091 T3IO1: MOVE R,QSCABN(C) ;RE-ENTER HERE TO RETRY WITH COMMAND IN A
5092 LSH R,10. ;FIRST ADDRESS IN TRANSFER
5093 TLO R,730000 ;12-BIT BYTES, START WITH FIRST BYTE IN WORD
5094 MOVSI E,-4 ;SET UP BYTE POINTERS
5098 MOVE D,QSGL(C) ;DO LIKE QPOSR
5119 ;START T-300, COMMAND IN A, DRIVE IN Q
5120 T3CMD: MOVEI TT,2561
5130 CONO DLC,100040+TTYCHN ;INTERRUPT 11
5133 QHUNG1: MOVE Q,QSDU1
5135 BUG INFO,[DSK: HUNG ON T-300 UNIT ],DEC,QSDU
5136 MOVEI TT,5*60.*30. ;SHUT UP FOR FIVE MINUTES
5142 IFN RP10P, PUSHJ P,QERSOFT
5143 IFN DC10P, AOSE PKIDM
5148 JRST .+3 ;GET CKS ERR
5150 AOS NQCMPE(Q) ;# COMPARE ERRORS [WITH NO OTHER ERROR]
5152 IFN T300P,T3DE: ;ENTER HERE FOR ERROR ON T-300
5157 IFN DC10P, JUMPL R,QERV1 ;DO ANOTHER RD/COMP TO SEE IF OK ON DSK (IF WRITE)
5158 QERV2: AOS R,QERRS(C)
5159 TRNN R,10 ;TRY 8 TIMES BEFORE AND AFTER REPOSITION
5162 JRST QDE2 ;TRY REPOSITION ONCE
5163 QERV3: MOVE D,QSRAC(C)
5166 XCT .+1(D) ;INVOKE IRRECOV ERROR HANDLER
5168 %QMIDL::JRST 4,QERV+. ;IDLE CHANNELS SHOULDN'T GET HERE
5169 %QMRD:: JRST QPE2D ;USER DATA
5170 %QMWRT::JRST QDE1 ;WRITE KEEP TRYING
5171 %QMWOV::JRST QDE1 ;..
5173 JRST 4,QERV+. ;ILL CODE
5181 JRST 4,QERV+. ;ILL CODE
5182 JRST 4,QERV+. ;ILL CODE
5183 JRST 4,QERV+. ;ILL CODE
5186 QSWPER: SKIPGE CIRPSW ;TRY XFER AGAIN IF CIRPSW NOT AVAILABLE
5188 JRST QDE1 ;DON'T TRY TO DO ANYTHING ABOUT WRITE ERRORS
5189 MOVE A,QSCABN(C) ;READ - GIVE ALL USERS OF PAGE PARITY ERR
5192 MOVE C,[2200,,MEMPNT(A)]
5195 LDB Q,[2200,,MEMPNT(A)]
5196 DPB Q,C ;REMOVE MEM FROM LOOP
5197 PUSHJ P,IMEMR ;AND GIVE BACK MEM
5198 POP P,Q ;ALTERNATIVELY, COULD LEAVE THE MEM BUT SET MMPBAD
5199 POP P,C ;TO INDICATE THAT THAT MEM COPY OF THE PAGE IS NO GOOD.
5201 DPB D,[410200,,@QSMMP(Q)] ;PAGE IS OUT
5211 JRST QERV2 ;NOT SET FOR RCC
5213 QERL2: CONSZ DC0,DSSRUN+DSSACT
5215 DATAO DC0,[DJMP QCHPR4]
5229 MOVEM R,QERRS(C) ;CLOBBER QERRS
5230 JRST QREC ;AND TRY REPOSITIONING
5233 QERSOFT:LDB A,[DCYL+QCHPRG] ;PARSE STARTING DISK ADDRESS
5234 LDB B,[DCYLXB+QCHPRG]
5237 LDB B,[DSURF+QCHPRG]
5238 LDB D,[DSECT+QCHPRG]
5239 SKIPN QERRS(C) ;PRINT ONLY ONCE, NOT ON RETRIES
5240 BUG INFO,[DSK: SOFT ERR UNIT ],DEC,Q,[CYL ],DEC,A,[STARTING HEAD ],DEC,B,[SEC ],DEC,D,[CONI=],OCT,QERST,[DATAI=],OCT,QERDTI
5244 BUG INFO,[DSK: SEEK ERR DATAO=],OCT,QSEEK(Q),[CONI=],OCT,A,[DATAI=],OCT,E
5250 IFN RP10P, PUSHJ P,QERSOFT
5253 IFN T300P,T3HE: ;ENTER HERE FOR ID ERROR ON T-300
5261 JRST [ SETOM QRCAL(Q)
5264 MOVEM Q,QSDU1 ;CONTROLLER IS TIED UP BY RECAL BECAUSE
5265 JRST QINT1 ] ;IT'S TOO DAMNED PSEUDO-INTELLIGENT
5269 QREC0: DPB TT,[DUNFLD+QRECAL]
5275 MOVEI T,10. ;5-SECOND RECALIBRATE TIMEOUT
5278 CONO DC0,DCSET+DCATEB+DSKCHN ;ENABLE ATTENTION
5281 DPB Q,[DUNFLD+QRECAL]
5286 SETOM QRCAL(Q) ;INDICATE RECALIBRATING THIS DISK
5290 PUSHJ P,RHSLCT ; Select drive
5291 PUSHJ P,RHCLRD ; Clear errors
5293 PUSHJ P,RHCMD ; Recalibrate
5303 PUSHJ P,RHSET ;CLEAR ERROR OUT OF DRIVE.
5305 HRRI A,%HMREC ;RECALIBRATE
5306 PUSHJ P,RHSET ;MAYBE SHOULD TRY OFFSET FIRST?
5314 JRST QINT1 ;LOOK FOR SOME OTHER TRANSFER
5316 QHE2: SKIPL QSCRW(C) ;HANG UP OR POSITIONING ERR (AFTER 5 TRIES)
5317 JRST QERV3 ;IF READ, PERFORM RECOVERY
5319 QPE2D: MOVSI R,%QAPAR ;IRRECOVERABLE ERROR
5323 MOVEM D,QIRCBK ;BLOCK # AT IRRCV ERR
5324 MOVEM Q,QIRUNT ;SAVE UNIT TOO
5326 AOS NIRSWE ;# IRRCV SWAPPING ERRS
5329 JRST QPE2E ;DON'T MESS WITH LOCKED TUT
5331 CAIN B,TUTLK ;PRINT MESSAGE IF NOT YET LOCKED OUT
5335 QPE2E: BUG INFO,[DSK: IRREC DATA ERR #],DEC,QIRRCV,[UNIT=],DEC,QIRUNT,[BLK=],OCT,QIRCBK
5338 QUDER1: MOVEI R,1(Q) ;TRY TO READ DIR FROM OTHER DISKS
5343 JRST QDE1 ;NO OTHER DISK AVAIL TO READ FROM, TRY AGAIN
5345 QUDER4: SKIPGE QACT(R)
5347 HRRZM R,QDSKN(C) ;TRY THIS DISK
5350 JRST [ SETOM QSDU1 ;FREE DRIVE FORMERLY HACKING
5354 IFE DC10P, SETOM QSKT1(Q) ;FREE DRIVE FORMERLY HACKING
5367 QIDRCH: MOVE TT,QDIRP(C) ;CHNL IN C PNTR TO QSNUD IN J LOAD NEXT CHR INTO A
5368 AOS QDIRP(C) ;ALSO RET BYTE PNTR IN TT
5376 QMPDCH: MOVE TT,QDIRP(A) ;CHNL IN A PNTR TO QSNUD IN H LOADS NEXT CHR IN R
5377 AOS QDIRP(A) ;USED AT M.P. LEVEL
5378 QMPDC1: IDIVI TT,UFDBPW ;ALSO RETN BYTE PNTR IN TT
5385 ;REACHED EOF ON READ
5386 QEOF: SOS QDIRP(C) ;AVOID GC UNHAPPINESS
5389 HLLZS QSRAC(C) .SEE %QMIDL ;IDLE THE CHANNEL
5390 AOS QSBFS(C) ;TO UNHANG M.P. WHICH IS WAITING FOR BUF TO APPEAR
5397 TRZE A,20 ; FUNNY FILE BLOCK
5398 IORM E,QSRAC(C); INDICATE SO
5409 ;DECODE UNBYTE SPEC IN D.
5410 ;RETURNS BYTE SIZE IN D, NUMBER OF UNUSED BYTES IN LAST WORD IN E.
5412 JRST [ IDIVI D,100 ? POPJ P, ]
5414 JRST [ IDIVI D,20 ? POPJ P, ]
5416 JUMPGE D,[ IDIVI D,4 ? POPJ P, ]
5421 ;ENCODE BYTE SIZE IN Q AND RESIDUE IN R INTO UNBYTE SPEC IN RH(Q)
5423 JRST [ IMULI Q,100 ? ADDI Q,400(R) ? POPJ P, ]
5425 JRST [ IMULI Q,20 ? ADDI Q,200(R) ? POPJ P, ]
5427 JRST [ IMULI Q,4 ? ADDI Q,44(R) ? POPJ P, ]
5432 JRST QINT3X ;DIR CHNL IN USE
5434 SKIPGE QSDU ;DON'T GET PAST HERE UNLESS BOTH CONTROLLERS ARE IDLE
5442 SKIPG QACTTM ;LAST ACTIVITY TOO RECENT
5450 QMDW: SKIPGE QACT(Q)
5451 JRST QMDWA ;UNIT NOT ACTIVE
5455 HRLI Q,(SETZ) ;INDICATE MFD WRITE IN PROGRESS
5459 HRRZM TT,QSRAC+NQCHN
5463 CAME C,[SIXBIT /M.F.D./]
5464 BUG HALT,[MFD CLOBBERED]
5475 MOVEM TT,QSCABN+NQCHN
5482 QTDW1: SKIPGE QACT(Q)
5491 MOVE TT,TIME ;DON'T WRITE TUTS TOO OFTEN
5492 SUB TT,QTWRTM(Q) ;BECAUSE THE TUT IS LOCKED WHILE IT'S BEING WRITTEN
5500 HRRZM TT,QSRAC+NQCHN
5503 MOVE H,QPKNM(Q) ;VERIFY THAT TUT IS NOT BEING CLOBBERED
5507 BUG HALT,[TUT ],DEC,Q,[CLOBBERED]
5509 MOVEI TT,MFDBLK ;INITIATE WRITING OF FIRST BLOCK OF TUT
5512 LDB TT,[121000,,QTUTO(Q)]
5513 MOVEM TT,QSCABN+NQCHN
5516 QTDWA1: ANDCAM J,QTUTO(Q)
5517 QTDWA: AOBJN Q,QTDW1
5519 QDW4A: MOVE J,QACTB ;BITS CORRESP TO ACTIVE DISKS
5520 QDW4: SKIPE TT,QSNUD(C)
5522 JRST QDW3 ;SLOT VACANT OR LOCKED
5524 JRST QUDW1 ;NEEDS TO BE WRITTEN ON SOME UNIT
5526 QINT3X: ;HERE IF DISK GOING IDLE. CLEAR DONE FLAG.
5527 ;IN 2-CONTROLLER CASE, MAKE SURE WE ONLY DO IT TO THE RIGHT CONTROLLER.
5530 JRST DSKEX ;STUFF NEEDS TO BE DONE BUT CANT NOW
5532 IFN DC10P, CONO DC0,DCCLR+DCIENB+DSKCHN
5533 IFN RP10P, CONO DPC,177710+DSKCHN ;MUST CLEAR "DONE"
5534 IFN RH10P, CONO DSK,%HOCLR+%HOATN+%HORAE+DSKCHN
5535 IFN RH11P, ;; RH11 doesn't need this?
5536 JRST DSKEX ;STUFF NEEDS TO BE DONE BUT CANT NOW
5538 QUDW1: MOVSI J,%QUDWM ;WRITE RIGHT AWAY IF %QUDWM IS ON
5540 SKIPE QSFBT(C) ;OR DISK BLOCKS (AND CORE) WAITING TO BE FREED
5542 SKIPG QACTTM ; ACTIVITY TOO RECENT
5543 SKIPN QSNNR(C) ; THEN ONLY WRITE IF NOTHING POINTING TO DIRECTORY
5547 QUDW4: SKIPGE QACT(Q)
5552 QUDW3: AOBJN Q,QUDW4
5555 QUDW6: ANDCAM J,QSNLCN(C) ;TURN OFF %QUDWM
5556 MOVE Q,MDSK ;AND WRITE ON MASTER DISK (ASSUME MDSK IS ACTIVE AND BIT IN QSNLCN IS SET)
5559 TLNE I,40000 ;IS THIS CODE OBSOLETE? LEFT FROM DAYS OF 1 MFD PER DRIVE?
5560 JRST QUDW2B ;MASTER DIR NOT IN
5562 CAMN Q,MDSK ;SKIP IF NOT WRITING ON MASTER DISK
5563 PUSHJ P,QDIRCK ;BLESS THIS UFD!!!
5565 IORB TT,QSNLCN(C) ;LOCK USER DIRECTORY
5568 MOVE A,1(TT) ;NAME AREA PTR
5570 CAMN J,UDNAME(TT) ;MAKE SURE NOT ABOUT TO WRITE BAD DIRECTORY
5576 CAMLE J,A ;FS PTR BAD?
5584 MOVEM TT,QSCABN+NQCHN
5589 QUDW2B: ANDCAM J,QSNLCN(C) ;CLEAR BIT + GO AWAY
5592 ;GENERALLY GET HERE BY JSP TT,
5593 QUDCLB: BUG HALT,[DIR ],OCT,C,SIXBIT,QSNUD(C),[CLOBBERED]
5595 QDIRCK: PUSH P,TT ;CHECKS FILES FOR REASONABLE DESCRIPTORS -
5596 ; PRECEDING BYTE =0, FIRST BYTE NOT=0
5598 MOVEI B,1777(A) ;END OF NAMES
5599 ADD A,1(A) ;BEGIN NAMES
5603 JRST QDIRC2 ;0 NAME=NO FILE
5604 LDB TT,[1500,,UNRNDM(A)] ;DESC PTR
5605 SOS TT ;TRICK - IF DESC PTR = 0 LDB BELOW GETS 0 BECAUSE P FIELD = 44
5607 HLL TT,SBTBL(I) ;BYTE POINTER
5608 ADDI TT,UDDESC-1777(B)
5613 QDIRC2: ADDI A,LUNBLK
5618 BUG ;TOO BIG EVEN FOR RP03
5650 IFE DMDSK, .ERR CHANGE QPOSR FOR 9-SECTOR BLOCKS!
5654 HRLZ D,E ;CYLINDER IN LH
5660 IOR E,D ;SURFACE IN 1.9-2.4
5661 IOR E,TT ;SECTOR IN 1.1-1.5
5679 DPB TT,[DUNFLD+QCHPRG]
5685 QPOSRI: MOVE TT,QTRAN(Q) ;NEED PACK ID BEFORE PROCEEDING
5686 DPB TT,[DUNFLD+GPKID]
5692 MOVEM A,QPOS(TT) ;WILL SEEK TO HERE AUTOMATICALLY
5694 DATAO DC0,[DJMP GPKID]
5699 QSPKID: CONSZ DC1,1777
5701 LDB TT,[DPKID+RPKID]
5707 SUBTTL DISK IOT ROUTINES
5709 OVHMTR UUO ;MORE RANDOM UUOS
5711 ;BECAUSE .ACCESS MERELY DROPS ITS ARG IN A VARIABLE AND SETS %QAACC,
5712 ;ALL IOT ROUTINES MUST TEST %QAACC AND DO THE REAL WORK OF CHANGING
5713 ;THE ACCESS POINTER IF NECESSARY.
5725 TLNE T,%QAACC+%QALNK
5726 PUSHJ P,QBWRA1 ;RANDOM ACCESS MODE HACK
5730 JSP B,CPOPJ ;TRANSFER TO CHRKT, SIOKT, OR BLKT
5731 QBOV: SETZ QSMPRP(A)
5743 QUAI: MOVEI T,CHRKTI
5747 TLNE T,%QAACC+%QALNK
5751 JSP B,CPOPJ ;TRANSFER TO CHRKTI, SIOKT, OR BLKT
5759 QBWRA1: TLNE T,%QALNK
5761 LDB T,[$QAMOD,,QSRAC(A)] ;SET RANDOM ACCESS PNTRS ON WRITE
5762 SOJN T,QBWRA2 ;IN ORDINARY WRITE MODE
5763 SKIPGE QSCRW(A) ;WAIT FOR CHANNEL TO BECOME IDLE OR HANG UP IN READ
5764 PUSHJ P,UFLS ; WAITING FOR %QAACC TO TURN OFF
5769 MOVE T,QRADAD(A) ;DESIRED ADDRESS
5770 SUB T,QFBLNO(A) ;ACTUAL ADDRESS OF BEG OF CURRENT BUFFER
5771 JUMPL T,QBWRA2 ;XFER ON BEFORE CURRENT BLOCK
5773 SUB T,QMPBSZ(A) ;SIZE OF CURRENT BUFFER IN BYTES
5774 JUMPL T,QBWRA3 ;SAME BLOCK AS NOW
5778 PUSHJ P,QSOCL5 ;CLEAR ANY CURRENT BUFFERS ETC
5781 PUSHJ P,QFNTR ;LOCKS DIR IF SKIPS
5782 JRST QBWRA4 ;OFF END OF FILE
5783 QBWRA5: PUSHJ P,QUDULK
5787 CLEARM QSCRW(A) ;SWITCH TO WRITE OVER MODE
5788 MOVSI Q,%QAMPU+%QAMWO ;SET UPDATE ADR AND WRITE OVER
5791 MOVSI Q,%QAEFR+%QAEFW+%QAACC ;CLEAR EOF, WRITE EOF, AND ACCESS FLAGS
5793 MOVEI Q,%QMRD1 ;AND READ IN THE CURRENT BLOCK
5797 QBWRA4: JUMPE Q,QBWRA0
5798 CAME J,Q ;MIGHT BE ADDING TO END OF FULL BLOCK
5802 QBWRA0: PUSHJ P,QLWO ;OFF END OF FILE AND WAS ACCESSING WD 0
5803 MOVSI C,%QAACC ;SO SWITCH TO NORMAL WRITE MODE AND
5804 ANDCAM C,QSRAC(A) ;TURN OFF RANDOM ACCESS BIT
5810 QBWRA3: SKIPGE TT,QSMDN(A)
5811 BUG ;NO BUFFER REALLY ACTIVE AT M.P.
5815 ANDCAM J,QSRAC(A) ;WAS WRITING IN LAST BLK PAST EOF,
5816 MOVN D,QSMPRC(A) ; UPDATE ACTIVE BYTE COUNT
5817 ADDM D,QMPBSZ(A) ;DECREASE SIZE OF BUFFER TO AMT ACTUALLY WRITTEN
5818 QBWRA7: LSH TT,10. ;ADDRESS OF BUFFER
5819 MOVE T,Q ;SAVE RELATIVE BYTE ADDR WITHIN BUFFER
5820 IDIVI Q,@QSBYTE(A) ;Q = WDS, J = BYTES
5821 ADD TT,Q ;ADDRESS OF DESIRED WORD
5822 HLL TT,QSBYTE(A) ;BYTE POINTER TO FIRST BYTE IN THAT WORD
5823 JUMPE J,.+3 ;ADVANCE TO APPROPRIATE BYTE
5827 SUB T,QMPBSZ(A) ;MINUS # BYTES LEFT IN BLOCK
5829 QBRRA4: MOVSI Q,%QAACC
5833 QSKFRC: MOVN B,QSMPRC(A)
5834 ADD B,QMPBSZ(A) ;NUMBER OF BYTES WRITTEN IN BLOCK
5838 JRST [MOVEM B,QMPBSZ(A) ;IS LAST BLOCK, CHANGE LENGTH
5839 PUSHJ P,QOCLPD ;AND PAD IT (GUARANTEED NO-OP IF WORD MODE CHNL)
5841 SETZM QSMPRC(A) ;BUFFER WILL BE DISPOSED OF
5844 SETZB B,E ;NO BUFFER AFTER ALL
5845 ADD B,QFBLNO(A) ;CURRENT POSITION IN FILE
5848 MOVEM B,QRADAD(A) ;ACCESS BACK ON NEXT IOT
5850 PUSHJ P,[TLNE C,%QAWOV ;WRITE OUT THE BUFFER
5855 PUSHJ P,QOCL2 ;STORE QMPTC IF NECESSARY
5856 IORM E,QSNLCN(H) ;WRITE OUT DIR FAST IF CHANGED
5860 ;.CALL FINISH ON DISK OUTPUT CHANNEL
5861 QSKFIN: HRRZ T,QSRAC(A)
5862 CAIN T,%QMWOV ;IF WRITE-OVER MODE
5863 JRST [ SKIPE QSCRW(A) ;THEN WAIT FOR IT TO SWITCH TO READ MODE
5866 CAIN T,%QMWRT ;IF WRITE MODE
5867 JRST [ SKIPE QSBFS(A) ;THEN WAIT FOR ALL BUFFERS TO GET WRITTEN
5871 MOVE T,MDSK ;HAS THE DIR BEEN CHANGED AND NOT WRITTEN
5872 MOVE T,DCHBT(T) ;YET TO THE MASTER DISK?
5875 MOVSI TT,%QUDWM ;YES, WRITE IT OUT IMMEDIATELY
5876 IORM TT,QSNLCN(H) ;AND DON'T RETURN UNTIL IT IS WRITTEN
5881 QBRRA1: TLNE T,%QALNK
5884 JRST QBRRA2 ;NO MAIN PRGM BUFFER
5889 SUB T,QMPBSZ(A) ;SIZE OF CURRENT BUFFER
5890 JUMPL T,QBRRA3 ;SAME BLOCK AS NOW
5894 PUSHJ P,QICLW1 ;STOP THE CHANNEL AND FLUSH CURRENT BUFFERS
5896 CLEARM QSBFS(A) ;FLUSH POSSIBLE EXTRA AOSES WHEN PI HIT EOF
5899 JRST QBRRA5 ;OFF END OF FILE (DIR ALREADY UNLOCKED)
5905 IORM Q,QSRAC(A) ;SET FLAG TO SET QSMPRP AND QSMPRC ON NEXT BUFFER LOAD
5906 MOVSI Q,%QAEFR+%QAACC ;CLEAR EOF AND .ACCESS FLAGS
5908 MOVEI Q,%QMRD ;START READING AGAIN
5916 JRST IOCER2 ;ACCESS OFF END OF FILE IS ERROR
5917 MOVSI TT,%QAEFR ;BUT ACCESS TO EXACTLY EOF IS OK
5918 IORM TT,QSRAC(A) ;IMITATES WHAT QEOF DOES
5920 SETZM QSMPRC(A) ;AND READS ZERO WORDS
5923 QBRRA3: SKIPGE TT,QSMDN(A)
5927 ;BLKT-SIOKT-CHRKT GET BUFFER ROUTINE FOR WRITE-OVER MODE.
5928 QWOG1: SKIPGE QSCRW(A) ;FETCH BLOCK WRITEOVER MODE
5929 JRST QWOG2 ;STILL WRITING PREVIOUS ONE, WAIT
5930 MOVEI Q,%QMRD1 ;SWITCH INTO READ MODE
5931 SKIPG QSBFS(A) ;IF A BUFFER HAS TO BE READ
5936 ;BLKT-SIOKT-CHRKT GET-BUFFER ROUTINE FOR DISK INPUT.
5937 QSBGB: MOVSI Q,%QAPAR
5942 JUMPE Q,[MOVSI J,%QAEFR ;SAID TO BE BUFFERS, BUT NONE THERE
5944 BUG ;SHOULDN'T HAPPEN EXCEPT AT EOF
5946 LDB J,[MLO,,MEMBLT(Q)]
5949 SETZM QBFP(A) ;LAST BLOCK, LIST NOW EMPTY
5950 HRRZ J,MEMPNT(Q) ;GET SIZE OF BUFFER IN BYTES
5952 LDB TT,[$QAMOD,,QSRAC(A)]
5953 SKIPN TT ;DONT SOS IF IN WRITE OVER MODE
5956 LSH TT,10. ;RETURN ADDR OF BUFFER
5963 MOVE Q,QRADAD(A) ;DIDDLE PNTRS TO TAKE CARE OF RANDOM ACCESS WITHIN BLOCK
5964 SUB Q,QFBLNO(A) ;DESIRED OFFSET WITHIN BLOCK
5966 JUMPL J,IOCER2 ;OFF END OF FILE
5967 JUMPL Q,IOCER2 ;OFF FRONT OF FILE (NEGATIVE .ACCESS PNTR)
5970 ADD TT,Q ;ADJUST BYTE POINTER
5975 MOVSI Q,%QAMPU ;NOW IS SAFE TO TURN OFF FLAG
5979 ;GET-BUFFER DETECTED EOF ON INPUT OR WRITE-OVER.
5980 QSBGB5: CONO PI,UTCON
5984 LDB Q,[$QAMOD,,QSRAC(A)]
5985 SOJN Q,POPJ2 ;ON INPUT, SKIP TWICE TO SIGNAL EOF.
5986 PUSHJ P,QLWO ;LEAVE WRITE OVER MODE
5987 JRST QSBWG ;START NORMAL WRITE
5989 QWOG2: SKIPGE QSCRW(A) ;WAIT FOR WRITE TO FINISH
5991 JRST POPAJ ;NOW RECYCLE AND WAIT FOR READ
5993 ;LEAVE WRITE OVER MODE
5994 QLWO: MOVE H,QUDPR(A)
5997 SETZM QBFP(A) ;WRITEOVER MODE EXTEND FILE (SWITCH TO NORMAL MODE)
6001 HRRZM Q,QMPTN(A) ;STORE BASE TRACK
6002 MOVSI Q,%QAEFR+%QAMWO ;CLEAR EOF AND WRITEOVER
6004 MOVEI Q,%QMWRT ;NORMAL WRITE MODE
6006 CLEARM QMPTC(A) ;TRACK COUNT FOR TAKE N
6007 SETOM QMTTR(A) ;NO TRACK RESERVED
6008 SETOM QMFTP(A) ;GET NEW DECADE RESERVATION
6010 MOVE TT,QDIRP(A) ;SEE IF GARBAGE COLLECTION NEEDED
6013 PUSHJ P,QMPDC1 ;CONV CHAR ADR TO BYTE PNTR (AND LDB IN R)
6020 JRST QLWO1 ;DON'T NEED TO EXPAND F.S.
6025 JRST QSBWG7 ;DON'T HAVE ROOM. GC
6026 MOVEI R,3*6 ;HAVE ROOM
6035 QSBWG7: MOVSI R,%QAFUL ;NO ROOM, GC BEFORE COMMITTING NEXT TRACK
6040 QSBGB2: ANDCAM Q,QSRAC(A) ;DISK READ ERROR
6041 JRST IOCER3 ;TELL USER
6043 ;DISK OUTPUT GET-BUFFER ROUTINE. PRESERVES D FOR BENEFIT OF PDUMP.
6044 QSBWG: MOVE Q,QSRAC(A)
6045 TLNE Q,%QALNK+%QAACC ;DON'T WRITE TO LINK, DON'T LET PDUMP GET
6046 JRST IOCR10 ; FAKED OUT BY USE FORCE OR ACCESS
6049 JRST QWOG1 ;JUMP IF WRITE OVER MODE
6050 HRRZ Q,QBFP(A) ;NORMAL MODE
6051 JUMPE Q,QSBWG1 ;CAN ALWAYS HAVE ONE BUFFER
6054 JRST POPAJ ;TOO MANY WRITE BUFFERS QUEUED
6055 QSBWG1: PUSHJ P,QSTWG
6058 JRST QSBWG5 ;MEM FROZE OR NOT AVAILABLE
6059 MOVE Q,(P) ;DISK CHNL #
6060 DPB Q,[MNUMB,,MEMBLT(A)]
6062 DPB Q,[MUR,,MEMBLT(A)]
6069 MOVEM J,QMPBSZ(A) ;FRESH BLOCK SIZE
6072 QSTWG: MOVSI Q,%QAFUL
6073 TDNE Q,QSRAC(A) ;ROUTINE TO COMMIT A TRACK
6074 JRST QSTWG1 ;DIR FULL, NEED GC BEFORE GROWING FILE
6075 MOVE H,QUDPR(A) ;IF THIS DIRECTORY HAS AN ALLOCATION
6076 MOVE Q,QSNLCN(H) ; ENFORCE IT
6079 JUMPE J,QSTWG0 ;NO ALLOCATION
6080 HRRZ H,UDBLKS(Q) ;GET BLOCKS USED
6082 JRST IOCR13 ;HAS ALLOCATION AND USER IS TRYING TO EXCEED IT
6084 QSTWG0: MOVE J,QDSKN(A)
6085 SOSL QSFT(J) ;RESERVE A TRACK
6087 AOS QSFT(J) ;DISK FULL, GIVE BACK THE TRACK
6088 SKIPE QFBTS ;WAIT FOR ANY PENDING FILE DELETIONS
6089 PUSHJ P,UFLS ; TO COMPLETE AND FREE THEIR BLOCKS
6090 SOSL QSFT(J) ;GOT SPACE NOW?
6092 AOS QSFT(J) ;NO, GIVE UP AND ERR OUT
6095 QSTWG1: MOVE H,QUDPR(A)
6098 JRST IOCR12 ;DIR FULL
6100 ANDCAM Q,QSRAC(A) .SEE %QAFUL
6103 QSBWG5: POP P,A ;GET BACK QSK CHANNEL #
6105 AOS QSFT(J) ;NO MEMORY; GIVE EVERYTHING BACK
6108 ;DISK OUTPUT RELEASE-BUFFER ROUTINE FOR BLKT, SIOKT, CHRKT.
6109 QSBWW: SKIPGE QSMDN(A) ;WRITE BUFFER FROM MN PROG TO CHAIN FOR PI
6110 POPJ P, ;NO WRITE BUFFER ACTIVE
6111 LDB TT,[$QAMOD,,QSRAC(A)]
6112 SOJE TT,QSBWO1 ;WRITE OVER MODE
6114 JRST QTG1 ;TRACK ALREADY RESERVED
6117 PUSHJ P,QGTRK ;GET A TRACK
6120 QTG1: MOVE H,QUDPR(A) ;TRACK IN D
6124 MOVE TT,QMPTN(A) ;GET PREVIOUS TRACK#
6126 JRST QTG2 ;THIS TRACK IS CONSECUTIVE
6127 SKIPN QMPTC(A) ;THIS TRACK NOT CONSEC CHECK COUNT OF PREV CONSEC BLOCKS
6129 PUSH P,D ;NON-ZERO SO STORE IN USER DIRECTORY
6134 QTG3: MOVE J,QMTTR(A) ;DESCRIPTOR WILL BE STORED
6136 SUB D,QMPTN(A) ;CAN TRACK BE SKIPPED TO?
6137 SOJL D,QTG4 ;CAN'T BE SKIPPED TO (NOTE QMPTN HAS NOT BEEN AOS'D)
6138 CAILE D,UDWPH-UDTKMX-1
6140 ADDI D,UDTKMX ;NEXT BLOCK WITHIN N
6141 PUSHJ P,QUDS ;STORE APPROPRIATE SKIP
6143 QTG5: MOVE Q,QSMDN(A) ;CORE BLOCK NUM BEING WRITTEN
6144 MOVE D,QMPTN(A) ;TRACK NUM OF BLOCK ADDING TO FILE
6145 HRLZM D,MEMPNT(Q) ;STORE TRACK NUM
6146 SETOM QMTTR(A) ;INDICATE TRACK USED
6147 MOVE J,QMPBSZ(A) ;LENGTH OF THIS BLOCK
6148 ADDM J,QFBLNO(A) ;INCR BYTE ADR OF START OF CURRENT BLOCK IN FILE
6149 HRRM J,MEMPNT(Q) ;SAVE BYTE COUNT
6151 IDIVI J,@QSBYTE(A) ;CONVERT TO WORD COUNT
6152 JUMPE R,QTG7 ;EXACT MULTIPLE OF WORD
6155 ADDI R,@QSBYTE(A) ;# BYTES RESIDUE IN LAST WORD
6156 QTG7: DPB J,[MWC,,MEMBLT(Q)] ;STORE ACTIVE WORD COUNT
6158 LDB TT,[$QAMOD,,QSRAC(A)]
6159 TLNN D,%QALBK ;LAST BLOCK OF WRITE OVER POSSIBLY
6160 SOJE TT,QTG6 ;WRITEOVER MODE AND NOT LAST BLOCK, DONT UPDATE LAST BLOCK WORD COUNT
6161 MOVE H,QUDPR(A) ;SET UP DIRECTORY CHANNEL
6164 DPB J,[UNWRDC+UNRNDM(D)] ;SET WORD COUNT OF LAST BLOCK
6166 PUSHJ P,QBENC ;ENCODE BYTE CRUFT
6167 DPB Q,[UNBYTE+UNREF(D)]
6174 ANDCAM J,MEMBLT(Q) ;SET END OF LIST INDICATOR IN MEMORY BLOCK
6176 HLRZ J,QBFP(A) ;STORE MEMORY BLOCK IN OUTPUT LIST
6178 DPB Q,[MLO,,MEMBLT(J)]
6179 QSBWW2: HRLM Q,QBFP(A)
6181 SETOM QSMDN(A) ;MN PROG BUFFER NOW WRITTEN
6182 JRST QSTRTR ;START ACTION IF 2311 IDLE AND RETURN
6184 QSBWO1: MOVE Q,QSRAC(A) ;PUT BUFFER IN WRITE-OVER MODE
6185 TLNE Q,%QALBK ;IF NOT HACKING LAST BLOCK
6186 TLNE Q,%QAEFW ;OR HACKING CLOSE
6187 JRST QSBWO2 ;THEN JUST WRITE IT
6191 JUMPE D,QSBWO2 ;BLOCK REALLY FULL
6192 TLNE Q,%QAMPU ;DID WE IOCER2 AT QSBWG4?
6193 JRST IOCER2 ;YES, QSMPRP NOT SET UP, DON'T WRITE ANYTHING
6194 MOVEM D,QSMPRC(A) ;LAST BLOCK NOT REALLY USED UP ("SPRUNG BACK TO LIFE")
6195 ADDM D,QMPBSZ(A) ;EXTRA ROOM IN LAST BLOCK TO FILL UP
6197 IORM D,QSRAC(A) ;FILLING LAST BLK PAST ORIG EOF
6198 POPJ P, ;FINISH OUT BLOCK
6200 QSBWO2: MOVSI D,%QAWOV
6202 MOVE D,QSLGL(A) ;WRITE TRACK BACK WHERE IT CAME FROM
6203 MOVEM D,QMPTN(A) ;PUT TRACK NO WHERE QTG5 CAN FIND IT
6206 SETOM QSCRW(A) ;SWITCH TO WRITE MODE
6212 QTG4: LDB D,[140500,,QMTTR(A)] ;WRITE LOAD ADDRESS
6215 LDB D,[060600,,QMTTR(A)]
6217 LDB D,[0600,,QMTTR(A)]
6221 QGTRK: PUSHJ P,QTLOCK ;GET TRK CHNL IN A DSK IN I RET IN D CLOBBERS E,TT,Q,J,B
6222 QGTK4: PUSH P,R ;ENTER HERE FROM SWAP OUT WITH UTCOFF
6226 QGTK4A: SKIPGE Q,QMFTP(A)
6227 JRST QGTK3A ;FIRST TRACK
6229 HRREI J,-DECADE(J) ;COMPUTE TRACKS REMAINING IN DECADE
6232 ADD D,[TUTBYT_14,,] ;MAKE INTO ILDB-TYPE POINTER
6235 QGTK3: CAML D,QLASTB(R)
6236 JRST QGTK3A ;REACHED END OF DISK
6239 AOJGE J,QGTK3A ;DECADE OUT
6242 QGTK3A: CAILE A,NQCHN
6243 JRST QGTK3C ;SWAP CHANNEL
6244 QGTK3D: MOVEI Q,DECADE
6246 QGTK3B: MOVEM Q,QMFTP(A)
6249 MOVE Q,QSWAPA(R) ;REACHED END OF DSK, RESET TO END OF SWAPPING AREA
6250 ADDI Q,DECADE-1 ;ROUND UP TO A MULTIPLE OF A DECADE
6265 POPJ P, ;CALLED FROM SWAP OUT
6268 QGTK3C: CAML D,QSWAPA(R)
6269 JRST QGTK3D ;IN NON-SWAP AREA
6275 \f;STORE CHR IN D CHNL IN A USER DIR PNTR IN H
6276 ;CANNOT PCLSR NOR GC
6282 CAML I,@QSNLCN(H) ;UDESCP
6283 BUG ;WRITING ABOVE F.S. PNTR?
6289 BUG ;UFD WAS NOT LOCKED
6292 CAIE I,UDWPH ;OK TO CLOBBER UDWPH (NORMALLY DOES AT START OF FILE)
6293 JUMPN I,[JRST 4,.] ;ABOUT TO CLOBBER SOMETHING IN UFD
6295 ILDB I,Q ;MAKE SURE FILE DESC WILL ALWAYS BE FOLLOWED BY ZERO
6298 REPEAT NXLBYT+2,[ ;MAKE SURE THERE'S ROOM FOR ONE MORE TRACK
6304 CAMGE I,@QSNLCN(H) ;UDESCP
6305 JRST QUDSX ;DESC AREA NOT COLLIDING WITH LIM OF DESC SPACE
6310 JRST QUDS1 ;NO ROOM.
6311 MOVEI Q,3*UFDBPW ;EXPAND DESC AREA
6315 QUDS1: MOVSI Q,%QAFUL ;NEED GC BEFORE STARTING ON NEXT TRACK
6318 IORM Q,QSNLCN(H) ;SET DIRECTORY CHANGED
6323 QSBWW1: HRRM Q,QBFP(A)
6333 ADDM TT,QFBLNO(A) ;INCREMENT BYTE ADR IN FILE OF BEG OF NEXT BLOCK
6337 QTG2: MOVE J,QMTTR(A) ;INDICATE WE WILL STORE DESCRIPTOR FOR NEXT TRACK.
6339 AOS D,QMPTC(A) ;NEXT BLOCK IS CONSECUTIVE
6342 SETZM QMPTC(A) ;MAX # CONSECUTIVE BLOCKS, STORE DESC NOW
6346 SUBTTL DIRHNG DEVICE
6348 ;WHENEVER THE DIRECTORY SPECIFIED AS THE SNAME WHEN DIRHNG IS OPENED
6349 ;IS MODIFIED, YOU GET AN INTERRUPT ON THE DIRHNG DEVICE CHANNEL.
6351 ;HERE TO OPEN THE DIRHNG DEVICE. IOCHNM ADDR IN R, SNAME IN USYSN1(U).
6352 DIRHO: MOVE C,USYSN1(U)
6353 PUSHJ P,QFL ;LOOK UP THIS DIRECTORY
6354 JRST OPNL20 ;CALL FAILS IF DIRECTORY DOES NOT EXIST.
6355 HRRZM J,IOCHST-IOCHNM(R) ;DIR EXISTS; STORE TRACK NUMBER IN IOCHST.
6356 DIRHP1: CONO PI,CLKOFF
6357 HLLZ A,DIRHNG ;ADD THIS CHANNEL'S IOCHNM TO THE LIST OF DIRHNG CHANNELS.
6359 MOVEM A,(R) ;SET UP THE IOCHNM WITH IOTTB INDEX AND LIST CHAIN.
6363 ;CLOSE A DIRHNG DEVICE CHANNEL.
6364 DIRHCL: PUSHJ P,DIRHPS ;REMOVE IT FROM THE LIST, AND
6365 SETZM (R) ;MARK IT CLOSED.
6368 ;IOPUSH A DIRHNG DEVICE CHANNEL. REMOVE IT FROM THE LIST OF ALL SUCH.
6369 DIRHPS: MOVEI A,DIRHNG
6371 ;FIND THE PLACE THAT POINTS AT THIS IOCHNM WORD.
6375 SKIPN A,B ;END OF LIST REACHED =>
6376 BUG ;THIS IOCHNM ISN'T IN THE LIST. BUT IT IS SUPPOSED TO BE!
6379 ;A POINTS AT IOCHNM THAT POINTS AT THIS ONE. PATCH THIS ONE OUT OF LIST.
6380 DIRHC2: HLRZ B,(B) ;THE ONE AFTER THIS ONE
6384 ;IOPUSH OR IOPOP THE DIRHNG CHANNEL WITH R -> IOCHNM WORD. I SAYS WHICH OPERATION.
6385 DIRHIP: JUMPE I,DIRHPS ;IOPUSH REMOVES CHANNEL FROM LIST OF ALL DIRHNG CHANNELS.
6387 ;IOPOP A DIRHNG DEVICE CHANNEL. JUST LIKE OPENING IT EXCEPT THAT
6388 ;THE DIRECTORY TRACK NUMBER IS ALREADY IN THE IOCHST.
6389 ;ALSO, WE SHOULD GIVE AN INTERRUPT NOW,
6390 ;IN CASE THE DIRECTORY WAS WRITTEN IN WHILE THE CHANNEL WAS PUSHED.
6391 DIRHPP: PUSHJ P,DIRHP1 ;FIRST, REOPEN THE CHANNEL. LINK IT INTO THE DIRHNG LIST.
6394 SUBI A,IOCHNM(U) ;COMPUTE CHANNEL NUMBER FROM IOCHNM WORD ADDRESS.
6395 MOVE A,CHNBIT(A) ;GET BIT CORRESPONDING TO CHANNEL.
6396 AND A,MSKST2(U) ;GIVE THE INT IF THE INT IS ENABLED.
6400 ;HERE WITH A/ DIRECTORY'S TRACK NUMBER (AS RETURNED BY QFL)
6401 ;TO SIGNAL A WRITE IN THAT DIRECTORY TO ALL DIRHNG DEVICES THAT ARE LOOKING.
6403 DIRSIG: CONO PI,CLKOFF
6405 DIRSI0: HLRZ B,(B) ;GET IOCHNM ADDR OF NEXT DIRHNG DEVICE.
6407 HRRZ C,IOCHST-IOCHNM(B)
6408 CAIE C,(A) ;DOES IT LOOK AT THIS DIRECTORY?
6410 MOVEI C,-IOCHNM(B) ;YES => FIGURE OUT USER INDEX OF JOB IT BELONGS TO.
6412 IMULI C,LUBLK ;C NOW HAS USER INDEX.
6414 ADD D,B ;D GETS CHANNEL NUMBER
6416 AND D,MSKST2(C) ;INTERRUPT THE USER ON THAT CHANNEL, IF IT'S ENABLED.