d9c72ccd01c7a94b9c386db538dd08ea83af3e40
[its.git] / system / disk.1222
1 ; I T S DISK SERVICE ROUTINES AND FILE SYSTEM  -*-MIDAS-*-
2 ;;; Copyright (c) 1999 Massachusetts Institute of Technology
3 ;;;
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 2 of the
7 ;;; License, or (at your option) any later version.
8 ;;;
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.
13 ;;;
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.
17
18
19 DSKVRS==.IFNM2
20 IFN DC10P+RP10P+RH10P+RH11P-1, .ERR WRONG NUMBER OF DISK CONTROLLERS
21
22 ;GET DISK PHYSICAL PARAMETERS BY .INSRT'ING APPROPRIATE FILE
23
24 IFN DC10P,[
25 $INSRT DC10
26 ]
27
28 IFN RP10P,[
29 $INSRT RP10
30 ]
31
32 IFN RH10P,[
33 $INSRT RH10
34 ]
35
36 IFN RH11P,[
37 $INSRT RH11
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
40 IFN RP06P,[
41 $INSRT RP06
42 ]
43 IFN RM03P,[
44 $INSRT RM03
45 ]
46 IFN RM80P,[
47 $INSRT RM80
48 ]
49 ]
50
51 ;GET FILE SYSTEM DEFINITIONS:
52 ;       MFD     MASTER FILE DIRECTORY
53 ;       TUT     TRACK (BLOCK) UTILIZATION TABLE
54 ;       UFD     USER FILE DIRECTORY
55
56 $INSRT FSDEFS
57
58 IFN T300P,[
59 $INSRT T300
60 ]
61 \f
62 SUBTTL MISC FILE SYSTEM CALLS
63
64 ADMPCH: UMOVE A,(J)     ;SET OR READ STATUS OF DUMP BIT OF FILE OPEN ON
65                         ; CHNL IN AC(RH)
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.
69         TLNN R,%CLSQ
70          JRST ILUUO     ;NOT DISK CHANNEL.
71         PUSHJ P,QCHNLT  ;DECODE THE CHNL FURTHER.
72         MOVSI B,400000
73         TLNE A,400000
74          IORM B,UNRNDM(C)
75         TLNE A,200000
76          ANDCAM B,UNRNDM(C)
77         MOVE D,QACTB
78         TLNE A,600000
79          IORM D,QSNLCN(H)
80         LDB A,[430100,,UNRNDM(C)]
81         PUSHJ P,QUDULK
82         JRST APTUAJ
83
84 NRFDATE:        PUSHJ P,QCHNLT  ;READ FILE CREATION DATE WORD
85         MOVE A,UNDATE(C)
86 NRDM1:  PUSHJ P,QUDULK
87         JRST POPJ1      ;STORE BACK IN USER MEM
88
89 NSRDATE:        PUSHJ P,QCHNLT  ; SET REFERENCE DATE
90         HLRS B
91         DPB B,[UNREFD+UNREF(C)]
92         JRST NSDM1
93
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)]
97         JRST NSDM1
98
99 NSFDATE:        PUSHJ P,QCHNLT  ;SET FILE CREATION DATE WORD
100         MOVEM B,UNDATE(C)
101 NSDM1:  MOVE TT,QACTB
102         IORM TT,QSNLCN(H)
103 QUDUL1: AOS (P)
104         JRST QUDULK
105
106
107 NRDMPBT:        PUSHJ P,QCHNLT  ;READ FILE DUMPED BIT
108         LDB A,[430100,,UNRNDM(C)]
109         JRST NRDM1
110
111 NSDMPBT:        PUSHJ P,QCHNLT  ;SET FILE DUMPED BIT
112         DPB B,[430100,,UNRNDM(C)]
113         JRST NSDM1
114
115 NLNKEDP:
116         PUSHJ P,QCHNLT          ;RETURN NONZERO IF WE TRACED LINKS TO GET THIS FILE.
117         MOVE T,QSRAC(R)
118         LDB A,[.BP (%QALOP),T]
119         JRST NRDM1
120
121 NFILBLK:PUSHJ P,QCHNLT  ;READ ALL 5 PARAMETERS OF NAME AREA
122         MOVE A,(C)
123         MOVE B,1(C)
124         MOVE D,3(C)
125         MOVE E,4(C)
126         MOVE C,2(C)
127         JRST NRDM1      ; UNLOCK DIR AND STORE ARGUMENTS
128
129 QCHNLT: TLNN R,%CLSQ    ;IS CHNL A DISK CHNL?
130          JRST [SUB P,[1,,1] ? JRST OPNL34]
131         HLRZ R,H
132         MOVE H,QUDPR(R)
133         PUSHJ P,QUDLK
134         MOVE C,QSNLCN(H)
135         ADD C,QUDFPR(R)
136         POPJ P,
137 \f
138 IFN QAUTHP,[
139 ASAUTH: PUSHJ P,QCHNLT  ;SET AUTHOR OF FILE
140         PUSH P,C
141         JUMPE B,ASAUT4  ;SETTING AUTHOR TO 0
142         MOVE J,QSNMI(H)
143         CAMN B,QSNUD(H)
144          JRST ASAUT1
145         MOVE C,B
146         PUSHJ P,QFL
147          SKIPA
148           JRST ASAUT1
149         SETZM C
150         MOVEI J,5
151         MOVE TT,[440600,,B]
152         MOVE I,[440600,,C]
153         ILDB D,TT
154         IDPB D,I
155 ASAUT2: ILDB D,TT
156         CAIG D,'Z
157         CAIGE D,'A
158          JRST ASAUT3
159         IDPB D,I
160         SOJG J,ASAUT2
161         JRST ASAUT4
162
163 ASAUT3: PUSHJ P,QFL
164 ASAUT4:  SETOM J
165 ASAUT1: POP P,C
166         DPB J,[UNAUTH+UNREF(C)]
167         JRST NSDM1
168
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
172         CAIL B,NUDSL
173          JRST NRDM1
174         LSH B,1
175         MOVEI B,2000-<NUDSL*2>(B)
176         ADD B,QMDRO
177         MOVE A,(B)
178         JRST NRDM1
179 ];QAUTHP
180
181 ASREAP: PUSHJ P,QCHNLT          ;SET NO REAP BIT
182         DPB B,[.BP (UNREAP),UNRNDM(C)]
183         JRST NSDM1
184
185 ARQDAT: CONO PI,CLKOFF  ;GET DSK TIME AND DATE
186         SKIPL A,QDATE
187         HRR A,TIMOFF
188         MOVE B,QDATEI   ;2ND VALUE = DATE & TIME SYS CAME UP, IN DISK FORMAT.
189         CONO PI,CLKON
190         JRST POPJ1
191
192 ADSKUP: PUSHJ P,QCHNLT  ;SET CREATION DATE, REF DATE AND CLEAR DUMP BIT
193         CONO PI,CLKOFF
194         SKIPL TT,QDATE
195          HRR TT,TIMOFF
196         CONO PI,CLKON
197         MOVEM TT,UNDATE(C)
198         HLRS TT
199         DPB TT,[UNREFD+UNREF(C)]
200         MOVSI TT,UNDUMP
201         ANDCAM TT,UNRNDM(C)
202         JRST NSDM1
203
204 DELEWO: TLNN R,%CLSQ    ;DELETE WHILE OPEN
205          JRST OPNL34    ;WRONG TYPE DEVICE
206         PUSHJ P,QCHNLT
207         PUSH P,W
208         PUSH P,C
209         MOVEI W,4
210         MOVE A,UNFN1(C) ;Get names of file being hacked.
211         MOVE B,UNFN2(C)
212         MOVE C,QSNUD(H)
213         PUSHJ P,MNGDIR  ;If this is a sanctified dir
214          PUSHJ P,SYSDSK ; get SYS job to tattle about it.
215         POP P,C
216         POP P,W
217         MOVSI T,%QADEL  ;SET DELETE BIT IN QSK CHNL
218         IORM T,QSRAC(R)
219         MOVSI T,UNCDEL  ;AND IN FILE
220         IORM T,UNRNDM(C)
221         JRST NSDM1
222 \f
223 ;.CALL FILLEN
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)
228
229 NFILLEN:PUSHJ P,QCHNLT
230         MOVE A,QSRAC(R)
231         TLNE A,%QALNK
232          JRST OPNL34    ;NOT A FILE
233         SKIPGE QSCRW(R)
234          TLNE A,%QAMWO
235           JRST NFILL1   ;READ CHANNEL OR WRITE-OVER, GET FILE'S STORED LENGTH.
236         MOVE A,QFBLNO(R);NORMAL WRITE, GET ACCESS POINTER.
237         SKIPGE QSMDN(R)
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
245         JRST POPJ1
246
247 NFILL1: LDB TT,[UNDSCP+UNRNDM(C)]
248         IDIVI TT,UFDBPW
249         HLL TT,QBTBLI(I)        ;GET DESCRIPTOR POINTER
250         LDB E,[UNWRDC+UNRNDM(C)]
251         SKIPN E
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
258         PUSHJ P,QUDULK
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
262         MOVEI Q,36.
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
273
274 NFLLN2: ADD A,B         ; NEXT N BLOCKS
275 NFLLN1: ILDB B,TT       ; GET NEXT DESC BYTE
276         JUMPE B,CPOPJ   ; NO MORE
277         CAIG B,UDTKMX
278          JRST NFLLN2    ; TAKE-N
279         CAIGE B,UDWPH
280          AOJA A,NFLLN1  ; SKIP-N, TAKE-1
281         CAIN B,UDWPH
282          JRST NFLLN1    ; IGNORE WRITE-PLACEHOLDER
283 REPEAT NXLBYT, IBP TT   ; LOAD-ADDRESS, TAKE-1
284         AOJA A,NFLLN1
285 \f
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
290 NDIRSI: MOVE D,C
291         PUSHJ P,QCHNLT
292         MOVE C,QSNLCN(H)
293         MOVE A,UDBLKS(C)
294         JUMPL B,NDIRS1
295         CAIE W,1
296          HLLM B,UDBLKS(C)
297 NDIRS1: MOVE B,UDALLO(C)
298         CAILE W,2
299          MOVEM D,UDALLO(C)
300 IFN QRSRVP,[
301         HLRZS D                 ;PACK ALLOCATED TO
302         SETO E,
303         JUMPE D,NDIRS2
304         MOVEI E,NQS-1           ;UPDATE ALLOC DRIVE NUM
305         CAME D,QPKID(E)
306          SOJGE E,.-1
307 NDIRS2: MOVEM E,QSALLO(H)
308 ];QRSRVP
309         JRST NSDM1
310 \f
311 SUBTTL DISK OPEN ROUTINES
312
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).
318
319 IFN TPLP+UNSPLP,[
320 TPLO:   MOVE C,[SIXBIT /.LPTR./] ;PSEUDO LINE PRINTER (DISC)
321         JUMPGE D,TPLO2
322         MOVE B,UNAME(U)
323         AOS A,TPLFNO    ;GENERATE RANDOM FILE NAME
324         JRST TPLO2
325 ]
326
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)
330         MOVNI I,1
331         JRST QSKO
332
333 QSKPO:  MOVSI TT,-NQS   ;PACK # OPEN
334         CAME I,QPKID(TT)
335          AOBJN TT,.-1   ;I <= PHYSICAL UNIT WITH SPECIFIED PACK
336         JUMPL TT,QSKPO1
337         PUSHJ P,QPKNFP
338          JRST QSKPO
339         CAIE W,4        ;IF RENAME/DELETE, OK, DOESN'T TOUCH FILE ANYWAY
340          JRST OPNL16    ;OTHERWISE COMPLAIN PACK NOT MOUNTED
341 QSKPO1: HRRZ I,TT
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.
346 IFN QRSRVP,[
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.
351 ];QRSRVP
352 ];DM
353         JRST QSKOB
354
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
357
358 ; Regular DSK: device
359 ;
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)
362
363 QSKO:   MOVNI I,1       ;DSK OPEN, I <= # DETERMINED BY SYS
364 QSKOB:  MOVEM I,EPDL(U) ;SAVE DISK #
365         MOVE C,USYSN1(U)
366         CAIN W,4
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
371 QSKOL:  PUSHJ P,MFDCK
372          JRST SYSDS2
373         JUMPN W,OPNL11
374         JUMPL D,OPNL11  ;MUST BE NORMAL READ
375         JRST QMLSTF     ;USER WANT TO READ THE MASTER DIRECTORY
376
377 MFDCK:  CAMN A,[SIXBIT /M.F.D./]
378         CAME B,[SIXBIT /(FILE)/]
379          POPJ P,
380         JRST POPJ1
381 \f
382 SYSDS2: PUSHJ P,QFLD    ;H <= PTR TO USER DIR TABLE
383          PUSHJ P,QSKO1  ;LOSER DIR NOT IN CORE
384         SKIPG QSNNR(H)
385          BUG
386         PUSHJ P,QUDLK   ;RETURN WITH SOS OF QSNNR ON LSWPR
387         MOVSI TT,40000
388         TDNE TT,QSNLCN(H)
389          JRST QSKDP1    ;PAW OVER USER DIRECTORY
390 QSKDP2: PUSHJ P,QUDULK
391         PUSHJ P,FLDRCK
392          JRST QSKDP9    ;NOT SPECIAL DIRECTORY FILE
393         JUMPN W,QPNL11
394         JUMPL D,QPNL11
395         JRST QLISTF     ;USER WANTS TO READ HIS USER DIRECTORY
396
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
403         CAIN W,4
404          JRST QRNAM     ;RENAME/DEL
405         CAIN W,2
406          JRST QALINK    ;MAKE LINK
407         JUMPN W,QPNL22
408 QWROR:  JUMPE A,QPNL11  ;ALSO ENTER FOR VARIOUS WRITE OVER, COPY OVER MODES
409         JUMPE B,QPNL11
410         PUSHJ P,QCHNF   ;GET CHANNEL FOR READ
411         PUSHJ P,LOSSET
412             QCHNRT
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
422          JRST QSKO2
423         MOVE J,[440700,,5] ;BYTE SIZE IS 7 BITS
424         MOVEM J,QSBYTE(E)
425 QSKO2:  HLLZ J,QSBYTE(E) ;GET PROPER BYTE POINTER LH
426         MOVEM J,QSMPRP(E)
427         TRNN D,%DONRF/2 ;3.4 BIT IN OPEN IMPLIES DONT SET REFERENCE DATE
428          PUSHJ P,QFREF  ;"REFERENCE" FILE
429         MOVE C,Q
430         SUB C,QSNLCN(H)
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
434         MOVE C,UNRNDM(Q)
435         TLNE C,UNLINK
436          JRST QLINK     ;FILE IS A LINK
437         MOVSI C,%QALOP
438         SKIPE QLD(U)    ;IF WE TRACED A LINK TO OPEN THE FILE, REMEMBER THAT.
439          IORM C,QSRAC(E)
440         MOVSI C,%QARWT
441         TRNE D,%DORWT/2
442          IORM C,QSRAC(E)
443         LDB J,[UNPKN+UNRNDM(Q)] ;GET PACK NUMBER FILE IS ON
444         MOVSI I,-NQS
445         CAME J,QPKID(I)
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
451         HRRM TT,QSRAC(E)
452 QOEX1:  PUSHJ P,QUDULK  ;UNLOCK USER DIR
453         PUSHJ P,LSWDEL  ;QUSR ENTRY
454         PUSHJ P,LSWDEL  ;QSNNR ENTRY
455         SKIPG QSNNR(H)
456          BUG
457         PUSHJ P,QSTRTR
458         MOVE C,D
459         ROT C,1
460         HRL A,E
461         JSP Q,OPSLC7    ;SET UP IOCHNM AND DEPART
462             DQUAI,,DQUAO
463             DQBI,,DQBO
464             DQUII,,DQUIO
465             DQBI,,DQBO
466 \f
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
473          SKIPGE QUSR(I)
474           JRST QROR1B
475         CAMN H,QUDPR(I)
476          CAME J,QUDFPR(I)
477           JRST QROR1B
478         JRST  OPNL23
479
480 QROR1B: AOBJN I,QROR1A
481         PUSHJ P,QAUTH
482         MOVSI TT,UNWRIT
483         IORM TT,UNRNDM(Q)       ;SET WRITE BIT
484         MOVSI TT,UNDUMP
485         ANDCAM TT,UNRNDM(Q)
486         PUSH P,D
487         PUSH P,Q
488         PUSH P,R
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
492         MOVEI Q,36.
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
503         MOVE R,-1(P)
504         DPB Q,[UNBYTE+UNREF(R)] ;CLOBBER FILE'S BYTE SIZE
505         POP P,R
506         POP P,Q
507         POP P,D
508         CONO PI,CLKOFF
509         SKIPL TT,QDATE
510          HRR TT,TIMOFF
511         CONO PI,CLKON
512         MOVEM TT,UNDATE(Q)
513         HLRS TT
514         DPB TT,[UNREFD+UNREF(Q)]
515         HLLM TT,OLDRDT(E)
516         MOVE TT,QACTB
517         IORM TT,QSNLCN(H)
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
521
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.
527 ;Clobbers C, J.
528 QROR1C: HRRZ C,QSNLCN(H)
529         SUBI Q,-LUNBLK(C)
530         SKIPL Q         ;SEE IF STILL POINTED INSIDE DIR
531         CAILE Q,2000-LUNBLK
532          JRST QROR1D    ;NO - REALLY FNF
533         ADDI Q,(C)
534         CAMN A,UNFN1(Q) ;DO NAMES MATCH?
535         CAME B,UNFN2(Q)
536          JRST QROR1D    ;NO - REALLY FNF
537         HRRZ J,Q        ;Find channel that has this file open.
538         SUB J,QSNLCN(H)
539         ANDI J,-1
540         HRRZS H         ;Clear garbage in user dir num
541         HRRZS E         ;Clear garbage in chnl num
542         MOVSI I,-NQCHN
543 QROR1E: CAIE E,(I)      ;Dont get faked out by our own chnl.
544          SKIPGE QUSR(I)
545           JRST QROR1F
546         CAMN H,QUDPR(I)
547          CAME J,QUDFPR(I)
548           JRST QROR1F
549 ;Found the channel.  Does it want us to wait?
550         MOVE I,QSRAC(I)
551         TLNN I,%QARWT
552          JRST OPNL23    ;He didn't say so => get "file locked".
553         JRST POPJ1
554
555 QROR1F: AOBJN I,QROR1E
556         JRST POPJ1      ;Cannot find channel => maybe was closed.  Retry.
557
558 QROR1D: SKIPN QLD(U)
559          JRST OPNL4     ;FILE NOT FOUND
560         JRST OPNL47     ;LINK WAS FOUND, BUT NOT THE FILE IT POINTED TO
561 \f
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
565          JRST OPNL14
566         SKIPE SRN3(U)
567          SKIPN SRN4(U)
568           JRST OPNL11
569         ADD A,U
570         HLRZ E,IOCHNM(A)
571         MOVE H,QUDPR(E)
572         MOVE A,SRN3(U)
573         MOVE B,SRN4(U)
574         PUSHJ P,MFDCK
575          JRST .+2
576           JRST QPNL11
577         PUSHJ P,FLDRCK
578          JRST .+2
579           JRST QPNL11
580         PUSHJ P,QUDLK
581         MOVE Q,QUDFPR(E)
582         ADD Q,QSNLCN(H)
583         PUSHJ P,QGRLSC  ;EITHER NAME > OR <?
584          JRST OPNL11    ;BOTH-BARF
585           PUSHJ P,QFNG  ;ONE- COMPUTE EFFECTIVE FILE NAME
586         MOVE C,QSNUD(H)
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
593         PUSHJ P,QRELOC
594         MOVE TT,QACTB
595         IORM TT,QSNLCN(H)
596         PUSHJ P,QUDULK
597         JRST POPJ1
598 \f
599 SUBTTL PAW OVER USER DIRECTORY
600
601 QSKDP1: ANDCAB TT,QSNLCN(H)
602         PUSH P,A
603         PUSH P,B
604         PUSH P,C
605         PUSH P,D
606         PUSH P,I
607         PUSH P,W
608         MOVE C,UDNAMP(TT)
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)
613         MOVE W,E        ;FN2
614         MOVEI J,0       ;J NEGATIVE => NEED SORT, NON-ZERO => DIR MODIFIED
615 QSKDP4: SUBI I,LUNBLK
616 QSKDP5: SUBI D,LUNBLK
617         CAMLE C,D
618          JRST QSKDP8    ;THROUGH
619         SKIPN A,UNFN1(D)
620          SKIPE UNFN2(D)
621           JRST QSKDP3
622         HLLOS J
623         JRST QSKDP5     ;NAME BLOCK FREE
624
625 QSKDP3: MOVE Q,UNRNDM(D)
626         TLNN Q,UNIGFL
627          JRST QSKDPR    ;NOT OPEN FOR WRITE OR BEING DELETED
628         HLLOS J         ;NEED TO WRITE OUT DIR
629         SKIPN A,UNFN1(D)
630          MOVSI A,(SETZ)
631         SKIPN B,UNFN2(D)
632          MOVSI B,(SETZ)
633 QSKDP7: PUSHJ P,QGRLSC  ;DON'T CREATE ANY FILE WITH NAME OF < OR >
634          AOJA A,QSKDPA  ;CHANGE BOTH JUST TO BE SURE
635           AOJA A,QSKDPA
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
640           JRST QSKDPT
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
644         CAMG C,Q
645          JRST QSKDPU
646         MOVEM A,UNFN1(D)
647         MOVEM B,UNFN2(D)
648         MOVSI Q,UNIGFL
649         ANDCAM Q,UNRNDM(D)
650 QSKDPR: CAMN D,I
651          JRST QSKDP6
652         HRLZ Q,D        ;RELOCATE FILE BLOCK
653         HRR Q,I
654         BLT Q,LUNBLK-1(I)
655 QSKDP6: JUMPL J,QSKDP4  ;ALREADY NEEDS SORT
656         MOVE B,UNFN2(D) ;MAY NOT HAVE YET IF GOT HERE FASTEST WAY
657         TLC A,(SETZ)
658         TLC B,(SETZ)
659         EXCH A,E
660         EXCH B,W
661         CAMLE A,E
662          JRST QSKDP4    ;ORDER OK
663         CAMN A,E
664          CAMGE B,W
665           MOVNI J,1     ;NEED SORT
666         JRST QSKDP4
667 \f
668 QSKDP8: ADDI I,LUNBLK   ;I POINTED TO EMPTY SLOT
669         MOVE D,I
670         SUBI D,(TT)
671         EXCH D,UDNAMP(TT)
672         ADDI D,(TT)
673         CAML D,I
674          JRST QSKDPV
675         SETZM (D)       ;CLEAR VACATED AREA
676         HRLS D
677         ADDI D,1
678         BLT D,-1(I)
679 QSKDPV: JUMPL J,QSKDPS  ;SORT
680         TRNN J,-1
681          JRST QSKDPK
682 QSKDPX: MOVE I,QACTB
683         IORM I,QSNLCN(H)
684 QSKDPK: MOVE W,QSNLCN(H)
685 IFN QRSRVP,[
686         HLRZ A,UDALLO(W)        ;IF THIS DIR HAS ALLOCATION
687         JUMPE A,QSKBK0
688         MOVEI B,NQS-1           ;CONVERT PACK # TO DRIVE #
689         CAME A,QPKID(B)
690          SOJGE B,.-1
691         SKIPGE A,B
692 QSKBK0:  SETO A,                ;ALLOCATED PACK NOT MOUNTED, USE ANY
693         MOVEM A,QSALLO(H)       ;SAVE DRIVE # (-1 IF NONE)
694 ];QRSRVP
695         HLLZS UDBLKS(W)
696         MOVE A,UDNAMP(W)
697         ADDI A,(W)
698 QSKBK1: CAIL A,2000(W)  ;COUNT BLOCKS USED
699          JRST QSKBK2
700         MOVE B,UNRNDM(A)
701         TLNE B,UNLINK
702          JRST QSKBK3
703         LDB B,[UNDSCP+UNRNDM(A)]
704         IDIVI B,UFDBPW
705         HLL B,QBTBLI(C)
706         ADDI B,UDDESC(W)        ;B GETS BYTE PNTR TO DESC
707 QSKBK4: ILDB C,B
708         JUMPE C,QSKBK3
709         CAIN C,UDWPH
710          JRST QSKBK4
711         CAIG C,UDTKMX
712          JRST [ADDM C,UDBLKS(W) ? JRST QSKBK4]
713         CAIG C,UDWPH
714          JRST [AOS UDBLKS(W) ? JRST QSKBK4]
715         REPEAT NXLBYT, IBP B
716         AOS UDBLKS(W)
717         JRST QSKBK4
718
719 QSKBK3: ADDI A,LUNBLK
720         JRST QSKBK1
721
722 QSKBK2: POP P,W
723         POP P,I
724         POP P,D
725         POP P,C
726         POP P,B
727         POP P,A
728         JRST QSKDP2
729 \f
730 QSKDPS: MOVEI T,LUNBLK
731         ADD P,[3,,3]
732 QSKDPB: MOVEI Q,(I)     ;BEGINNING OF NAME AREA
733         SKIPGE T
734          MOVEI Q,2000-LUNBLK(TT)        ;START AT END
735         MOVEI W,2000(TT)
736         SKIPGE T
737          MOVEI W,-LUNBLK(I)
738         SETZM (P)
739         TDZA J,J        ;0 => SORTED  -1 => MAKE ANOTHER PASS
740 QSKDPE:  ADD Q,T
741         CAIE Q,(W)
742          JRST QSKDPC
743         JUMPE J,QSKDPW
744         MOVNS T
745         JRST QSKDPB
746
747 QSKDPW: SUB P,[3,,3]
748         JRST QSKDPX
749
750 QSKDPC: SKIPN A,UNFN1(Q)
751          SKIPE UNFN2(Q)
752           JRST QSKDPD
753         BUG
754
755 QSKDPD: MOVE B,UNFN2(Q)
756         TLC A,(SETZ)
757         TLC B,(SETZ)
758         SKIPE E,(P)     ;FIRST ENTRY
759          JRST QSKDPF
760 QSKDPG: MOVEM A,-2(P)
761         MOVEM B,-1(P)
762 QSKDPI: MOVEM Q,(P)
763         JRST QSKDPE
764
765 QSKDPF: JUMPL T,QSKDPJ
766         CAMLE A,-2(P)
767          JRST QSKDPG
768         CAME A,-2(P)
769          JRST QSKDPH
770         CAML B,-1(P)
771          JRST QSKDPG
772 QSKDPH: REPEAT LUNBLK,[
773         EXCH A,.RPCNT(E)
774         EXCH A,.RPCNT(Q)
775         EXCH A,.RPCNT(E)
776 ]
777         MOVNI J,1
778         JRST QSKDPI
779
780 QSKDPJ: CAMGE A,-2(P)
781          JRST QSKDPG
782         CAME A,-2(P)
783          JRST QSKDPH
784         CAMG B,-1(P)
785          JRST QSKDPG
786         JRST QSKDPH
787 \f
788 SUBTTL OPEN FOR WRITE
789
790 ;RETURNS WITH QUSR(E) AND QSNLCN(E) ON LSWPR
791 QWRO2:  JUMPE A,QPNL11
792         JUMPE B,QPNL11
793         SKIPGE I,EPDL(U)        ;PICK UP DESIRED DISK UNIT
794          JRST QWRO2A    ;SYSTEMS CHOICE
795 QWRO2B: CAIGE I,NQS
796          SKIPE QACT(I)
797           BUG           ;WE LOST SOMEHOW...
798         MOVE TT,QTUTO(I)
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
803         PUSHJ P,LOSSET
804             QCHNRT
805         MOVE TT,[440700,,5]
806         TRNN D,3
807          MOVEM TT,QSBYTE(E) ;UNIT ASCII MODE, BYTE SIZE=7
808         PUSHJ P,QUDLK   ;LOCK USER DIRECTORY
809         PUSHJ P,QGRLSC  ;CHECK < AND >
810          JRST QPNLBN    ;LOSE
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
815         IORM TT,UNRNDM(Q)
816         MOVE TT,QPKID(I)
817         DPB TT,[UNPKN+UNRNDM(Q)]
818         PUSHJ P,QAUTH   ;SET FILE AUTHOR, MAY NOT PCLSR
819         MOVE TT,QACTB
820         IORM TT,QSNLCN(H)
821         SETOM QSCRW(E)  ;SET CHNL WRITE SWITCH
822         POPJ P,
823
824 QWRO2A:
825 IFN QRSRVP,[
826         SKIPL I,QSALLO(H)
827          JRST QWRO2B    ;THIS DIR GOES ON A PARTICULAR UNIT
828 ]
829         SKIPGE I,QWRU   ;GET CURRENT WRITING UNIT
830          JRST QWRO2E    ;NO CURRENT UNIT, GO FIND ONE
831         MOVE TT,QSFT(I)
832         CAML TT,QFTTHR
833          JRST QWRO2B    ;ENOUGH ROOM ON PREFERRED UNIT
834 QWRO2E: SETOB T,I       ;NOT MUCH SPACE LEFT TRY OTHER UNITS
835         MOVSI E,-NQS
836 QWRO2C: SKIPGE QACT(E)  ;SKIP ON UNIT ACTIVE
837          JRST QWRO2D
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
841         MOVE T,QSFT(E)
842         HRRZ I,E
843 QWRO2D: AOBJN E,QWRO2C
844         SKIPGE I
845          BUG            ;NO ACTIVE UNRESERVED UNITS
846         CAMN I,QWRU
847          JRST QWRO2B    ;DON'T WRITE MFD IF UNCHANGED
848         MOVEM I,QWRU
849         MOVE E,QACTB
850         IORB E,QMDRO
851         MOVEM I,MPDWDK(E)
852         JRST QWRO2B
853
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
857         SETOM QMTTR(E)
858         CLEARM QMPTN(E)
859         CLEARM QMPTC(E)
860         MOVEI TT,%QMWRT ;ENTER NORMAL WRITE MODE
861         HRRM TT,QSRAC(E)
862         MOVSI TT,%QARWT
863         TRNE D,%DORWT/2
864          IORM TT,QSRAC(E)
865         JRST QOEX1      ;EXIT
866
867 \f
868 SUBTTL  File hacking tracking
869
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.
873
874 MNGDIR: HLRZ TT,C
875 IFN KL10P, CAME C,[SIXBIT /.KLFE./]
876         CAIN TT,'SYS    ;A sys directory?
877          POPJ P,
878         CAME C,[SIXBIT /ACOUNT/]
879          CAMN C,[SIXBIT /./]
880           POPJ P,
881         CAME C,[SIXBIT /DEVICE/]
882          CAMN C,[SIXBIT /CHANNA/]
883           POPJ P,
884         AOS (P)         ;Not a system directory. skip return.
885         POPJ P,
886
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.
890
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.
899         MOVE TT,UNAME(U)
900         MOVEM TT,SWUNAM         ;Luser.
901         MOVE TT,JNAME(U)
902         MOVEM TT,SWJNAM
903         MOVEM A,SWFN1
904         MOVEM B,SWFN2
905         MOVEM C,SWFN3           ;Sname.
906         IORM T,SUPCOR           ;Notify the SYS job.
907         JRST CLKONJ             ;Turn on the clock and return.
908
909 \f
910 SUBTTL DIRECTORY ROUTINES
911
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
914         PUSH P,I
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
917         MOVE TT,QSNLCN(H)
918         SKIPL Q,UDESCP(TT)
919          CAIL Q,2000*UFDBPW
920           BUG           ;FREE DESC POINTER OUT OF RANGE
921         IDIVI Q,UFDBPW
922         MOVE C,UDNAMP(TT)
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
927         TRNN J,1777
928          JRST QFREFE    ;GOES AT END OF DIR
929 QFREFC: CAMN A,UNFN1(J)
930          CAME B,UNFN2(J)
931           JRST QFREFE
932         MOVE C,UNRNDM(J)
933         TLNE C,UNIGFL   ;* FILES MUST COME AFTER NON * FILES
934          JRST QFREFE    ;OF SAME NAME
935         ADDI J,LUNBLK
936         CAIGE J,2000(TT)
937          JRST QFREFC
938 QFREFE: CAMN Q,J
939          JRST QFREFF    ;GOES AT BEGINNING
940         PUSHJ P,QINSRT
941         JRST QFREFD
942
943 QFREFF: SUBI Q,LUNBLK           ;Q -> NAME BLOCK FILE WILL GO IN
944 QFREFD: MOVNI T,LUNBLK          ;ALLOCATE MORE SPACE FOR NAME AREA
945         ADDM T,UDNAMP(TT)
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
951         MOVE B,Q
952         SUB B,QSNLCN(H)
953         HRRZM B,QUDFPR(E)       ;ASSOCIATE CHANNEL WITH FILE
954         CONO PI,CLKOFF
955         SKIPL B,QDATE           ;GET TIME AND DATE
956          HRR B,TIMOFF
957         CONO PI,CLKON
958         MOVEM B,UNDATE(Q)       ;SET CREATION DATE
959         HLLM B,OLDRDT(E)
960         HLRS B
961         DPB B,[UNREFD+UNREF(Q)] ;SET REFERENCE DATE
962         IDIVI A,UFDBPW          ;GET WRD AND CHAR ADRS
963         HLLZ B,QBTBLI(B)
964         ADDI B,UDDESC(A)
965         HRRZ A,QSNLCN(H)
966         ADD B,A
967         ILDB A,B
968         SKIPE A
969          BUG                    ;DESCRIPTOR AREA ALREADY OCCUPIED
970         MOVEI A,UDWPH
971         DPB A,B
972         ILDB A,B
973         SKIPE A
974          BUG                    ;NOT FOLLOWED BY ZERO
975         POP P,I
976         POP P,B
977         POP P,A
978         MOVEM A,UNFN1(Q)        ;SET FILE NAMES
979         MOVEM B,UNFN2(Q)
980         JRST POPJ1
981
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.
984          JFCL
985         MOVNI I,1       ;SIGNAL GC HAS BEEN TRIED
986         JRST QFREFA
987 \f
988 ;MAKE ROOM FOR FILE BEFORE J.  Q POINTS TO NEW EMPTY FILE SLOT
989 QINSRT: PUSH P,A
990         PUSH P,TT
991         HRRZ TT,QSNLCN(H)
992         HRRZ A,UDNAMP(TT)
993         PUSH P,A
994         ADDI A,(TT)
995         HRLS A
996         SUBI A,LUNBLK
997         BLT A,-LUNBLK-1(J)
998         SETZM -LUNBLK(J)
999         HRRZI A,-LUNBLK+1(J)
1000         HRLI A,-LUNBLK(J)
1001         BLT A,-1(J)
1002         SUB J,QSNLCN(H)
1003         MOVSI A,-NQCHN
1004 QINSR1: HRRZ TT,QUDPR(A)
1005         SKIPL QUSR(A)
1006         CAIE TT,(H)
1007         JRST QINSR2
1008         MOVE TT,QUDFPR(A)
1009         CAMGE TT,(P)
1010         JRST QINSR2
1011         CAIGE TT,(J)
1012         SUBI TT,LUNBLK
1013         MOVEM TT,QUDFPR(A)
1014 QINSR2: AOBJN A,QINSR1
1015         ADD J,QSNLCN(H)
1016         HRRZI Q,-LUNBLK(J)
1017         SUB P,[1,,1]
1018         POP P,TT
1019         POP P,A
1020         POPJ P,
1021 \f
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.
1025
1026 QSKO1:  PUSHJ P,SWTL
1027             QSKOSW      ;PREVENT TIMING ERROR IF TWO PCS SHOULD
1028         PUSHJ P,QFLD    ; ATTEMPT TO BRING IN SAME DIRECTORY
1029          JRST QSKO11
1030         MOVEI T,2       ;SOMEONE ELSE BROUGHT IT IN, RELEASE QSKOSW
1031         JRST LSWPON     ;BUT LEAVE QSNNR(H) LOCKED.
1032
1033 QSKO11: PUSH P,J
1034         PUSH P,I
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
1038         MOVE I,MDSK
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
1042         MOVEI TT,%QMUDR
1043         MOVEM TT,QSRAC(E)
1044 QSKON1: MOVEI T,2
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
1048         JRST QSTRTR
1049
1050 QNOFRE: POP P,I         ;NO FREE FILES AVAIL
1051         JRST POPBAJ
1052
1053 QPNL24: PUSHJ P,OPNL24
1054         JRST URET
1055
1056 QPNL20: PUSHJ P,OPNL20
1057         SKIPE QLD(U)
1058          PUSHJ P,OPNL47 ;FOUND LINK, BUT IT POINTS TO NON-EXISTENT DIRECTORY
1059         JRST URET
1060
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
1067 NATOCR==.-AUTOCR
1068 \f
1069 QSKON:  JUMPE C,QPNL20  ;DON'T ALLOW ZERO USER NAME
1070         PUSH P,TT
1071         MOVSI TT,-NATOCR
1072 QSKONA: CAMN C,AUTOCR(TT)
1073          JRST QSKONB
1074         AOBJN TT,QSKONA
1075         CAMN A,[SIXBIT /..NEW./]
1076          CAME B,[SIXBIT /(UDIR)/]
1077           JRST [POP P,TT
1078                 JRST QPNL20]
1079         BUG INFO,[DSK: DIR ],SIXBIT,C,[CREATED BY ],SIXBIT,UNAME(U),SIXBIT,JNAME(U) 
1080 QSKONB: POP P,TT
1081         SKIPG NQFUS
1082          JRST QPNL24    ;NO MFD SLOTS AVAILABLE
1083         PUSH P,A
1084         PUSH P,B
1085         PUSH P,C
1086 QSKONE: PUSHJ P,QFLDF   ;FIND FREE DIR SLOT
1087         PUSHJ P,QMLOCK
1088         PUSHJ P,TCALL
1089          JRST IOMQ
1090           JRST [PUSHJ P,LSWPOP  ;QMDRO
1091                 PUSHJ P,LSWPOP  ;QSNNR
1092                 PUSHJ P,UDELAY  ;HOPEFULLY MEMORY WILL APPEAR SHORTLY
1093                 JRST QSKONE]
1094         MOVEM C,QSNUD(H)
1095         SOS NQFUS       ;NO TIMING ERR DUE TO QSKOSW
1096         MOVEI J,MU23UD
1097         DPB J,[MUR,,MEMBLT(A)]
1098         DPB H,[MNUMB,,MEMBLT(A)]
1099         LSH A,10.
1100         HRRM A,QSNLCN(H)
1101         SETZM (A)
1102         HRLS A
1103         AOS B,A
1104         BLT A,2000-2(B)
1105         MOVEI A,2000
1106         MOVEM A,UDNAMP-1(B)
1107         MOVE A,QSNUD(H)
1108         MOVEM A,UDNAME-1(B)
1109         MOVE B,QACTB            ;NOW PUT UFD INTO MFD
1110         IORB B,QMDRO
1111         MOVE TT,MDNAMP(B)       ;LOOK FOR A FREE SLOT
1112         ADDI TT,(B)
1113 QSKONC: TRNN TT,1777
1114          JRST QSKOND
1115         SKIPN MNUNAM(TT)
1116          JRST QSKONF
1117         ADDI TT,LMNBLK
1118         JRST QSKONC
1119
1120 QSKONF: SUBI TT,(B)
1121         JRST QSKONG
1122
1123 QSKOND: MOVNI TT,LMNBLK         ;NO FREE SLOTS, SO EXTEND DOWNWARD
1124         ADDB TT,MDNAMP(B)
1125 QSKONG: ADDI B,(TT)
1126         MOVEM A,MNUNAM(B)
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)
1131         LSH TT,-1
1132         MOVEM TT,QSNMI(H)       
1133         MOVE TT,QACTB           ;UNLOCK UFD AND CAUSE IT TO GET WRITTEN
1134         HLLM TT,QSNLCN(H)
1135         PUSHJ P,QMULK           ;UNLOCK MFD
1136         POP P,C
1137         POP P,B
1138         POP P,A
1139         JRST QSKON1
1140 \f
1141 SUBTTL MAKE LINK
1142
1143 QALINK: MOVE I,MDSK     ;ENTER WITH QSNNR ON LSWPR
1144         MOVEM I,EPDL(U)
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
1150         PUSHJ P,LDEP
1151          PUSHJ P,QUDS
1152         MOVE C,SRN3(U)  ;FN1 LINKED TO
1153         PUSHJ P,LDEP
1154          PUSHJ P,QUDS
1155         MOVE C,SRN4(U)  ;FN2 LINKED TO
1156         PUSHJ P,LDEP
1157          JFCL
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
1163         JRST POPJ1
1164
1165 LDEP:   MOVEI E,6       ;STORE SIXBIT FROM C INTO LINK DESC
1166 LDEPL:  MOVEI B,0       ;GET NEXT CHAR
1167         LSHC B,6
1168         JUMPE B,LDEPS   ;*THIS ALLOWS EMBEDDED BLANKS.
1169         CAIE B,';
1170          CAIN B,':
1171          JRST LDEPS
1172 LDEPS2: MOVE D,B
1173         PUSHJ P,QUDS
1174         SOS E           ;NUMBER OF CHARACTERS LEFT IN WORD
1175         JUMPN C,LDEPL   ;JUMP IF ANY MORE NON-BLANK CHARS TO STORE
1176         MOVEI D,';
1177         JUMPE E,POPJ1   ;JUMP IF STORED 6 CHARACTERS
1178         POPJ P,         ;STORED FEWER, NEED TERMINATOR
1179
1180 LDEPS:  MOVEI D,':      ;THIS CHAR NEEDS TO BE QUOTED
1181         PUSHJ P,QUDS
1182         JRST LDEPS2
1183 \f
1184 ;LINK ENCOUNTERED DURING LOOKUP
1185
1186 QLINK:  TRNE D,%DONLK/2 ;CHECK 3.5 BIT IN OPEN MODE
1187          JRST QOLINK    ;JUMP IF DON'T CHASE LINKS MODE
1188         AOS A,QLD(U)
1189         CAIL A,100.
1190          JRST OPNL27    ;LINK DEPTH EXCEEDED
1191         PUSH P,E        ;SAVE XR NEEDED BY LSWPOP OF QUSR ENTRY
1192         MOVE E,TT
1193         IDIVI E,UFDBPW
1194         ADD E,QSNLCN(H)
1195         ADDI E,UDDESC
1196         MOVE TT,QBTBLI(TT)
1197         HRR TT,E
1198         MOVE I,[440600,,A]
1199         SETZB A,B
1200         SETZ C,
1201 QL1:    ILDB J,TT
1202         JUMPE J,QL3     ;END DESC
1203         CAIN J,':
1204          JRST QL4       ;QUOTE NEXT CHAR
1205         CAIN J,';
1206          TLZA I,770000  ;TERMINATE THIS WORD
1207 QL5:      IDPB J,I
1208         JRST QL1
1209
1210 QL4:    ILDB J,TT       ;GET CHAR THAT WAS QUOTED
1211         JRST QL5
1212
1213 QL3:    EXCH A,C        ;END OF DESC REACHED
1214         EXCH A,B        ;MAKE A FN1 B FN2 C SNM
1215         SKIPN C
1216          MOVE C,USYSN1(U)
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
1222         JRST QSKOL
1223
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
1228 \f
1229 SUBTTL PAW OVER MFD
1230
1231 QMCH1:  CONO PI,UTCOFF
1232         MOVE TT,QMDRO
1233         TLNE TT,40000
1234         AOJE TT,QMCH2   ;NOT ON WAY IN
1235 QMCH3:  CONO PI,UTCON
1236         SKIPGE QMDRO
1237          PUSHJ P,UFLS
1238         MOVSI E,2
1239         TDNN E,QMDRO
1240          POPJ P,        ;PAWED OVER
1241         PUSHJ P,QMLOCK
1242         ANDCAM E,QMDRO
1243         HRRZ E,QMDRO
1244         MOVE TT,MDCHK(E)
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
1249 IFE KA10P,[
1250         MOVNI TT,2              ;PROTECT DEC 'HOM' BLOCKS SO KLDCP OR 8080
1251         MOVEM TT,NQFUS          ; CAN FIND ITS CRUFT
1252 ] ;IFE KA10P
1253 QMCH1E: LDB TT,[1200,,E]
1254         JUMPE TT,QMULK
1255         SKIPN (E)
1256          AOS NQFUS
1257         ADDI E,LMNBLK
1258         JRST QMCH1E
1259
1260 QMCH2:  SOS QMDRO       ;INDICATE ON WAY IN
1261         CONO PI,UTCON
1262         SKIPG QFCHN
1263          BUG            ;DON'T WANT TO WAIT FOR CHANNEL?
1264         PUSHJ P,QCHNF
1265         MOVEI TT,MFDBLK ;MFD TRACK
1266         MOVEM TT,QSLGL(E)
1267         MOVEI TT,%QMMDR
1268         MOVEM TT,QSRAC(E)
1269         PUSHJ P,QSTRTR
1270         JRST QMCH3
1271 \f
1272 SUBTTL PAW OVER TUT
1273
1274 QTCH1:  CONO PI,UTCOFF
1275         MOVSI TT,200000
1276         TDNE TT,QTUTO(I)
1277          JRST QTCH2     ;GO READ IT IN
1278         CONO PI,UTCON
1279 QTCH1A: PUSHJ P,QTLOCK  ;TO MAKE SURE IT'S IN
1280         AOSE QDPWF(I)
1281          JRST QTULK     ;ALREADY PAWED OVER
1282         PUSH P,A
1283         PUSH P,B
1284         MOVE T,QTUTO(I)
1285         MOVE E,QSWAPA(T)
1286         IDIVI E,DECADE
1287         SKIPE TT
1288          ADDI E,1
1289         IMULI E,DECADE  ;ROUND SWAPPING ALLOC TO MULTIPLE OF A DECADE
1290         MOVEM E,QSWAPA(T)
1291         PUSH P,D
1292         PUSH P,E        ;FIRST TRACK OF NON-SWAPPING (FILE) AREA
1293         MOVE E,QTUTP(T) ;ROUND TUT POINTER TO MULTIPLE OF A DECADE
1294         ADDI E,DECADE-1
1295         IDIVI E,DECADE
1296         IMULI E,DECADE
1297         CAMGE E,(P)     ;KEEP IT WITHIN THE FILE AREA
1298          MOVE E,(P)
1299         MOVEM E,QTUTP(T)
1300         MOVE E,QPKNUM(T)
1301 IFN DC10P,[
1302         CAME E,QPKID(I)
1303          BUG HALT,[PACK ID ],OCT,E,[IN TUT FOR UNIT ],DEC,I,[DIFFERS FROM HARDWARE PACK ID],OCT,QPKID(I)
1304 ]
1305 IFE DC10P,      MOVEM E,QPKID(I)
1306         MOVE E,QPAKID(T)
1307         MOVEM E,QPKNM(I)
1308 IFN QRSRVP,[
1309         MOVE E,QTRSRV(T)
1310         MOVEM E,QRESRV(I)
1311 ]
1312 ;DROPS THROUGH
1313 \f;DROPS IN
1314         CLEARM QSFTS(I) ;FREE SPACE IN SWAPPING AREA
1315         SETZB D,QSFT(I)
1316         MOVE B,QTUTO(I)
1317         HRLI B,(TUTBP)
1318         ADDI B,LTIBLK
1319 QTCH1D: ILDB A,B
1320         JUMPN A,QTCH1F
1321         CAML D,(P)
1322          AOS QSFT(I)    ;BLOCK IN NON-SWAPPING AREA
1323         CAMGE D,(P)
1324          AOS QSFTS(I)   ;BLOCK IN SWAPPING AREA
1325 QTCH1F: ADDI D,1
1326         CAMGE D,QLASTB(T)
1327          JRST QTCH1D
1328         SUB P,[1,,1]
1329         POP P,D
1330         POP P,B
1331         POP P,A
1332         JRST QTULK
1333
1334 QTCH2:  SETOM QDPWF(I)
1335         ANDCAM TT,QTUTO(I)
1336         CONO PI,UTCON
1337         SKIPG QFCHN
1338          BUG                    ;DON'T WANT TO WAIT FOR CHANNEL?
1339         PUSHJ P,QCHNF
1340         HRRZM I,QDSKN(E)
1341         MOVEI TT,MFDBLK         ;TELL PI LEVEL TO READ IT ALL IN
1342         SUB TT,NTBL(I)
1343         MOVEM TT,QSLGL(E)
1344         LDB TT,[121000,,QTUTO(I)]
1345         MOVEM TT,QSCABN(E)
1346         MOVEI TT,%QMTTR
1347         MOVEM TT,QSRAC(E)
1348         PUSHJ P,QSTRTR
1349         JRST QTCH1A
1350
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.
1355 ;CLOBBERS E
1356 ;CALLER MUST LOCK TUT
1357
1358 TUTPNT: MOVE B,QTUTO(I)
1359         CAML D,QFRSTB(B)
1360         CAML D,QLASTB(B)        
1361          BUG                    ;BLOCK NUMBER NOT IN RANGE COVERED BY TUT
1362         SUB D,QFRSTB(B)
1363         IDIVI D,TUTEPW
1364         ADDI D,LTIBLK(B)
1365         HLL D,TBTBL(E)
1366         LDB B,D
1367         POPJ P,
1368 \f
1369 QSTRTR:
1370 IFN DC10P,[
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
1374 ]
1375 IFN RP10P+RH10P+RH11P,[
1376         CONO PI,UTCOFF
1377         PUSHJ P,QSTRT1
1378         CONO PI,UTCON
1379 ]
1380         POPJ P,
1381
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
1388          CONO PI,DSKRQ
1389         POPJ P,
1390 ]
1391
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)
1398          SKIPE QSNNR(H)
1399 QDFLS2:   AOBJN H,QDFLS1        ;CAN'T FLUSH IF SLOT NOT USED OR CHANNELS OPEN IN DIR
1400         JUMPGE H,CPOPJ
1401         MOVE TT,QACTB
1402         TLO TT,600000
1403         TDNE TT,QSNLCN(H)
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
1407         AOS QFUD
1408         PUSH P,A
1409         HRRZ A,QSNLCN(H)
1410         LSH A,-10.
1411         PUSHJ P,(C)             ;RETURN THE MEMORY
1412         POP P,A
1413         JRST QDFLS2             ;TRY FLUSHING SOME MORE
1414
1415 ;CALL WITH UFD SLOT# IN H, WHEN YOU THINK THAT UFD IS FREE.
1416 QDFCHK: PUSH P,C
1417         PUSH P,J
1418         MOVSI C,-NQCHN
1419 QDFCH1: SKIPGE QUSR(C)
1420          AOBJN C,QDFCH1
1421         JUMPGE C,QDFCH2
1422         HRRZ J,QUDPR(C)
1423         CAIN J,(H)
1424          BUG            ;IT WASN'T REALLY FREE, MAYBE QSNNR IS SCREWED UP?
1425         AOBJN C,QDFCH1
1426 QDFCH2: POP P,J
1427         POP P,C
1428         POPJ P,
1429 \f
1430 ;FIND A FREE UFD SLOT, RETURN INDEX IN H.  PUTS QSNNR ON LSWPR.
1431 ;CLOBBERS T, TT.
1432
1433 QFLDF:  PUSHJ P,SWTL
1434             UDRSW
1435         MOVSI H,-QNUD
1436         SKIPLE QFUD
1437          JRST QFLDF1
1438         PUSH P,C        ;ALL UFD SLOTS IN USE, TRY FLUSHING SOME
1439         MOVEI C,MEMR
1440         PUSHJ P,QDFLS
1441         POP P,C
1442         MOVSI H,-QNUD
1443         SKIPLE QFUD
1444          JRST QFLDF1
1445         PUSHJ P,LSWPOP  ;UDRSW
1446         PUSHJ P,UDELAY  ;WAIT 1/2 SECOND THEN TRY AGAIN, INCLUDING QDFLS
1447         JRST QFLDF
1448
1449 QFLDF1: SKIPN QSNNR(H)  ;SLOT ALREADY GOBBLED
1450          SKIPE QSNUD(H) ;OR ALREADY OCCUPIED
1451           AOBJN H,QFLDF1 ;MEANS CAN'T TAKE IT
1452         SKIPL H
1453          BUG            ;NONE FREE, QFUD OUT OF PHASE WITH REALITY
1454         HRRZS H
1455         SOS QFUD
1456         MOVSI TT,600000 ;DOUBLE LOCK
1457         MOVEM TT,QSNLCN(H)
1458         AOSG QSNNR(H)
1459          BUG
1460         PUSHJ P,LSWPOP  ;UDRSW
1461         PUSHJ P,LOSSET
1462             QFLDRT
1463         POPJ P,
1464
1465 ;LOSSET ROUTINE
1466 QFLDRT: SKIPL A,AC0S+H(U)
1467          CAIL A,QNUD
1468           BUG           ;H CLOBBERED
1469         SOSGE T,QSNNR(A)
1470          BUG
1471         JUMPG T,CPOPJ   ;HOW DID SOMEONE ELSE GET IT?
1472         SKIPN QSNUD(A)
1473          AOS QFUD       ;READ-IN NEVER STARTED, SLOT BECOMES FREE
1474         POPJ P,         ;OK TO LEAVE 600000,, SET IN QSNLCN
1475
1476 ;C HAS DIR NAME.
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.
1479 QFLD:   PUSHJ P,SWTL
1480             UDRSW
1481 QFLD1A: MOVSI H,-QNUD
1482 QFLD1:  CAME C,QSNUD(H)
1483          AOBJN H,QFLD1
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
1488 ;       PUSHJ P,SOSSET
1489 ;           QSNNR(H)
1490 ;THIS IS AN ATTEMPT TO FIND A BUG.
1491         PUSH P,T
1492         MOVEI T,QSNNR(H)
1493         MOVEM T,IOTBTS(U)
1494         PUSHJ P,LOSSET
1495             [ SOSGE @IOTBTS(U)
1496                BUG
1497               POPJ P, ]
1498         POP P,T
1499 ;END TEMPORARY CODE
1500         JRST POPJ1
1501 \f
1502 ;C <=SYS NAME,   RETURNS TRACK ADDR OF DIR IN J, SKIPS IF FINDS LOSER
1503 QFL:    PUSHJ P,QMLOCK
1504         PUSHJ P,QFL0
1505          JRST QMULK
1506         AOS (P)
1507         JRST QMULK      
1508
1509 QFL0:   PUSH P,Q
1510         HRRZ Q,QMDRO
1511         ADD Q,MDNAMP(Q) ;PTR TO USER AREA
1512 QFL1:   LDB J,[1200,,Q]
1513         JUMPE J,QFL3
1514         CAMN C,MNUNAM(Q)
1515          JRST QFL2
1516         ADDI Q,LMNBLK
1517         JRST QFL1
1518
1519 QFL2:   SUBI J,2000-LMNBLK*NUDSL        ;J <= TRACK ADDR OF USER DIR
1520         LSH J,-1
1521         AOS -1(P)       ;SUCCESS
1522 QFL3:   POP P,Q
1523         POPJ P,
1524
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.
1530
1531 QCHNF:  PUSHJ P,SWTL    ;PREVENT ANYONE ELSE FROM ALLOCATING CHANNELS
1532             QCHSW
1533         MOVSI E,-NQCHN
1534         SKIPLE QFCHN
1535          JRST QCH2      ;SOME CHANNELS ARE AVAILABLE, GO FIND ONE
1536         PUSHJ P,LSWPOP  ;QCHSW
1537         SKIPG QFCHN
1538          PUSHJ P,UFLS
1539         JRST QCHNF
1540
1541 QCH2:   SKIPGE QSRAC(E) .SEE %QALOK
1542          JRST QCH3
1543         SKIPGE QUSR(E)
1544          JRST QCH1
1545 QCH3:   AOBJN E,QCH2
1546         BUG             ;WHERE DID THAT FREE CHANNEL GO?
1547
1548 QCH1:   HRRZS E         ;CHANNEL ALLOCATED, INITIALIZE VARIABLES
1549         HRRZM I,QDSKN(E)
1550         SETOM QSCABN(E)
1551         SETOM QSGL(E)
1552         SETOM QSLGL(E)  ;IN CASE OF WRITE-OVER ON 0-LENGTH FILE.
1553         SETZM QBFP(E)
1554         SETZM QSBFS(E)
1555         CLEARM QSLBLK(E)
1556         SETOM QSMDN(E)
1557         SETZM QSCRW(E)
1558         SETZM QSBI(E)
1559         SETZM QSRAC(E)  .SEE %QMIDL
1560         CLEARM QFBLNO(E)
1561         SETZM QSMPRC(E)
1562         SETZM QSMPRP(E)
1563         MOVE T,[444400,,1]      ;ASSUME BYTES=WORDS, WILL BE FIXED LATER
1564         MOVEM T,QSBYTE(E)
1565         SETZM QPCLSR(E)
1566         HRRZM H,QUDPR(E)
1567         SETZM QUDFPR(E) ;NOT YET SET UP TO ANY PARTICULAR FILE
1568         MOVEM U,QUSR(E) ;CHANNEL IS NOW IN-USE
1569         SOSGE QFCHN
1570          BUG
1571         JRST LSWPOP     ;QCHSW
1572
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)
1576          CAIL T,NQCHN
1577           BUG           ;E CLOBBERED
1578         HRRZ A,U        ;LSWPOP MESSES WITH LH(U)
1579         CAME A,QUSR(T)
1580          BUG
1581         SETOM QUSR(T)
1582         AOS QFCHN
1583         POPJ P,
1584 \f
1585 SUBTTL DELETE, RENAME
1586 ;COME HERE FOR DELETE, OR RENAME NOT WHILE OPEN, ON DISK.
1587
1588 QRNAM:  SKIPN SRN3(U)
1589          JRST QDEL
1590         PUSH P,A
1591         PUSH P,B
1592         SKIPN B,SRN4(U)
1593          JRST QPNL11
1594         MOVE A,SRN3(U)
1595         PUSHJ P,MFDCK
1596          JRST .+2
1597           JRST QPNL13
1598         PUSHJ P,FLDRCK
1599          JRST .+2
1600           JRST QPNL13
1601         POP P,B
1602         POP P,A
1603         PUSH P,SRN3(U)
1604         PUSH P,SRN4(U)
1605         PUSHJ P,QUDLK
1606         PUSHJ P,QLOOK
1607          JRST [ SUB P,[2,,2]
1608                 JRST QROR1C ]   ;GIVE FILE NOT FOUND OR FILE LOCKED
1609         MOVE I,Q
1610         POP P,B
1611         POP P,A
1612         PUSHJ P,QGRLSC
1613          JRST QPNLBN    ;FILE ALREADY EXISTS
1614         PUSHJ P,QFNG
1615 QRNAM4: PUSHJ P,QLOOK
1616          JRST QRNAM3
1617         CAME I,Q        ;ALLOW RENAME THAT DOESN'T CHANGE NAMES.
1618          JRST QPNL13
1619 QRNAM3: MOVE Q,I
1620         MOVSI TT,UNDUMP ;SAY FILE NOT DUMPED.
1621         ANDCAM TT,UNRNDM(Q)
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
1626         IORM TT,QSNLCN(H)
1627 QRNAM1: MOVE U,USER     ;U MAY NOT HAVE USER IF CAME HERE FROM LOGOUT
1628         PUSHJ P,LSWCLR
1629         JRST POPJ1
1630
1631 QGRLSC: CAME A,[SIXBIT />/]     ;SKIP NONE IF BOTH A+B ARE SPECIAL
1632         CAMN A,[SIXBIT /</]     ;ONCE IF ONE IS
1633          SOS (P)
1634         CAME B,[SIXBIT />/]     ;AND TWICE IF NEITHER
1635         CAMN B,[SIXBIT /</]
1636          SOS (P)
1637         AOS (P)
1638         JRST POPJ1
1639
1640 \f
1641 ;MOVE FILE POINTED TO BY Q SO THAT NEW NAMES A AND B WILL BE IN
1642 ;ALPHABETICAL ORDER
1643 QRELOC: PUSH P,TT
1644         PUSH P,E
1645         PUSH P,J
1646         PUSH P,Q
1647         PUSH P,D
1648         PUSH P,W
1649         PUSH P,R
1650         PUSHJ P,QLGLK   ;SEE WHERE FILE MUST GO
1651          BUG            ;DIR WAS EMPTY
1652         HRRZ TT,QSNLCN(H)
1653 QRLOCK: CAIL J,2000(TT)
1654          JRST QRLOCJ
1655         CAMN A,UNFN1(J)
1656         CAME B,UNFN2(J)
1657          JRST QRLOCJ
1658         MOVE Q,UNRNDM(J)
1659         TLNE Q,UNIGFL
1660          JRST QRLOCJ
1661         ADDI J,LUNBLK
1662         JRST QRLOCK
1663
1664 QRLOCJ: HRRZ Q,-3(P)    ;WHERE FILE IS NOW
1665         CAIE J,LUNBLK(Q)
1666          CAMN J,Q
1667           JRST QRLOCS   ;SAME PLACE
1668 REPEAT LUNBLK,  PUSH P,.RPCNT(Q)
1669         CAMG Q,J
1670          JRST QRLOCB
1671         MOVEI TT,(Q)
1672 QRLOCC: SUBI TT,LUNBLK
1673         HRLZ D,TT
1674         HRRI D,LUNBLK(TT)
1675         BLT D,2*LUNBLK-1(TT)
1676         CAILE TT,(J)
1677          JRST QRLOCC
1678 QRLOCA:
1679 REPEAT LUNBLK,  POP P,LUNBLK-.RPCNT-1(J)
1680         MOVEM A,UNFN1(J)
1681         MOVEM B,UNFN2(J)
1682         HRRZ TT,QSNLCN(H)
1683         SUB Q,TT
1684         SUB J,TT
1685         CAML J,Q
1686          JRST QRLOCD
1687         MOVEI D,LUNBLK
1688         HRRZ W,J
1689         HRRZ R,Q
1690 QRLOCE: MOVSI TT,-NQCHN
1691 QRLOCF: HRRZ E,QUDPR(TT)
1692         SKIPL QUSR(TT)
1693          CAIE E,(H)
1694           JRST QRLOCG
1695         HRRZ E,QUDFPR(TT)
1696         CAIN E,(Q)
1697          JRST QRLOCI
1698         CAIL E,(W)
1699          CAIL E,(R)
1700           JRST QRLOCG
1701         ADD E,D
1702         HRRZM E,QUDFPR(TT)
1703 QRLOCG: AOBJN TT,QRLOCF
1704 QRLOCH: POP P,R
1705         POP P,W
1706         POP P,D
1707         POP P,Q
1708         POP P,J
1709         POP P,E
1710         POP P,TT
1711         POPJ P,
1712
1713 QRLOCB: HRRZ D,Q
1714         HRLI D,LUNBLK(Q)
1715         BLT D,-1-LUNBLK(J)
1716         SUBI J,LUNBLK
1717         JRST QRLOCA
1718
1719 QRLOCD: MOVNI D,LUNBLK
1720         HRRZI W,LUNBLK(Q)
1721         HRRZI R,LUNBLK(J)
1722         JRST QRLOCE
1723
1724 QRLOCI: HRRZM J,QUDFPR(TT)
1725         JRST QRLOCG
1726
1727 QRLOCS: MOVEM A,UNFN1(Q)
1728         MOVEM B,UNFN2(Q)
1729         JRST QRLOCH
1730 \f
1731 QDEL:   PUSHJ P,QUDLK
1732         PUSHJ P,QLOOK
1733          JRST QDFNF
1734         MOVE TT,UNRNDM(Q)
1735         TLNE TT,UNLINK
1736          JRST QDEL5A
1737         LDB J,[UNPKN+UNRNDM(Q)]
1738 QDELTA: MOVSI I,-NQS
1739         CAME J,QPKID(I)
1740          AOBJN I,.-1
1741         JUMPGE I,QPKNF6 ;PACK OF FILE NOT MOUNTED
1742 QDEL5:  PUSHJ P,QUDULK
1743         PUSHJ P,QDELA
1744          JRST QDFNF     ;GONE AWAY BETWEEN LOCKS
1745         JRST QRNAM1
1746
1747 QDEL5A: ;DELETE LINK
1748         MOVE I,MDSK     ;RANDOM EXISTANT UNIT
1749         JRST QDEL5
1750
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
1760         IDIVI A,UFDBPW
1761         ADD A,QSNLCN(H)
1762         ADDI A,UDDESC
1763         HLL A,QBTBLI(B)
1764         MOVEI C,0
1765 QNFDL2: ILDB B,A
1766         DPB C,A
1767         TRNE B,40
1768          JRST QNFDL3
1769         JUMPN B,QNFDL2
1770         JRST QRNAM2
1771
1772 QNFDL3: REPEAT NXLBYT,[IDPB C,A
1773 ]
1774         JRST QNFDL2
1775
1776 IFN QAUTHP,[
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.
1781         MOVE J,QSNMI(H)
1782         MOVE C,UNAME(U)
1783         CAMN C,QSNUD(H)
1784          JRST QAUTH1    ;UNAME = SNAME
1785         PUSHJ P,QFL0
1786          SKIPA          ;NOT FOUND IN MFD
1787           JRST QAUTH1
1788         SETZM C
1789         MOVEI J,5       ;STRIP OFF ANY NUMERICS
1790         MOVE TT,[440600,,UNAME(U)]
1791         MOVE I,[440600,,C]
1792         ILDB B,TT
1793         IDPB B,I
1794 QAUTH2: ILDB B,TT
1795         CAIG B,'Z
1796         CAIGE B,'A
1797          JRST QAUTH3
1798         IDPB B,I
1799         SOJG J,QAUTH2
1800         SKIPA           ;NO NON-LETTERS
1801
1802 QAUTH3: PUSHJ P,QFL0
1803          SKIPA C,HSNAME(U)      ;CAN'T CONVERT UNAME IN ANY FORM, TRY HSNAME AS LAST RESORT
1804           JRST QAUTH1
1805         PUSHJ P,QFL0
1806          SETOM J                ;CAN'T ENCODE AUTHOR AT ALL
1807 QAUTH1: DPB J,[UNAUTH+UNREF(Q)]
1808         POP P,I
1809         POP P,J
1810         POP P,C
1811         POP P,B
1812         POPJ P,
1813 ]               ;END IFN QAUTHP
1814 .ELSE QAUTH==CPOPJ
1815 \f
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
1819 QDELA:  MOVEI Q,0
1820 QDLA1:  PUSHJ P,SLUGH
1821             QCHSW
1822             1000,,QSNLCN(H)
1823             1000,,QTUTO(I)
1824         JUMPN Q,QDLA2
1825         PUSHJ P,QLOOK
1826          JRST QDEL4A    ;FNF
1827         SETO D,         ;NO ASSOCIATED CHANNEL
1828 QDLA3:  LDB A,[UNLNKB+UNRNDM(Q)]
1829         LDB TT,[UNPKN+UNRNDM(Q)]
1830         CAME TT,J
1831          JUMPE A,QDELA1 ;ON DIFFERENT DISK (DIDN'T LOCK RIGHT TUT TRY AGAIN)
1832         MOVE A,Q
1833         SUB A,QSNLCN(H)
1834         MOVSI J,-NQCHN
1835 QDEL1:  CAIN D,(J)
1836          JRST QDEL2     ;IGNORE CHANNEL (IF ANY) WHOSE CLOSING CAUSED THIS
1837         HRRZ TT,QUDPR(J)
1838         SKIPL QSCRW(J)  ;ONLY LOOK AT READ CHNLS
1839          CAIE TT,(H)
1840           JRST QDEL2
1841         HRRZ TT,QUDFPR(J)
1842         SKIPL QUSR(J)
1843          CAIE TT,(A)
1844           JRST QDEL2
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
1848         IORM TT,UNRNDM(Q)
1849 QDEL4:  MOVE TT,QACTB
1850         IORM TT,QSNLCN(H)
1851         MOVE TT,DCHBT(I)
1852         IORM TT,QTUTO(I)
1853 QDEL4B: PUSHJ P,QTULK
1854         PUSHJ P,QUDULK
1855         PUSHJ P,LSWPOP
1856         JRST POPJ1
1857
1858 QDLA2:  MOVE Q,QUDFPR(D)        ;COMPUTE FILE ADR FROM CHNL IN D
1859         ADD Q,QSNLCN(H) ;DIR MAY HAVE MOVED
1860         JRST QDLA3
1861
1862 QDEL4A: SOS (P)
1863         JRST QDEL4B
1864 \f
1865 QCDLWO: PUSH P,R        ;OUTPUT CLOSE BUT FILE WAS DELEWO'ED
1866         SETZM QSCRW(D)  ;FAKE OUT ERROR CHECK AT QSQSH6
1867         PUSHJ P,QUDULK
1868 QSICLD: MOVE H,QUDPR(D) ;ENTRY FROM INPUT CLOSE, FILE WAS DELETED
1869         MOVE I,QDSKN(D)
1870         PUSHJ P,QUDLK
1871         MOVE Q,QSNLCN(H)
1872         ADD Q,QUDFPR(D)
1873         MOVE J,QPKID(I)
1874         PUSHJ P,QUDULK
1875         PUSH P,D
1876         PUSHJ P,QDLA1
1877          BUG            ;FILE ISNT THERE?
1878         POP P,D
1879         MOVE H,QUDPR(D) ;DIRECTORY NUMBER
1880         SETOM QUSR(D)   ;FREE THE DISK CHANNEL
1881         AOS QFCHN
1882         JRST QICLX
1883
1884 QDELA1: PUSHJ P,QDEL4B  ;NOT OUR DISK IN J
1885          JFCL
1886         MOVE J,TT       ;DISK ITS REALLY ON
1887 QDELA2: MOVSI I,-NQS    ;TRANSLATE PACK # IN J TO DRIVE # IN I
1888         CAME J,QPKID(I)
1889           AOBJN I,.-1
1890         JUMPGE I,QPKNF1
1891         JRST QDELA
1892
1893 QSOCLD: PUSH P,D        ;DELETE FILE WHEN CLOSING OVER IT
1894         PUSH P,R
1895         LDB J,[UNPKN+UNRNDM(Q)]
1896         PUSHJ P,QUDULK
1897         PUSHJ P,QDELA2
1898          JFCL
1899 QPKNF7: POP P,R
1900         POP P,D
1901         POPJ P,
1902
1903 QPKNF1: PUSHJ P,QPKNFP  ;MAYBE TUT NOT IN YET?
1904          JRST QDELA2    ;YUP, TRY AGAIN
1905         PUSHJ P,QUDLK
1906         PUSHJ P,QLOOK
1907          JRST QUDULK    ;GONE AWAY BETWEEN LOCKS
1908         JRST QDFPK      ;GO DELETE OFF OF NON-MOUNTED PACK
1909
1910 QDL2:   PUSHJ P,QTULK   ;DELETE LINK
1911         MOVEI T,2
1912         PUSHJ P,LSWPON  ;UNLOCK QCHSW
1913 QDLINK: LDB E,[UNDSCP+UNRNDM(Q)]
1914         IDIVI E,UFDBPW
1915         ADD E,QSNLCN(H)
1916         ADDI E,UDDESC
1917         HLL E,QBTBLI(TT)
1918         ILDB A,E
1919         SKIPN E
1920          BUG            ;NULL LINK?
1921         MOVEI B,0
1922 QDL1:   DPB B,E                 ;CLEAR OUT THE CHAR
1923         CAIN A,':
1924          IDPB B,E               ;CLEAR A QUOTED CHAR WITHOUT LOOKING AT IT
1925         ILDB A,E
1926         JUMPN A,QDL1
1927         PUSHJ P,QSQSH   ;REMOVE ENTRY
1928         MOVE TT,QACTB
1929         IORM TT,QSNLCN(H)
1930         PUSHJ P,QUDULK
1931         JRST POPJ1
1932 \f
1933 QDEL2:  AOBJN J,QDEL1           ;CHECK NEXT DISK CHANNEL
1934         MOVE C,UNRNDM(Q)        ;NOT OPEN, SO REALLY DELETE IT
1935         TLNE C,UNLINK
1936          JRST QDL2
1937         ANDI C,.BM UNDSCP
1938         IDIVI C,UFDBPW
1939         ADD C,QSNLCN(H)
1940         ADDI C,UDDESC
1941         HLL C,QBTBLI(D)         ;GET DESCRIPTOR POINTER IN C AND TT
1942         MOVE TT,C
1943         MOVEI A,0
1944         PUSHJ P,NFLLN1          ;A GETS NUMBER OF BLOCKS IN FILE
1945         PUSH P,A
1946         SKIPN D,QSFBT(H)        ;SEE IF ENOUGH QSFBT STORAGE EXISTS
1947          JRST QDEL11
1948 QDEL10: HLRE B,(D)              ;NUMBER OF FREE LOCATIONS IN THIS PAGE
1949         ADD A,B                 ;DECREASE LOCATIONS NEEDED
1950         MOVE D,1(D)             ;CDR
1951         JUMPN D,QDEL10
1952 QDEL11: JUMPLE A,QDEL12         ;JUMP IF SUFFICIENT STORAGE EXISTS
1953         PUSHJ P,TCALL           ;GET MORE
1954             JRST IOMQ
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
1958                  PUSHJ P,UFLS
1959                 JRST UUOTRO ]
1960         MOVEI D,MU23FB
1961         DPB D,[MUR,,MEMBLT(A)]
1962         LSH A,10.
1963         MOVEI D,2(A)
1964         HRLI D,-1776
1965         MOVEM D,(A)
1966         MOVE D,A
1967         EXCH A,QSFBT(H)         ;ADD TO FRONT OF LIST
1968         MOVEM A,1(D)
1969         MOVE A,(P)              ;GET BACK NUMBER OF BLOCKS NEEDED
1970         JRST QDEL10             ;SEE IF THERE ARE ENOUGH NOW
1971
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.
1979         DPB A,C
1980         JUMPE B,QDEL4           ;END OF FILE DESCRIPTION
1981         TRNE B,40
1982          JRST QDEL6
1983         CAILE B,UDTKMX
1984          JRST QDEL7
1985 QDEL8:  SKIPN Q
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
1989                 JRST QDEL8 ]
1990         MOVEM J,(E)             ;STORE DISK,,BLOCK FOR LATER FREEING
1991         AOBJN E,.+1
1992         MOVEM E,(Q)             ;INCREMENT POINTER
1993         MOVE E,QSNLCN(H)        ;DECREASE DIR'S BLOCKS-USED
1994         HRRZ A,UDBLKS(E)
1995         SOSL A
1996          HRRM A,UDBLKS(E)
1997         ILDB A,D                ;CHECK TUT
1998         SKIPN A
1999          BUG                    ;TUT SHOWS TRACK NOT USED
2000         AOS J                   ;DO NEXT BLOCK IN CONTIGUOUS GROUP
2001         SOJG B,QDEL8
2002         JRST QDEL3
2003
2004 IFN NXLBYT-2, .ERR THIS ROUTINE AND OTHERS KNOW IMPLICITLY THAT NXLBYT=2
2005 QDEL6:  MOVEI D,0               ;LOAD ADDRESS
2006         DPB B,[140500,,D]
2007         ILDB B,C
2008         DPB B,[060600,,D]
2009         DPB A,C                 ;A HAS ZERO FROM QDEL3
2010         ILDB B,C
2011         DPB B,[0600,,D]
2012         DPB A,C
2013         MOVE J,D
2014         HRL J,I
2015         PUSHJ P,TUTPNT
2016         ADD D,[TUTBYT_14,,]     ;MAKE INTO ILDB-TYPE POINTER
2017         JRST QDEL7A
2018
2019 QDEL7:  CAIN B,UDWPH
2020          JRST QDEL3
2021         SUBI B,UDTKMX
2022         ADD J,B
2023         IBP D
2024         SOJG B,.-1
2025 QDEL7A: MOVEI B,1       ;LOAD ADDRESS OR SKIP AND TAKE, SO ONLY ONE TRACK
2026         JRST QDEL8
2027
2028 QDFNF:  PUSHJ P,OPNL4
2029         JRST URET
2030
2031 QDELB:  CONO PI,UTCON
2032         JRST QDELA
2033
2034 ;PERFORM BLOCK-FREEING SPECIFIED BY QFBTS
2035 QDLFBT: CONO PI,UTCOFF          ;PROTECT QFBTS
2036         SKIPN B,QFBTS
2037          JRST UTCONJ
2038         MOVE T,1(B)
2039         MOVEM T,QFBTS
2040         CONO PI,UTCON
2041         HRRZ T,(B)              ;FIRST FREE LOCATION
2042         SUBI T,2(B)             ;NUMBER OF LOCATIONS TO DO
2043         HRLO A,T
2044         EQVI A,1(B)
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
2049          JRST QDLFB2
2050         SKIPL I
2051          PUSHJ P,QTULK
2052         MOVE I,J
2053         PUSHJ P,QTLOCK
2054 QDLFB2: HRRZ D,(A)              ;BLOCK NUMBER TO FREE
2055         PUSHJ P,TUTPNT
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
2060         MOVE TT,QTUTO(I)
2061         CAML T,QSWAPA(TT)
2062          AOSA QSFT(I)
2063           AOS QSFTS(I)          ;TRACK IN SWAPPING AREA
2064 QDLFB3: DPB B,D                 ;DECREASE USAGE COUNT IN TUT
2065         AOBJN A,QDLFB1
2066         PUSHJ P,QTULK
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
2070             MU23FB
2071         JRST QDLFBT
2072 \f
2073 ;REMOVE HOLE FROM NAME AREA AT Q
2074 QSQSH:  PUSH P,A
2075         PUSH P,B
2076         PUSH P,C
2077         PUSH P,TT
2078         HRRZ TT,QSNLCN(H)
2079         MOVE A,UDNAMP(TT)
2080         CAILE A,2000
2081          BUG            ;UDNAMP BAD
2082         ADDI A,(TT)
2083         HRRZ C,Q
2084         SUB C,A
2085         SKIPL C
2086         CAIL C,2000-UDDESC
2087          BUG            ;Q BAD
2088         HRRZ C,Q
2089 QSQSH1: SUBI C,LUNBLK
2090         CAMLE A,C
2091          JRST QSQSH2
2092         HRLZ B,C
2093         HRRI B,LUNBLK(C)
2094         BLT B,2*LUNBLK-1(C)
2095         JRST QSQSH1
2096
2097 QSQSH2:
2098 REPEAT LUNBLK,SETZM .RPCNT(A)
2099         SUBI A,-LUNBLK(TT)
2100         HRRZM A,UDNAMP(TT)
2101         HRRZ C,Q
2102         SUBI C,(TT)     ;INDEX OF DELETED FILE
2103         HRRZI TT,-LUNBLK(A)     ;INDEX OF OLD BEGINNING OF NAME AREA
2104         MOVSI A,-NQCHN
2105 QSQSH3: HRRZ B,QUDPR(A)
2106         SKIPL QUSR(A)
2107          CAIE B,(H)
2108           JRST QSQSH4
2109         SKIPN B,QUDFPR(A)
2110          JRST QSQSH4
2111         CAIGE B,(TT)
2112          BUG
2113         CAIN B,(C)
2114          JRST QSQSH6    ;PNTR TO FLUSHED HOLE, CHECK IF READ CHNL
2115         CAIG B,(C)      ;IF AFTER DELETED FILE DON'T RELOCATE
2116          ADDI B,LUNBLK
2117         HRRZM B,QUDFPR(A)
2118         SKIPL QSCRW(A)
2119          JRST QSQSH4    ;READ CHNL
2120         ADD B,QSNLCN(H)
2121         MOVE B,UNRNDM(B)
2122         TLNN B,UNWRIT
2123          BUG            ;CHNL WRITING BUT BEING WRITTEN BIT NOT SET
2124 QSQSH4: AOBJN A,QSQSH3
2125         POP P,TT
2126         POP P,C
2127         POP P,B
2128         POP P,A
2129         POPJ P,
2130
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
2134           BUG
2135         JRST QSQSH4     ;WAS DELETE AFTER CLOSE ON READ CHNL
2136 \f
2137 SUBTTL DIRECTORY LOOK UP, > FEATURE
2138
2139 ;A contains the FN1 and B contains the FN2.
2140 ;H is the index of the directory slot.  The dir must be locked.
2141
2142 ;Returns the address of the filename block in Q.
2143 ;Clobbers C.
2144
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 <.
2150
2151 ;Look for place to create new file,
2152 ;and generate new version for >.
2153 QFNG:   MOVEM Q,EPDL3(U)
2154         SKIPA C,[SETZ]
2155 ;Look for existing files only
2156 QLOOK:   MOVEI C,0
2157         PUSH P,J
2158         HRRZ J,QSNLCN(H)
2159         MOVEI Q,2000-LUNBLK(J)
2160         ADD J,UDNAMP(J)
2161         CAMN A,[SIXBIT />/]
2162          TLOA J,400000
2163           CAMN A,[SIXBIT /</]
2164            JRST QLOOKA  ;4.9 BIT OF J SET IF >
2165         CAMN B,[SIXBIT />/]
2166          TLOA J,400000
2167           CAMN B,[SIXBIT /</]
2168            AOJA C,QLOOK1
2169         PUSHJ P,QLGLK
2170          JRST POPJJ     ;FNF
2171         TRNN J,1777
2172          JRST POPJJ     ;J IS OFF THE END OF THE BLOCK
2173         PUSH P,C
2174         EXCH Q,J
2175 QLK1:   CAMN A,UNFN1(Q)
2176          CAME B,UNFN2(Q)
2177           JRST QLK3     ;FNF
2178         MOVE C,UNRNDM(Q)
2179         TLNN C,UNIGFL   ;BEING WRITTEN OR DELETED
2180          JRST QLK2      ;FOUND IT
2181         SUBI Q,LUNBLK   ;SEARCH THROUGH * FILES
2182         CAML Q,J
2183          JRST QLK1
2184 QLK3:   POP P,C
2185         JRST POPJJ
2186
2187 QLK2:   AOS -2(P)
2188         JRST QLK3
2189
2190 QFNF2:  SUB P,[2,,2]
2191         JRST OPNL4
2192
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
2204         MOVE T,DCHBT(T)
2205         IORM T,QSNLCN(H)
2206         POPJ P,
2207 \f
2208 QLOOKA: CAME B,[SIXBIT /</]
2209         CAMN B,[SIXBIT />/]
2210          JRST POPJJ     ;MUST BE READ RETN FILE NOT FOUND
2211 QLOOK1: JUMPGE C,QLOOK9
2212         CAMN B,[SIXBIT /</]
2213          TLO J,400000   ;IF WRITING, TURN "<" INTO ">"
2214 QLOOK9: PUSH P,D
2215         PUSH P,TT
2216         PUSH P,I
2217         PUSH P,[-1]     ;BEST INDEX
2218         PUSH P,[SETZ]   ;BEST "NUMERIC" PART
2219         PUSH P,[SETZ]   ;BEST ALPHA PART
2220 QLOOK4: CAIGE Q,(J)
2221          JRST QLOOK2
2222         XCT QLKI1(C)
2223          JRST QLOOK3
2224         MOVE D,UNRNDM(Q)
2225         TLNE D,UNIGFL
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
2231           JRST QLOOK5
2232         LSH TT,-6
2233         JRST QLOOK6
2234
2235 QLOOK5: MOVEI I,0
2236 QLOOK8: LDB D,[600,,TT]
2237         CAIL D,'0
2238         CAILE D,'9
2239          JRST QLOOK7    ;NOT A DIGIT
2240 QLOK5B: TRNE I,77       ;RIGHT ADJ LOW NON NUM PART
2241          JRST QLOK5A
2242         LSH I,-6
2243         JUMPN I,QLOK5B
2244 QLOK5A: TLC TT,400000   ;AVOID CAM LOSSAGE
2245         TLC I,400000
2246         SKIPGE -2(P)
2247          JRST QLOK5D    ;FIRST MATCH
2248         JUMPGE J,QLOK5E ;GET LEAST
2249         CAMGE TT,-1(P)  ;GET GREATEST
2250          JRST QLOOK3
2251         CAME TT,-1(P)
2252          JRST QLOK5D
2253         CAMGE I,(P)
2254          JRST QLOOK3    ;NOT AS GOOD
2255 QLOK5D: HRRZM Q,-2(P)
2256         MOVEM TT,-1(P)
2257         MOVEM I,(P)
2258 QLOOK3: SUBI Q,LUNBLK
2259         JRST QLOOK4
2260
2261 QLOK5E: CAMLE TT,-1(P)
2262          JRST QLOOK3
2263         CAME TT,-1(P)
2264          JRST QLOK5D
2265         CAMLE I,(P)
2266          JRST QLOOK3
2267         JRST QLOK5D
2268
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
2273         JRST QLOK5B
2274
2275 QLOOK2: JUMPL C,QFNG1   ;REALLY WANT TO MAKE F.N.'S FOR WRITE
2276         SUB P,[1,,1]
2277         POP P,C ;BEST "NUMERIC" PART
2278         POP P,Q ;ADR
2279         POP P,I
2280         POP P,TT
2281         POP P,D
2282         AOJE Q,POPJJ
2283         MOVE A,UNFN1-1(Q)       ;ACTUAL MATCHED FILE NAMES
2284         MOVE B,UNFN2-1(Q)
2285         SOJGE Q,POPJJ1          ;FOUND A FILE THAT WASN'T LOCKED
2286         MOVEI Q,-LUNBLK(Q)
2287         JRST POPJJ
2288 \f
2289 QFNG1:  SKIPGE -2(P)
2290          JRST QFNG2     ;NOT FOUND START W/ 1
2291         MOVE TT,-1(P)
2292         TLC TT,400000
2293         MOVE I,[600,,TT]
2294 QFNG3:  LDB D,I
2295         CAIL D,'0
2296         CAILE D,'9
2297          JRST QFNG4     ;REACH END OF NUMERIC FIELD
2298         AOS D
2299         CAILE D,'9
2300          JRST QFNG5
2301         DPB D,I
2302 QFNG5A: TLNE TT,770000
2303          JRST QFNG3A
2304         LSH TT,6
2305         JRST QFNG5A
2306
2307 QFNG2:  MOVSI TT,(SIXBIT /1/)
2308 QFNG3A: MOVEM TT,A(C)   ;STORE INTO A OR B AS APPRO
2309         SUB P,[3,,3]
2310         POP P,I
2311         POP P,TT
2312         POP P,D
2313         MOVE Q,EPDL3(U)
2314         JRST POPJJ
2315
2316 QFNG5:  MOVEI D,'0
2317         DPB D,I
2318         ADD I,[60000,,]
2319         JUMPL I,QFNG5A
2320         JRST QFNG3
2321
2322 QFNG4:  TLNN TT,770000  ;SKIP ON ALREADY 6 CHAR NAME
2323          LSH TT,6
2324         MOVEI D,'1
2325         DPB D,I
2326         MOVEI D,'0
2327 QFNG4B: TLNN I,770000
2328          JRST QFNG5A
2329         IDPB D,I
2330         JRST QFNG4B
2331
2332 QLKI1:  CAME B,UNFN2(Q)
2333         CAME A,UNFN1(Q)
2334         UNFN2(Q)
2335
2336 QPKNF:  MOVE C,QSNUD(H)
2337         PUSHJ P,QUDULK  ;UNLOCK DIR
2338         PUSHJ P,LSWPOP  ;QUSR ENTRY
2339         PUSHJ P,LSWPOP  ;QSNNR ENTRY
2340         PUSHJ P,QPKNFP
2341          JRST QSKOL
2342         PUSHJ P,OPNL16  ;PACK NOT MOUNTED
2343         JRST URET
2344
2345 QPKNFP: MOVSI I,-NQS
2346 QPKNF3: SKIPGE QACT(I)
2347          JRST QPKNF4
2348         MOVE TT,QTUTO(I)
2349         SKIPL QDPWF(I)
2350          TLNE TT,40000
2351           JRST QPKNF2   ;PACK NOT IN OR NOT PAWED OVER
2352 QPKNF4: AOBJN I,QPKNF3
2353         JRST POPJ1
2354
2355 QPKNF2: JRST QTCH1      ;MAYBE THIS UNIT HAS GOODIES
2356
2357 QFDF:   PUSHJ P,OPNL5   ;FILE DIR FULL ON WRITE
2358         JRST URET
2359
2360 QPNL13: PUSHJ P,OPNL13
2361         JRST URET
2362
2363 QPNL22: PUSHJ P,OPNL22
2364         JRST URET
2365
2366 QPNLBN:
2367 QPNL11: PUSHJ P,OPNL11
2368         JRST URET
2369 \f
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)
2376         HRRZ Q,UDNAMP(J)
2377         ADDI Q,(J)
2378         CAIL Q,2000(J)
2379          POPJ P,        ;DIRECTORY EMPTY
2380         TLC A,(SETZ)
2381         TLC B,(SETZ)
2382         PUSH P,D
2383         PUSH P,E
2384         ADDI J,600      ;128. NAME BLOCKS FROM END
2385 REPEAT 7,[              ;THIS CODE DELIBERATELY NOT INDENTED. NEED 4 DIMENSIONS.
2386         CAMGE J,Q
2387         JRST .+6
2388         MOVE D,UNFN1(J)
2389         TLC D,(SETZ)
2390         CAMN A,D
2391         JSP E,QLGLE
2392         CAML A,D
2393         ADDI J,<1_<7-.RPCNT>>*LUNBLK
2394         SUBI J,<1_<6-.RPCNT>>*LUNBLK
2395 ]
2396         CAMGE J,Q
2397          ADDI J,LUNBLK
2398         CAMGE J,Q
2399          BUG
2400         MOVE D,UNFN1(J)
2401         TLC D,(SETZ)
2402         CAME A,D
2403          JRST QLGL1
2404         MOVE D,UNFN2(J)
2405         TLC D,(SETZ)
2406         CAMLE B,D
2407 QLGL2:   ADDI J,LUNBLK
2408 QLGL3:  TLC A,(SETZ)
2409         TLC B,(SETZ)
2410         POP P,E
2411         POP P,D
2412         JRST POPJ1
2413
2414 QLGL1:  CAML A,D
2415          JRST QLGL2
2416         JRST QLGL3
2417
2418 ;CALL BY JSP E,QLGLE
2419 QLGLE:  MOVE D,UNFN2(J)
2420         TLC D,(SETZ)
2421         CAMN B,D
2422          JRST QLGL3
2423         CAML B,D
2424          JRST 1(E)
2425         JRST 2(E)
2426 \f
2427 SUBTTL LOCKING ROUTINES
2428
2429 QMLOCK: PUSHJ P,LSWTL
2430             QMDRO
2431         POPJ P,
2432
2433 QMULK:  PUSH P,U
2434         MOVE U,USER
2435         MOVE U,LSWPR(U)
2436         HRRZ U,(U)
2437         CAIE U,QMDRO
2438          BUG
2439         POP P,U
2440         JRST LSWPOP
2441
2442 QTLOCK: PUSHJ P,LSWTL
2443             QTUTO(I)
2444         POPJ P,
2445
2446 QTULK:  PUSH P,U
2447         MOVE U,USER
2448         MOVE U,LSWPR(U)
2449         HRRZ U,(U)
2450         CAIE U,QTUTO(I)
2451          BUG
2452         POP P,U
2453         JRST LSWPOP
2454
2455 QUDLK:  PUSHJ P,LSWTL
2456             QSNLCN(H)
2457         POPJ P,
2458
2459 QUDULK: PUSH P,U
2460         MOVE U,USER
2461         MOVE U,LSWPR(U)
2462         HRRZ U,(U)
2463         CAIE U,QSNLCN(H)
2464          BUG
2465         POP P,U
2466         JRST LSWPOP
2467
2468 SBTBLI:
2469 QBTBLI: 440600,,        ;IF GOING TO ILDB
2470 SBTBL:
2471 QBTBL:  360600,,
2472         300600,,
2473         220600,,
2474         140600,,
2475         060600,,
2476         000600,,
2477
2478 TBTBL=.+1
2479 TBTBLI: REPEAT 1+TUTEPW, TUTBP-<.RPCNT*TUTBYT*010000,,>
2480 \f
2481 SUBTTL DIRECTORY GARBAGE COLLECTOR
2482
2483 ; MOVE H, directory number
2484 ; lock the directory
2485 ; PUSHJ P,QGC
2486 ;  return if directory full.
2487 ;  return if won.
2488 ; No ACs clobbered.
2489 ; All pointers to directory relocated appropriately.
2490
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."
2495
2496 ;NOTE NOTE NOTE:
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.
2501
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.
2507
2508 QGC:    IRPC X,,ABCDQIJTR
2509          PUSH P,X
2510         TERMIN
2511
2512 ;Old GC prints message on system console.  Any reason to with fast one?
2513
2514 ; validate the directory
2515
2516 QGC00:  SKIPL A,QSNLCN(H)
2517          BUG                    ;directory not locked
2518         MOVE C,UDNAME(A)
2519         MOVEM C,LASTGC          ;save name of last dir GCed
2520         CAME C,QSNUD(H)
2521          BUG                    ;directory clobbered
2522         SKIPLE C,UDNAMP(A)
2523         CAILE C,2000
2524          BUG                    ;name pointer out of bounds
2525         IMULI C,UFDBPW
2526         SKIPL D,UDESCP(A)
2527         CAIL D,-UDDESC*UFDBPW(C)
2528          BUG                    ;descriptor/name overlap
2529
2530 ; Get a block of core to use for temporary storage.
2531 ; The block is left in the "in-process" state.
2532
2533         HRRZ Q,A
2534         PUSHJ P,TCALL
2535             JRST IOMQ
2536          JRST [ PUSHJ P,UDELAY  ;no core available in low half
2537                 JRST QGC00 ]    ;so wait, then loop back to beginning
2538         LSH A,10.
2539         MOVEI B,1(A)            ;zero it out
2540         HRL B,A
2541         SETZM (A)
2542         BLT B,1777(A)
2543         EXCH Q,A                ;A -> directory, Q -> temporary core
2544 ;Drops through
2545 \f;Drops in
2546 ; Scan the directory and count:
2547 ;  I    all files
2548 ;  J    files open for writing
2549 ;  R    active bytes of descriptor
2550
2551         SETZB I,J
2552         SETZ R,
2553         MOVEI B,2000(A)         ;end of name area
2554         ADD A,UDNAMP(A)         ;start of name area
2555 QGC10:  CAML A,B
2556          JRST QGC19             ;jump if all files done
2557         SKIPE UNFN2(A)
2558         SKIPN UNFN1(A)
2559          BUG                    ;zero name block?
2560         AOJA I,QGC12            ;file exists
2561
2562 QGC11:  ADDI A,LUNBLK           ;advance to next file
2563         AOJA R,QGC10            ;also count the zero byte that ends the descriptor
2564
2565 QGC12:  MOVE C,UNRNDM(A)
2566         TLNE C,UNWRIT
2567          ADDI J,1
2568         ANDI C,.BM UNDSCP       ;get descriptor ptr (undscp has pos=0)
2569         IDIVI C,UFDBPW
2570         HLL C,QBTBLI(D)
2571         ADDI C,UDDESC-2000(B)
2572         MOVE D,UNRNDM(A)
2573         TLNE D,UNLINK
2574          JRST QGC14
2575 QGC13:  ILDB T,C                ;get byte of descrip
2576         JUMPE T,QGC11           ;eof
2577         CAIG T,UDWPH
2578          AOJA R,QGC13           ;1-byte desc
2579 REPEAT NXLBYT, IBP C            ;multi-byte desc
2580         ADDI R,NXLBYT+1
2581         JRST QGC13
2582
2583 QGC14:  ILDB T,C                ;count bytes of link descriptor
2584         JUMPE T,QGC11
2585         CAIN T,':
2586          AOJA R,[IBP C          ;quoted
2587                  AOJA R,QGC14 ]
2588         AOJA R,QGC14
2589
2590
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.
2594
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
2600         SKIPE J
2601          IDIV A,J               ;number of bytes available to extend open files
2602         CAIGE A,QAPBMN
2603          JRST QGC69             ;if < minimum, dir. full
2604         CAILE A,QAPBMX
2605          MOVEI A,QAPBMX         ;limit to at most QAPBMX bytes at a time
2606 ;Drops through
2607 \f;Drops in
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
2615
2616         SETZ J,
2617         HRRZ R,QSNLCN(H)        ;old dir
2618         ADDI Q,UDDESC           ;new dir
2619         HLL Q,QBTBLI
2620         MOVE B,UDNAMP(R)
2621         ADD B,R
2622
2623 ; Loop over files
2624
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
2629
2630 ; Loop over all disk channels, relocating the ones that point to this file
2631
2632         MOVSI D,-NQCHN
2633 QGC31:  HRRZ T,QUDPR(D)
2634         SKIPL QUSR(D)
2635          CAIE T,(H)
2636           AOBJN D,QGC31         ;not in use or not same directory
2637         JUMPGE D,QGC39          ;jump if all disk channels done
2638         LDB T,[1200,,B]
2639         CAME T,QUDFPR(D)
2640          JRST QGC32             ;not same file
2641         MOVE T,J                ;relocate descriptor pointer
2642         SUB T,C
2643         ADDM T,QDIRP(D)
2644 QGC32:  AOBJN D,QGC31
2645
2646 QGC39:  IDIVI C,UFDBPW          ;make desc pntr into byte pointer
2647         HLL C,QBTBLI(D)
2648         ADDI C,UDDESC(R)
2649         MOVE T,UNRNDM(B)
2650         TLNE T,UNLINK
2651          JRST QGC22
2652 QGC21:  ILDB T,C                ;copy descriptor bytes of a file into temporary core
2653         IDPB T,Q
2654         JUMPE T,QGC23
2655         CAIG T,UDWPH
2656          AOJA J,QGC21
2657 REPEAT NXLBYT,[
2658         ILDB T,C
2659         IDPB T,Q
2660 ]       ADDI J,NXLBYT+1
2661         JRST QGC21
2662
2663 QGC22:  ILDB T,C                ;copy descriptor bytes of a link into temporary core
2664         IDPB T,Q
2665         JUMPE T,QGC23
2666         CAIN T,':
2667          AOJA J,[ILDB T,C
2668                  IDPB T,Q
2669                  AOJA J,QGC22 ]
2670         AOJA J,QGC22
2671
2672 QGC23:  MOVE T,UNRNDM(B)
2673         TLNN T,UNWRIT
2674          JRST QGC25
2675         ADD J,A                 ;file being written, increase desc area
2676         MOVE T,A
2677         IBP Q
2678         SOJG T,.-1
2679
2680 QGC25:  ADDI B,LUNBLK           ;next file
2681         AOJA J,QGC20            ;also account for final zero at end of descriptor
2682 \f
2683 ; Paranoia:  check that all disk channels to this directory look OK
2684
2685 QGC40:  MOVEM J,UDESCP(R)       ;store free-desc pointer
2686         LDB A,[1200,,Q]         ;last word used by descriptors
2687         CAML A,UDNAMP(R)
2688          BUG                    ;overlap
2689         ANDI Q,-2000            ;base of temp core block again
2690         MOVSI A,-NQCHN
2691 QGC41:  HRRZ T,QUDPR(A)
2692         SKIPL QUSR(A)
2693          CAIE T,(H)
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
2698         CAIGE B,2000
2699          CAMGE B,UDNAMP(R)
2700           BUG                   ;file pointer screwed
2701         ADD B,R
2702         SKIPL J,QDIRP(A)        ;get descriptor pointer
2703          CAMLE J,UDESCP(R)
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
2711          CAML J,D
2712           BUG
2713 QGC42:  AOBJN A,QGC41           ;do next channel
2714
2715 ; If you thought that was paranoid, get a load of this:
2716
2717 QGC49:  MOVE B,UDNAMP(R)
2718         ADD B,R
2719 QGC50:  CAIL B,2000(R)
2720          JRST QGC60
2721         LDB C,[UNDSCP UNRNDM(B)]
2722         SOS C
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
2725         ADDI C,UDDESC(Q)
2726         LDB T,C
2727         SKIPE T
2728          BUG                    ;descriptor not preceeded by zero
2729         MOVE J,UNRNDM(B)
2730         TRZ J,#.BM UNDSCP       ;LH(J) flags, RH(J) just desc pntr
2731         TLNE J,UNLINK
2732          JRST QGC52
2733 QGC51:  ILDB T,C
2734         JUMPE T,QGC53
2735         CAIG T,UDWPH
2736          AOJA J,QGC51
2737 REPEAT NXLBYT, IBP C
2738         ADDI J,NXLBYT+1
2739         JRST QGC51
2740
2741 QGC52:  ILDB T,C
2742         JUMPE T,QGC53
2743         CAIE T,':
2744          AOJA J,QGC52
2745         IBP C
2746         ADDI J,2
2747         JRST QGC52
2748
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
2754         CAIG D,(J)
2755          BUG                    ;descriptors overlap
2756         ADDI B,LUNBLK   
2757         JRST QGC50
2758 \f
2759 ; Copy the descriptors back into the directory
2760
2761 QGC60:  MOVSI C,UDDESC(Q)       ;make BLT pointer to copy it back
2762         HRRI C,UDDESC(R)
2763         MOVE B,UDNAMP(R)        ;use same BLT to zero out the free area
2764         ADD B,R
2765         BLT C,-1(B)
2766
2767 ; Take win return.
2768
2769         AOS -9(P)
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.
2773         IRPC X,,RTJIQDCBA
2774          POP P,X
2775         TERMIN
2776         POPJ P,
2777 \f
2778 SUBTTL INTERPRET DESCRIPTORS
2779
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
2786         CLEARM QSBI(A)
2787         CLEARM QFBLNO(A)
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
2791         CAMLE J,Q
2792          JRST QFNT7     ;LOCATED BLOCK CONTAINING WORD
2793         MOVEM J,QFBLNO(A)
2794         JRST QFNT1A
2795
2796 QFNTN:  MOVE H,QUDPR(A) ;LIKE ABOVE BUT SCAN FORWARD ONLY FROM CURRENT SPOT
2797         PUSHJ P,QUDLK
2798         PUSHJ P,QFNT1
2799          CAIA           ;EOF, DON'T SKIP RETURN
2800           AOS (P)
2801         MOVEM J,QFBLNO(A)
2802         JRST QUDULK
2803
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
2808          JRST QFNT3     ;NULL
2809         JUMPN R,QFNT8   ;NOT OFF END OF FILE
2810         SOS QDIRP(A)
2811         POPJ P,
2812
2813 QFNT8:  TRNE R,40
2814          JRST QFNT4
2815         CAILE R,UDTKMX
2816          JRST QFNT6     ;SKIP AND TAKE
2817         MOVEM R,QSBI(A)
2818 QFNT2:  SOS QSBI(A)
2819         AOS QSLGL(A)
2820 QFNT5:  MOVEI J,2000    ;ACTIVE BYTES IN BLOCK
2821         IMULI J,@QSBYTE(A)
2822         ADD J,QFBLNO(A)
2823         JRST POPJ1
2824
2825 QFNT7:  MOVSI T,%QALBK  ;SET UP PROC LAST BLOCK FLG AND RETN
2826         ANDCAM T,QSRAC(A)       ;CLEAR LAST BLOCK OF FILE BIT
2827         SKIPE QSBI(A)
2828          JRST QFNT7A    ;NOT LAST BLOCK
2829         ILDB R,TT       ;GET NEXT CHR IN DIR
2830         JUMPN R,QFNT7A
2831         IORM T,QSRAC(A) ;PROCESSING LAST BLOCK
2832 QFNT7A: AOS QSBI(A)     ;FAKE OUT PI ROUTINE WHICH WILL TRY TO INCREMENT
2833         SOS QSLGL(A)
2834         JRST POPJ1
2835
2836 QFNT4:  MOVEI J,0       ;LOAD ADR
2837         DPB R,[140400,,J]
2838         PUSHJ P,QMPDCH
2839         DPB R,[060600,,J]
2840         PUSHJ P,QMPDCH
2841         DPB R,[0600,,J]
2842         MOVEM J,QSLGL(A)
2843         JRST QFNT5
2844
2845 QFNT6:  MOVEI J,1-UDTKMX(R)
2846         ADDM J,QSLGL(A)
2847         JRST QFNT5
2848 \fEBLK
2849
2850 SUBTTL DISK CHANNEL DATA AREAS
2851
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
2856
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)
2860
2861 QFCHN:  NQCHN           ;NUMBER OF FREE QSK CHNLS (NOT COUNTING DIR WRITE AND SWAP CHANNELS)
2862
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
2878  %QA==525252(1)
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
2899
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
2904         -1              ;D.W.
2905         BLOCK NQS       ;SWAP
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
2929 \f
2930 ;VARIABLES FOR CURRENT TRANSFER
2931
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
2936
2937 IFN T300P,[
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
2942 NRXFR1: 0               ;METERS
2943 NWXFR1: 0
2944 NSRXF1: 0
2945 NSWXF1: 0
2946 LQTM1:  0               ;TIME LAST TRANSFER STARTED
2947 ];T300P
2948
2949 ;MASTER FILE DIRECTORY
2950
2951 QMDRO:  -1              ;ORIGIN OF MASTER DIR 4.9 IF LOCKED
2952                         ;-2 ON WAY IN 
2953                         ;4.6 NOT IN
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
2959
2960 ;TRACK UTILIZATION TABLES
2961
2962 QTUTO:  REPEAT NQS,-1   ;ADDRESS OF TUT.  LH SIMILAR TO QMDRO
2963                         ;4.9 LOCK
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
2968                         ;5 = 3.9  6 = 3.8
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
2976 IFN QRSRVP,[
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
2979 ];QRSRVP
2980 NTBL:                   ;NUMBER OF BLOCKS IN TUT ON THIS DRIVE
2981 IFE T300P, REPEAT NQS, NTUTBL
2982 IFN T300P,[
2983         REPEAT T300P, NTUTBL
2984         REPEAT NQS-T300P, NTUTB1
2985 ];T300P
2986
2987 ;POSITIONER VARIABLES (INDEXED BY PHYSICAL DRIVE)
2988
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
2995 IFN DC10P,[
2996 QRCTIM: BLOCK NQS       ;RECALIBRATE TIMEOUT IN HALF SECONDS.  THE ATTNS
2997 ];DC10P                 ; TEND TO GET LOST FOR SOME REASON
2998
2999 ;MISCELLANEOUS DISK VARIABLES
3000
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
3003                         ;3.9 5  3.8 6
3004 QWBUFS: 0               ;TOTAL NUMBER OF WRITE BUFFERS ACTIVE
3005
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
3010
3011 QTUNT:  0       ;UNIT TO TRANSFER ON NEXT
3012 QTCHN:  0       ;CHNL ..
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
3023
3024 LASTGC: 0       ;NAME OF LAST DIRECTORY TO GET GC'ED
3025 \f
3026 ;USER DIRECTORIES
3027
3028 QNUD==40.               ;NUMBER USER DIRECTORIES
3029
3030 QFUD:   QNUD            ;NUMBER OF FREE UFD SLOTS
3031
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
3039
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.
3053
3054 IFN QRSRVP,[
3055 QSALLO: BLOCK QNUD      ;-1 OR DRIVE # DIRECTORY ALLOCATED TO
3056 ]
3057
3058 ;LOCKS
3059
3060 UDRSW:  -1      ;USER DIR AREA LOCKED
3061         0
3062 QCHSW:  -1      ;CHNL AREA LOCKED
3063         0
3064 QSKOSW: -1      ;QSKO1 LOCKED (USER DIR READIN)
3065         0
3066
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.
3070
3071 QFBTS:  0
3072
3073 ;VARIABLES FOR SYSTEMS CONCEPTS DISK CONTROL
3074
3075 IFN DC10P,[
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
3082 ]
3083 IFE DMDSK,[
3084         0       ;FOR BLT INTO QXWDS
3085 QXWDS:  BLOCK NXWDS
3086 ]
3087 IFN DC10P,[
3088 QCHPRG: 0
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
3094         DHLT
3095
3096 GPKID:  DSPC+DSCRHD+DSWNUL+DUNENB+TUTCYL_11.+TUTSRF_6+TUTSEC
3097         DCOPY RPKID(37774)
3098         DHLT
3099 QRECAL: DSPC+DSRCAL+DUNENB
3100 ]
3101
3102 ;VARIABLES FOR DEC RP10 DISK CONTROL
3103
3104 IFN RP10P,[
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)
3110 IFE DMDSK,[
3111         -NXWDS,,QXWDS-1
3112         -200+NXWDS,,0
3113 ];DMDSK
3114         0
3115
3116 QRECAL: 700000,,
3117 QGTBZY: 0       ;FLAG FOR SOFTWARE AT INT
3118 ];RP10P
3119 IFN QRDCMP,[
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
3123 IFN KA10P,[
3124 RCIOWD: BLOCK 2 ;CHANNEL PROGRAM FOR READ INTO QRCBUF
3125 ];KA10P         ;ON KL WE HAVE TO PUT IT IN THE EPT!
3126 QRCBUF: BLOCK 2000
3127 ];QRDCMP
3128 \f
3129 ;VARIABLES FOR DEC RH10 DISK CONTROL
3130
3131 IFN RH10P,[
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
3156 ]
3157
3158 ;VARIABLES FOR DEC RH11 DISK CONTROL (ON THE KS10 UNIBUS)
3159
3160 IFN RH11P,[
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
3166
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
3176 QERPOS::
3177 QECPOS: 0       ; POS   ECC position
3178 QERPAT::
3179 QECPAT: 0       ; PAT   ECC pattern
3180 QERMAP: 0 ? 0   ; Unibus map to disk buffer
3181
3182 QECCS:  BLOCK NQS       ;NUMBER OF ECC CORRECTED ERRORS, PER DRIVE
3183 QECCAD: BLOCK NQS       ;DISK ADDRESS OF MOST RECENT ECC CORRECTED ERROR
3184
3185 NQSATN: BLOCK NQS       ;# SPURIOUS ATTENTIONS IN MID-TRANSFER
3186 NQEATN: BLOCK NQS       ;# ATTENTIONS REPORTING ERRORS
3187 NQOFFL: BLOCK NQS       ;# TIMES DISK WENT OFFLINE
3188 ]
3189
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.
3196
3197 BBLK
3198
3199 ;DISK CONSTANTS
3200
3201 IFN RP10P,[
3202 QATTNS: REPEAT NQS,500000+.RPCNT_14,,1_<10-.RPCNT>
3203 ;WORDS TO CLEAR ATTNS AND SELECT DRIVES
3204 ]
3205
3206 SWAPL:  SINLST(Q)
3207         SOUTLS(Q)
3208
3209 DCHBT:  20000,, ;BIT SET IF DIR NOT WRITTEN OUT ON UNIT
3210         10000,,
3211         4000,,
3212         2000,,
3213         1000,,
3214         400,,
3215         200,,
3216         100,,
3217 IFL .-DCHBT-NQS,.ERR YOU BETTER FIND ANOTHER BIT FOR QACTB,QSNLCN,QTUTO
3218
3219 IFN DC10P,[
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.)
3224         4
3225         5
3226         6
3227         7
3228 IFL .-QTRAN-NQS,        .ERR BARF AT QTRAN
3229 ]
3230 \f
3231 SUBTTL DISK CLOSE ROUTINES
3232
3233 QICL:   PUSH P,R
3234         SKIPGE QUSR(A)
3235          BUG
3236         MOVSI Q,%QAACC
3237         ANDCAM Q,QSRAC(A)       ;FLUSH RANDOM ACCESS HACKERY
3238         PUSHJ P,QICLW1          ;WAIT FOR INPUT TO STOP
3239         MOVE TT,QSRAC(D)
3240         TLNE TT,%QADEL  ;DELETE?
3241          JRST QSICLD    ;YES
3242         MOVE H,QUDPR(D)             ;DIRECTORY NUMBER
3243         SETOM QUSR(D)
3244         AOS QFCHN
3245 QICLX:  SOSGE QSNNR(H)              ;FREE DIRECTORY CHANNEL HAD BEEN USING
3246          BUG
3247         POP P,R
3248         SETZM (R)
3249         POPJ P,
3250
3251 QICLW1: MOVE D,A                ;IDLE CHANNEL AND FLUSH READ BUFFERS
3252         CONO PI,UTCOFF
3253         SKIPGE QSGL(D)
3254          JRST QSICL3
3255         SKIPL QSCABN(D)
3256          JRST QSICL4
3257         SETOM QSGL(D)
3258
3259 QSICL3: HLLZS QSRAC(D) .SEE %QMIDL ;STOP PI
3260         CONO PI,UTCON
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)]
3265         PUSHJ P,MEMR
3266         MOVE A,C
3267         SOS QSBFS(D)
3268         JRST QSICL2
3269
3270 QSICL6: SETZM QBFP(D)
3271         POPJ P,
3272
3273 QSICL4: MOVEI A,%QMRD1  ;STOP PI AFTER THIS BLOCK
3274         HRRM A,QSRAC(D)
3275         CONO PI,UTCON
3276         SKIPL QSGL(D)   ;WAIT FOR CHANNEL TO DEACTIVATE
3277          PUSHJ P,UFLS
3278         JRST QSICL5
3279 \f
3280 ;OUTPUT CLOSE
3281 QOCL:   PUSHJ P,QSOCL5  ;CLEAN UP THE DISK CHANNEL
3282 QSOCL4: MOVE D,A        ;ENTRY FROM QALINK
3283 QSOCL6: MOVE Q,QUDFPR(D)
3284         MOVE H,QUDPR(D)
3285         ADD Q,QSNLCN(H)
3286         MOVE TT,QSRAC(D)
3287         TLNE TT,%QADEL
3288          JRST QCDLWO    ;DELETED (PRESUMABLY VIA DELEWO)
3289         MOVE A,UNFN1(Q) ;Get names of file being hacked.
3290         MOVE B,UNFN2(Q)
3291         PUSHJ P,QLOOK   ;FILING OVER ANYTHING?
3292          JRST QSOCL3
3293         HRRZ I,QSNLCN(H)
3294         ADD I,QUDFPR(D)
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
3300
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
3308         JUMPN H,QOCL5
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
3312 QOCL2:  MOVE T,A
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.
3316                   POPJ P, ]
3317          PUSHJ P,UFLS
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)
3321         PUSHJ P,QUDLK
3322         SKIPN D,QMPTC(A)        ;SKIP ON NEXT "N" STILL PENDING
3323          POPJ P,
3324         PUSHJ P,QUDS            ;STORE IT AWAY
3325         CLEARM QMPTC(A)
3326         POPJ P,
3327
3328 QOCL6:  SKIPGE QSCRW(A) ;WAIT FOR CHANNEL TO IDLE OR HANG UP IN READ
3329          PUSHJ P,UFLS
3330         SKIPL QSGL(A)
3331          PUSHJ P,UFLS
3332         MOVE D,A
3333         PUSHJ P,QOCL7
3334         MOVE A,D
3335         MOVE Q,QSRAC(A)
3336         MOVE B,QSBFS(A)
3337         JUMPE B,QOCL6B
3338         TLNE Q,%QAEFW
3339          JRST QOCL6B
3340         TLNE Q,%QAEFR
3341          SOS B,QSBFS(A) ;COMPENSATE FOR EXTRA AOS ON EOF READ
3342 QOCL6B: CAILE B,1
3343          BUG
3344         TLNE Q,%QAWOV
3345          JRST QOCL6A    ;HACKING LAST BLOCK PAST EOF, UPDATE ACTIVE WD COUNT
3346         JRST QOCL4
3347
3348 QOCL1:  PUSHJ P,QSBRB   ;DISCARD BUFFER
3349         SOS QSBFS(A)
3350         SOS QWBUFS
3351         MOVE D,QDSKN(A)
3352         AOS QSFT(D)     ;RESTORE TRACK
3353         JRST QOCL2
3354 \f
3355 QSOCL3: MOVE Q,QUDFPR(D)
3356         MOVE TT,QSNLCN(H)
3357         ADDI Q,(TT)
3358         MOVSI T,UNWRIT
3359         ANDCAM T,UNRNDM(Q)      ;CLEAR WRITE IN PROG
3360         MOVE TT,QSNLCN(H)
3361         MOVE T,UDNAMP(TT)       ;MAKE SURE IT GOES BEFORE * FILE OF SAME NAME
3362         ADDI T,(TT)
3363         CAMN T,Q
3364          JRST QSOC3E    ;NO PREV FILE
3365         MOVE J,Q
3366 QSOC3A: SUBI J,LUNBLK
3367         CAMN A,UNFN1(J)
3368         CAME B,UNFN2(J)
3369          JRST QSOC3B    ;PREV FILE HAS DIFFERENT NAME
3370         CAILE J,(T)
3371          JRST QSOC3A
3372 QSOC3C: CAMN J,Q
3373          JRST QSOC3E
3374 REPEAT LUNBLK,  PUSH P,.RPCNT(J)
3375         MOVE T,J
3376         HRL T,Q
3377         BLT T,LUNBLK-1(J)
3378 REPEAT LUNBLK,  POP P,LUNBLK-.RPCNT-1(Q)
3379         SUB Q,J
3380         SUBI J,(TT)
3381         MOVSI T,-NQCHN
3382 QSOC3D: HRRZ A,QUDPR(T)
3383         SKIPL QUSR(T)
3384          CAIE A,(H)
3385           JRST QSOC3F
3386         HRRZ A,QUDFPR(T)
3387         CAIN A,(J)
3388          ADD A,Q
3389         MOVEM A,QUDFPR(T)
3390 QSOC3F: AOBJN T,QSOC3D
3391 QSOC3E: SETOM QUSR(D)   ;FREE THE DISK CHANNEL
3392         AOS QFCHN
3393         MOVE C,QSNUD(H)
3394 IFN TPLP+UNSPLP,[
3395         MOVEI TT,SCRTPC
3396         CAMN C,[SIXBIT /.LPTR./]
3397          IORM TT,SUPCOR ;CLOSING FILE ON TPL DEVICE SO SET FLAG FOR SYS JOB
3398 ];TPLP
3399         CAMN C,[SIXBIT/.MAIL./]
3400          AOS NQMFWR     ;CLOSING FILE ON .MAIL. => BUMP COUNT TO WAKE MAILER DEMON
3401 IFN XGP,[
3402         CAMN C,[SIXBIT/.XGPR./]
3403          AOS NXGPFW     ;WAKE XGPSPL
3404 ];XGP
3405         MOVE A,QSNMI(H) ;TELL DIRHNG DEVICE ABOUT IT
3406         PUSHJ P,DIRSIG
3407         MOVE TT,QACTB   ;DIR CHANGED (AT LEAST WRITE-IN-PROG BIT TURNED OFF)
3408         IORM TT,QSNLCN(H)       
3409         PUSHJ P,QUDULK
3410         SOSGE QSNNR(H)
3411          BUG
3412         PUSHJ P,QSTRTR
3413         SETZM (R)       ;CLEAR IOCHNM WORD.
3414         POPJ P,
3415
3416 QSOC3B: ADDI J,LUNBLK
3417         JRST QSOC3C
3418
3419 QOCLR:  MOVE Q,QSRAC(A) ;CLOSE UNIT ASCII OUTPUT
3420         TLNN Q,%QAWOV
3421          TLNN Q,%QAMWO+%QALNK
3422           PUSHJ P,QOCLPD        ;PUT NEEDED PADDING UNLESS NOT A FILE OR NOT AT END
3423         JRST QOCL
3424
3425 QOCLPD: LDB Q,[360600,,QSMPRP(A)] ;NUMBER OF BITS NOT WRITTEN IN LAST WORD
3426         CAIL Q,44
3427          POPJ P,        ;LAST WORD NOT WRITTEN AT ALL
3428         LSH Q,18.+6     ;FILL THOSE BITS WITH ^CS
3429         HRR Q,QSMPRP(A)
3430         MOVE C,[EOFWRD]
3431         SKIPLE QSMPRC(A) ;INHIBIT STORE IF NO BUFFER ETC.
3432          DPB C,Q
3433         POPJ P,
3434 \f
3435 SUBTTL DISK INTERRUPT ROUTINES
3436
3437 OVHMTR QIN      ;DISK INTERRUPT LOW-LEVEL
3438
3439 IFN RP10P,[
3440
3441 QINT:   AOS QGTBZY
3442         MOVEM TT,QCST
3443 IFN DMDSK,[
3444         TRNN TT,200000  ;END OF CYLINDER
3445          JRST QINT0
3446         SKIPGE C,QSDCH
3447          BUG
3448         MOVE D,QSGL(C)
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
3452           CAIA          ;IGNORE
3453            BUG PAUSE,[MAYBE DISK CONTROL IS WRITING ALL OVER THE DISK AGAIN]
3454 QINT0:  ];DMDSK
3455         TDNE TT,[17177700]      ;ANY ERRORS?
3456          JRST QINTE
3457 QINTN2: DATAI DPC,R
3458         SKIPGE QSDU     ;DONT CLOB CMD BUF TO CLR ATTS DURING DATA XFER
3459          TRNN R,776     ;ANY ATTNS
3460           JRST QINTA    ;NO
3461         LDB I,[11000,,R]        ;YES,FIND WHICH DRIVE
3462         JFFO I,.+1      ;CLOBBERS Q
3463         SUBI Q,28.
3464
3465 QINTAT: DATAO DPC,QATTNS(Q)     ;CLEAR ATTNS
3466         DATAI DPC,E
3467         TLNN E,40
3468          JRST QRECAT            ;NOT ON CYLINDER, RECALIBRATE
3469         LDB A,[DCYLI E]
3470         TRNE E,.BM DCYLXI
3471          ADDI A,400
3472         CAME A,QPOSGL(Q)
3473          JRST QRECAT    ;SEEK TO THE WRONG PLACE (CALCOMPS LIKE TO DO THIS)
3474         MOVEM A,QPOS(Q) ;REMEMBER WHERE IT IS AT
3475         SETZM QSEEK(Q)
3476         SETZM QRCAL(Q)
3477         JRST QINT       ;TRY AGAIN
3478
3479 QINTA:  SKIPGE Q,QSDU
3480          JRST QINT1     ;NOT EXPECTING DATA COMPLETION - FIND NEW TRANSFER
3481         CONSO DPC,400000
3482         CONSO DPC,10
3483          JRST DSKEX     ;TRANSFER STILL IN PROGRESS, DISMISS
3484         CONSZ DPC,20
3485          JRST .-1       ;BUSY?
3486         AOSN QHUNGF
3487          JRST QHE       ;XFER HUNG, RECALIBRATE AND RETRY
3488         JRST QINTA1     ;TRANSFER COMPLETE...
3489 \f
3490 QINTE:  DATAI DPC,R
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
3494         MOVEM TT,QERST
3495         MOVEM R,QERDTI
3496         CONSZ DPC,20    ;WAIT FOR UNBUSY
3497          JRST .-1
3498         MOVE Q,QSDU     ;FOR QOVR
3499         MOVE E,QCHPRG
3500         TRNE TT,20000   ;OVERRUN
3501          JRST QOVR
3502         TRNE TT,2000    ;NOT READY
3503          JRST QNRDY
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
3507          JRST QDE
3508         TRNE TT,1000    ;WRITE LOCKED
3509          JRST QIRWRE
3510         TRNE TT,40000   ;SEARCH FAILED
3511          JRST QHE
3512         TRNN TT,100000  ;POWER FAILURE
3513          JRST QINTE1
3514         CONSZ DPC,100000        ;TRY IT AGAIN
3515          JRST 4,.-1
3516         JRST QHE
3517
3518 QINTE1: TLNE R,10       ;FILE UNSAFE--NEED OPERATOR INTERVENTION
3519          BUG PAUSE,[DSK: FILE UNSAFE UNIT ],DEC,Q
3520         TLNE R,4
3521          BUG    ;NO SUCH DRIVE
3522         TLNE R,110      ;POSITION FAILURE (OR PROCEEDED FILE UNSAFE)
3523          JRST QHE
3524         AOS NQSE(Q)     ;SPURIOUS ERROR
3525         JRST QINTX      ;IGNORE
3526
3527 QIRWRE: BUG PAUSE,[DSK: WRITE LOCKED UNIT ],DEC,Q
3528         JRST QHE
3529
3530 QNRDY:  LDB Q,[410300,,R]       ;WHICH DPC
3531         SKIPN QSEEK(Q)
3532          SKIPGE QRCAL(Q)        ;NOT SEEKING OR RECALIBRATING IS ERROR
3533           JRST QINTN2
3534         BUG PAUSE,[DSK: UNIT ],DEC,Q,[NOT READY]
3535         JRST QREC
3536 ] ;END IFN RP10P
3537 \f
3538 IFN DC10P,[
3539
3540 QINT:   MOVEM TT,QCST
3541         SKIPL PKIDM     ;GETS SPURIOUS DIPE WHEN READING PACK ID
3542          CONSO DC1,7777 ;RUMOR THAT DSSERR DOESN'T ALWAYS SET
3543           TRNE TT,DSSERR
3544            JRST QINTE
3545         TRNE TT,DSSATT
3546          JRST QINTAT
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
3552          JRST QSPKID
3553         AOSN QHUNGF
3554          JRST QHE       ;XFER HUNG, RECALIBRATE AND RETRY
3555         SKIPL QERS1
3556          JRST QEROK     ;OK ON VERIFY
3557         JRST QINTA1     ;TRANSFER COMPLETE...
3558
3559 QINTE:  CONI DC1,TT
3560         CONO DC0,DCCLR+DCERR+DSKCHN     ;CLEAR ERRORS
3561         MOVEM TT,QERST
3562         MOVE Q,QSDU
3563         CONSZ DC0,DSSRUN+DSSACT
3564          JRST .-1       ;ACTIVE OR RUN?
3565         SKIPL QERS1
3566          JRST QERL1     ;VERIFY ALSO LOST
3567         TRNE TT,DOFFL+DPROT+DDOBSY+DNXM+DCPERR
3568          JRST QINTE1    ;REALLY LOST BIG
3569         TRNE TT,DOVRRN
3570          JRST QOVR
3571         TRNE TT,DWTHER+DFUNSF   ;SEEK INC, END DISK, WATCHDOG, OR UNSAFE
3572          JRST QHE       ;TRY TO RECALIBRATE
3573         SKIPGE PKIDM
3574          TRZ TT,DRLNER  ;IGNORE LENGTH ERROR IF READING PACK #
3575         TRNE TT,DIPE+DRLNER+DRCER+DCKSER
3576          JRST QDE       ;TRY AGAIN
3577         SKIPGE PKIDM
3578          TRNE TT,-1
3579           AOS NQSE      ;SPURIOUS ERROR (NOT LENGTH ERROR IN PKIDM)
3580         JRST QINTX      ;SPURIOUS ERROR
3581
3582 QINTE1: TRNE TT,DOFFL
3583          BUG PAUSE,[DSK: UNIT ],DEC,Q,[OFFLINE]
3584         TRNE TT,DPROT
3585          BUG PAUSE,[DSK: UNIT ],DEC,Q,[WRITE PROTECTED]
3586         TRNE TT,DDOBSY
3587          BUG PAUSE,[DSK: DATAO WHEN BUSY]
3588         TRNE TT,DNXM+DCPERR
3589          BUG PAUSE,[DSK: MEM PAR OR NXM ERROR]
3590         JRST QOVR
3591
3592 QINTAT: CONI DC1,Q
3593         CONO DC0,DCCLR+DCCATT+DSKCHN    ;CLEAR ATTENTION
3594         LDB Q,[DSATDN Q] ;ATTENTION DRIVE NUMBER
3595         CAIGE Q,NQS
3596          SKIPL QRCAL(Q)
3597           JRST QINTX
3598         SETZM QRCAL(Q)
3599         CONO DC0,DCCLR+DCATEB+DSKCHN    ;CLEAR ATTENTION ENABLE
3600         JRST QINTX
3601
3602 ;THIS IS CALLED EVERY HALF SECOND
3603 QRCTMO: MOVEI Q,NQS-1
3604         SKIPL QRCAL(Q)
3605 QRCTM1:  SOJGE Q,.-1
3606         JUMPL Q,CPOPJ
3607         SOSL QRCTIM(Q)
3608          JRST QRCTM1
3609         BUG INFO,[DSK: RECAL TIMEOUT UNIT],DEC,Q
3610         SETZM QRCAL(Q)
3611         CONO DC0,DCCLR+DCATEB+DSKCHN    ;CLEAR ATTENTION ENABLE I GUESS
3612         JRST QRCTM1
3613 ];DC10P
3614 \f
3615 IFN RH11P,[
3616
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
3623
3624 RHSLCT: IOWRQ Q,%HRCS2
3625 RHCHEK: IORDQ A,%HRCS1
3626         TRNE A,%HXTRE+%HXMCP
3627          BUG HALT,[DSK: MASSBUS ERROR, CS1=],OCT,A
3628         POPJ P,
3629
3630 RHCLRC: IOWRQ Q,%HRCS2          ; Must select drive before clearing controller
3631         MOVEI A,%HXTRE+%HXIE+%HMNOP
3632 RHCMD:  TROA A,%HXIE
3633 RHCLRD:  MOVEI A,%HXIE+%HMCLR
3634         IOWRQ A,%HRCS1
3635         JRST RHCHEK
3636
3637 EBLK
3638 DSKBRK: 0
3639 BBLK
3640         JSR UTCSAV
3641 QINT:   AOS QGTBZY
3642         MOVE Q,QSDU
3643         IORDQ TT,%HRCS1
3644         MOVEM TT,QCST
3645         TRNE TT,%HXTRE+%HXMCP
3646          JRST QINTE
3647         TRNN TT,%HXSC           ; Perhaps some drive needs attention?
3648          JRST QINT0             ; Not unless SC is set!
3649         IORDQ A,%HRATN
3650         JFFO A,QINTAT
3651 QINT0:  SKIPGE Q,QSDU
3652          JRST QINT1             ; Not expecting completion of transfer.
3653         TRNN TT,%HXRDY
3654          JRST DSKEX             ; Transfer still in progress.
3655         AOSN QHUNGF
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...
3662
3663 QINTAT: MOVNI Q,-35.(B)
3664         HRRZS Q
3665         MOVEI A,1
3666         LSH A,(Q)
3667         IOWRQ A,%HRATN          ; Turn off attention bit.
3668         CAIL Q,NQS
3669          JRST QINT0
3670         CAMN Q,QSDU
3671          JRST [ AOS NQSATN(Q)   ; Ignore attention in mid-transfer.
3672                 JRST QINTA2 ]
3673         SKIPE QACT(Q)
3674          JRST QINTA2            ; Ignore this drive.
3675         PUSHJ P,RHSLCT
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
3686         IORDQ A,%HRCCY
3687         MOVEM A,QPOS(Q)         ;UPDATE CURRENT CYLINDER
3688         CAME A,QPOSGL(Q)
3689          SETOM QSKT1(Q)         ;SEEK TO WRONG PLACE
3690 ];IFDEF %HRCCY
3691 IFNDEF %HRCCY,[
3692         MOVE A,QPOSGL(Q)        ;On RMxx, jump to conclusion
3693         MOVEM A,QPOS(Q)
3694 ];IFNDEF %HRCCY
3695         SETZM QRCAL(Q)          ;NO LONGER RECALIBRATING
3696         JRST QINT0              ;IF NO XFER ACTIVE, MAYBE CAN START ONE ON
3697                                 ; THIS UNIT NOW
3698
3699 QINTA2: SETOM QSKT1(Q)          ;DON'T TRUST POS
3700         JRST DSKEX
3701
3702 ; Went offline and came back online
3703 QOFFL:  TRC B,%HSMOL+%HSDPR+%HSRDY      ;Recover %HRSTS
3704         IORDQ C,%HRER1  
3705         IORDQ D,%HRER2
3706 IFDEF %HRER3,[
3707         IORDQ E,%HRER3
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
3709 ]
3710 IFNDEF %HRER3,[
3711         BUG INFO,[DSK: UNIT #],DEC,Q,[CAME BACK ONLINE, CS1=],OCT,A,[STS=],OCT,B,[ER1=],OCT,C,[ER2=],OCT,D
3712 ]
3713
3714         AOS NQOFFL(Q)
3715         MOVEI A,%HMCLR          ;Clear the drive
3716         PUSHJ P,RHCMD
3717         MOVEI A,%HMRDP          ;I said, clear the drive!
3718         PUSHJ P,RHCMD
3719         MOVEI A,0
3720         IOWRQ A,%HROFS          ;No offset, 18 bits, ECC on, HCI off
3721         MOVEI A,%HMACK          ;Turn %HSVV back on so drive will work
3722         PUSHJ P,RHCMD
3723         POPJ P,
3724 \f
3725 QINTE:
3726 IRPS X,,[CS1 CS2 BA WC POS PAT] ; First get status of controller
3727         IORDQ A,%HR!X
3728         MOVEM A,QER!X
3729 TERMIN
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
3733         MOVEM A,QERMAP+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...)
3740
3741 IRPS X,,[STS ER1 ER2]
3742         IORDQ A,%HR!X
3743         MOVEM A,QER!X
3744 TERMIN
3745         MOVE A,QERCS1           ; A: CS1
3746         MOVE R,QERCS2           ; R: CS2
3747 IFDEF %HRER3,[                  ; Disks with ER2 -and- ER3
3748         IORDQ A,%HRER3
3749         MOVEM A,QERER3
3750         SKIPN QERER2            ; Bad news
3751          SKIPE QERER3
3752           JRST UNSAFE
3753 ]
3754 IFNDEF %HRER3,[                 ; Disks with just ER2
3755         SKIPE QERER2
3756          JRST UNSAFE
3757 ]
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?
3762          JRST QINTE1
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
3766          BUG
3767         TRNN A,%HSERR
3768          JRST [ AOS NQSE(Q)     ; Spurious?
3769                 JRST QINT0]
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
3777          JRST QHE
3778         TRNE B,%H1ECC+%H1ECH+%H1PAR     ; These require reread
3779          JRST QDE
3780         JRST QOVR               ; No error bits set?  (How can this
3781                                 ; happen?)  Go and retry...
3782
3783 ;;; Controller error:
3784 QINTE1: BUG INFO,[DSK: ERR UNIT #],DEC,Q,[CS1=],OCT,QERCS1,[CS2=],OCT,QERCS2
3785         JRST QOVR
3786
3787 ;;; Drive error:
3788 IFDEF %HRER3,[
3789 QINTER: BUG INFO,[DSK: ERR UNIT #],DEC,Q,[ER1=],OCT,QERER1,[ER2=],OCT,QERER2,[ER3=],OCT,QERER3,[STARTING DISK ADDR=],OCT,QCHPGA
3790 ]
3791 IFNDEF %HRER3,[
3792 QINTER: BUG INFO,[DSK: ERR UNIT #],DEC,Q,[ER1=],OCT,QERER1,[ER2=],OCT,QERER2,[STARTING DISK ADDR=],OCT,QCHPGA
3793 ]
3794         JRST RHCLRD             ; Reset error status in drive
3795 \f
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
3802         MOVEM A,USFHLT
3803         PUSHJ P,QINTER          ;GIVE ERROR MESSAGE AND RESET DRIVE
3804         SKIPL QSDU
3805          JRST QHE               ;RECALIBRATE AND RETRY
3806         JRST QREC               ;Just recalibrate, no transfer to retry
3807
3808 QECC:   PUSHJ P,RHCLRD          ; Reset drive
3809         CAME Q,QSDU             ; ECC error better be for transfer in
3810          BUG                    ; progress...
3811         MOVE A,QCHPRG
3812         TRNN A,10       .SEE %HMRED
3813          BUG                    ; ECC error should only happen during read.
3814         LDB A,[$UPPAG QERMAP]
3815         IORI A,600000
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...
3819         MOVE J,QERBA
3820         SUBI J,1000+QUBPG_14    ; Correct to relative byte address of start
3821                                 ; of losing sector.
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
3825                                 ;  within block.
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
3829         CAIL A,177
3830          JRST [ ADDI B,36.      ;LAST WORD IN SECTOR - HACK IT TO AVOID NXM
3831                 SOJA A,.+1]
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
3841         XOR C,E
3842         MOVSM B,(J)             ;PUT CORRECTED DATA BACK
3843         MOVSM C,1(J)
3844         MOVEI A,0
3845         DPB A,[.PAREP+EXEUMP]   ;FLUSH THE DISK BUFF FROM MAP
3846         CLRPT 400000+PAREP_12
3847         CLRPT 401000+PAREP_12   ; Both halves...
3848
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)
3852         MOVE A,QCHPGA
3853         LDB B,[$HASEC A]        ;Compute disk address of failing sector:
3854         ADDI B,-1(E)
3855         IDIVI B,NSECS           ; C: sector
3856         DPB C,[$HASEC A]
3857         LDB D,[$HATRK A]
3858         ADD B,D                 ; B: track
3859         DPB B,[$HATRK A]
3860         MOVEM A,QECCAD(Q)
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)
3864         CAIL E,SECBLK
3865          JRST QINTA1            ;XFER COMPLETE
3866
3867         LDB B,[$HASEC QCHPGA]   ;NOW DETERMINE WHERE TO RESUME TRANSFER
3868         ADD B,E
3869         IDIVI B,NSECS
3870         DPB C,[$HASEC QCHPGA]
3871         LDB C,[$HATRK QCHPGA]
3872         ADD C,B
3873         DPB C,[$HATRK QCHPGA]   ;NO NEED TO IDIVI A,NHEDS SINCE NEVER CROSS
3874                                 ; CYLINDERS
3875
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
3881
3882 ] ;RH11P
3883 \f
3884 IFN RH10P,[
3885
3886 QINT:   AOS QGTBZY
3887         MOVE Q,QSDU
3888         MOVEM TT,QCST
3889         TRNE TT,%HIERR
3890          JRST QINTE
3891         TRNN TT,%HIATN
3892          JRST QINT0
3893         MOVSI A,%HRATN          ;FIND DRIVES NEEDING ATTENTION
3894         PUSHJ P,RHGET
3895         JFFO A,QINTAT
3896 QINT0:  SKIPGE Q,QSDU
3897          JRST QINT1             ;NOT EXPECTING COMPLETION OF TRANSFER
3898         TRNN TT,%HIDON
3899          JRST DSKEX             ;NO COMPLETED TRANSFER
3900         CONSZ DSK,%HIBSY
3901          JRST 4,.-1             ;TRANSFER STILL IN PROGRESS??
3902         AOSN QHUNGF
3903          JRST QHE               ;XFER HUNG, RECALIBRATE AND RETRY
3904         MOVSI A,%HRSTS(Q)       ;SOMETIMES %HSERR SETS AND %HIERR DOESN'T!
3905         PUSHJ P,RHGET
3906         TRNE A,%HSERR
3907          JRST QINTE
3908         JRST QINTA1             ;XFER COMPLETE...
3909
3910 QINTAT: MOVNI Q,-35.(B)         ;LOW BIT IS DRIVE 0
3911         HRRZS Q
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)
3914         HRLI A,%HRATN
3915         PUSHJ P,RHSET
3916         CAMN Q,QSDU
3917          JRST [ AOS NQSATN(Q)   ;IGNORE ATTN IN MID-TRANSFER
3918                 JRST QINTA2 ]
3919         MOVSI A,%HRSTS(Q)       ;GET STATUS OF DRIVE WITH ATTENTION
3920         PUSHJ P,RHGET           ;THIS ALSO CLEARS THE ATTENTION BIT
3921         SKIPE QACT(Q)
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
3927                 AOS NQEATN(Q)
3928                 JRST .+1 ]      ;THEN CLEAR SEEK AND RECALIBRATE FLAGS
3929         SETZM QSEEK(Q)          ;POSITIONING COMPLETION
3930         MOVSI A,%HRCCY(Q)
3931         PUSHJ P,RHGET
3932         MOVEM A,QPOS(Q)         ;UPDATE CURRENT CYLINDER
3933         CAME A,QPOSGL(Q)
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
3937
3938 QINTA2: SETOM QSKT1(Q)          ;DON'T TRUST POS
3939         JRST DSKEX
3940
3941 ;INPUT FROM MASSBUS -  ADDRESS IN LH(A), RETURNS DATA IN A
3942
3943 RHGET:  TLZA A,%HRLOD
3944
3945 ;OUTPUT TO MASSBUS -  ADDRESS IN LH(A), DATA IN RH(A)
3946
3947 RHSET:   TLO A,%HRLOD
3948         DATAO DSK,A
3949         MOVEM A,RHDATO          ;SAVE FOR REBUGGING
3950         MOVEI A,5               ;WAIT 3 USEC FOR BUS CYCLE
3951         SOJG A,.
3952         DATAI DSK,A
3953         TLNE A,%HDERR
3954          BUG HALT,[DSK: MASSBUS ERROR, DATAO=],OCT,RHDATO,[DATAI=],OCT,A
3955         ANDI A,177777           ;RETURN 16-BIT REGISTER CONTENTS
3956         POPJ P,
3957 \f
3958 QINTE:  CONI DSK,TT
3959         DATAI DSK,R
3960         CONO DSK,%HOCLR+%HORAE+%HOATN+DSKCHN    ;RESET CONTROLLER SO DRIVE STATUS MAY BE READ
3961         CONSZ DSK,%HIBSY
3962          JRST .-1               ;SOMETIMES CONTROLLER IS BUSY??
3963         MOVEM TT,QERST
3964         MOVEM R,QERST+1
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
3969          PUSHJ P,RHGET
3970          MOVEM A,QERST+.IRPCNT+2
3971         TERMIN
3972         SKIPN QERER2            ;FILE UNSAFE
3973          SKIPE QERER3
3974           JRST UNSAFE
3975         TRZE TT,%HIDRE
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?
3981 IFN KL10P,[
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
3986          CONO 10407
3987         BUG CHECK,[DSK: MEM PAR ERR, QICWA/],OCT,QICWA,OCT,QICWA+1,[QIOWD/],OCT,QIOWD
3988 QINTE0:
3989 ];KL10P
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?
3996         TRNN A,%HSERR
3997          JRST [ AOS NQSE(Q)     ;SPURIOUS?
3998                 JRST QINT0 ]
3999         MOVE B,QERER1           ;CHECK THE MAIN ERROR REGISTER
4000         TRNE B,#%H1SOF          ;ANY HARD ERRORS?
4001          JRST UNSAFE
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
4010
4011 ;CONTROLLER ERROR
4012 QINTE1: BUG INFO,[DSK: ERR UNIT #],DEC,Q,[CONI=],OCT,QERST,[DCL=],OCT,QERDCL
4013         JRST QOVR
4014
4015 ;DRIVE ERROR
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
4018         HRRI A,%HMCLR
4019         JRST RHSET
4020
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
4027         MOVEM A,USFHLT
4028         PUSHJ P,QINTER          ;GIVE ERROR MESSAGE AND RESET DRIVE
4029         JRST QHE                ;RECALIBRATE AND RETRY
4030 \f
4031 QECC:   MOVSI A,%HRDCL(Q)       ;RESET ERROR STATUS IN DRIVE
4032         HRRI A,%HMCLR
4033         PUSHJ P,RHSET
4034         CAME Q,QSDU             ;CORRECT AN ECC ERROR
4035          BUG                    ;BARF ... NO TRANSFER IN PROGRESS
4036         MOVE A,QCHPRG
4037         TRNN A,10
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
4041         SOS J,A
4042         TDZ J,[177+.BM $DFCWA]  ;J := ADDRESS OF FIRST WORD IN LOSING SECTOR
4043         LDB A,[$DFCAD QIOWD]
4044         SUBM J,A
4045         SOS H,A                 ;# WORDS SUCCESSFULLY XFERED.
4046         CAIL H,0                ;CHECK IF CHANNEL STORED BAD ADDRESS
4047          CAILE H,2000-200
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
4052         CAIL A,177
4053          JRST [ ADDI B,36.      ;LAST WORD IN SECTOR - HACK IT TO AVOID NXM
4054                 SOJA A,.+1]
4055         ADD J,A                 ;J := ADDRESS OF LOSING WORD-PAIR
4056         LDB A,[121400,,J]
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.
4062         LPMR ECCPAG
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
4070         XOR C,E
4071         MOVSM B,(J)             ;PUT CORRECTED DATA BACK
4072         MOVSM C,1(J)
4073         MOVEI A,0
4074         DPB A,[.PAREP+EXEUMP]   ;FLUSH THE DISK BUFF FROM MAP
4075         LPMR ECCPAG
4076
4077         AOS QECCS(Q)            ;LOG THE LOSS
4078         MOVE A,QCHPGA
4079         MOVEI E,200(H)
4080         LSH E,-7                ;NUMBER OF SECTORS TRANSFERRED (INCLUDING ECC SECTOR)
4081         LDB B,[$HASEC A]        ;GET DISK ADDR OF FAILING SECTOR
4082         ADDI B,-1(E)
4083         IDIVI B,NSECS
4084         DPB C,[$HASEC A]
4085         LDB D,[$HATRK A]
4086         ADD B,D
4087         DPB B,[$HATRK A]        ;NO NEED TO DIVIDE BY NHEDS SINCE NEVER CROSS CYLINDERS
4088         MOVEM A,QECCAD(Q)
4089         HLRZ A,A
4090         MOVE D,QSDCH
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
4093         ADD B,E
4094         IDIVI B,NSECS
4095         DPB C,[$HASEC QCHPGA]
4096         LDB C,[$HATRK QCHPGA]
4097         ADD C,B
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
4102         CAIE A,QIOWD
4103          BUG                    ;CHANNEL STORED BAD ADDRESS?
4104         HRRZM A,QICWA
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
4108         TLNE A,(.BM $DFWC)
4109          JRST QECCX             ;MORE TO DO, CONTINUE XFER
4110         AOS QICWA               ;ELSE ADVANCE TO NEXT C.W.
4111         SKIPE @QICWA
4112          JRST QECCX             ;MORE TO DO, CONTINUE XFER
4113         JRST QINTA1             ;XFER COMPLETE
4114 ]
4115 \f
4116 IFN T300P,[
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
4121         ADDI Q,T300P
4122         CAIGE Q,NQS
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
4131         HRR E,DSCSTS
4132         JUMPE E,QINTI           ;OPERATION COMPLETED UNEVENTFULLY
4133         MOVE D,DSCHED           ;GET DISK ADDRESS AS CYL,,HEAD_9+SECTOR
4134         LSH D,9
4135         IOR D,DSCSEC
4136         HRL D,DSCCYL
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   
4140          AOS QECCS(Q)
4141         JUMPE E,QINTI           ;OPERATION COMPLETED SUCCESSFULLY (WITH INTERVENTION OF 2561)
4142         MOVE T,E
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
4147           JRST T3INT2
4148         AOS NQSE(Q)             ;COUNT "SOFT ERRORS" (NOT "SPURIOUS" IN T-300 CASE)
4149         AOJA A,T3IO1            ;GO RETRY OPERATION USING NEXT FEATURE
4150
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
4153           JRST T3HE
4154         JRST T3DE               ;TRY OPERATION AGAIN.  PROBABLY WILL LOSE BUT TRY.
4155 ];T300P
4156 \f
4157 OVHMTR QSC      ;DISK SCHEDULER (AND HIGHER-LEVEL INTERRUPT STUFF)
4158
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
4166                     CAIA
4167                 MOVE A,R        ;A WAS CLOBBERED
4168                 JRST .+1 ]
4169 ]
4170 IFN KS10P,[
4171         SKIPL QSCRW(C)          ;ON KS, CAN ONLY CLEAR THE WHOLE CACHE
4172          CLRCSH
4173 ]
4174         LSH R,10.
4175         MOVE D,QSRAC(C)
4176 IFN RP10P,[
4177         HRRZ TT,QICWA+1
4178         CAIE TT,1777(R)
4179          TLNE D,%QAPAR          ;IGNORE IF LOSING ANYWAY (E.G. SEARCH ERR)
4180           CAIA
4181            JRST QDFLOS
4182 ];RP10P
4183 IFN QRDCMP,[
4184         SKIPE TT,RDCPHS         ;NEED TO READ-COMPARE?
4185          JRST QRC1              ;READ-COMPARE STARTING OR FINISHED
4186 QRC0:
4187 ];QRDCMP
4188         TRNE D,-%QMMAX
4189          BUG
4190         XCT .+1(D)              ;INVOKE COMPLETION HANDLER
4191         OFFSET -.
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
4208 %QMMAX::OFFSET 0
4209 IFN %QMMAX-20, .ERR %QMMAX MUST BE A POWER OF 2
4210
4211 IFN RP10P,[
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
4215         CAIL B,(D)
4216          SKIPL QSCRW(C)
4217           JRST QDFLZ1
4218         BUG HALT,[DSK: CHANNEL TRANSFERRED UP TO ],OCT,B,[RATHER THAN],OCT,D,[DISK IS CLOBBERED NOW.]
4219
4220 QDFLZ1: BUG PAUSE,[DSK: CHANNEL TRANSFERRED UP TO ],OCT,B,[RATHER THAN],OCT,D
4221         JRST QOVR
4222 ];RP10P
4223 \f
4224 ;;; SOFTWARE READ-COMPARE ROUTINES
4225
4226 IFN QRDCMP,[
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
4229
4230 ;;; REGULAR OPERATION COMPLETE, DO A READ-COMPARE TO BE SURE
4231 QRC1:
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
4238 IFN RP10P,[
4239         IOR E,[DREADC+7000+RCICWA]      ;MAKE READ COMMAND
4240         CONO DPC,175700+DSKCHN
4241         MOVE T,[-2000,,QRCBUF-1]        ;STORE CHANNEL PROGRAM
4242         MOVEM T,RCIOWD
4243         SETZM RCIOWD+1
4244         MOVEI T,RCIOWD
4245         MOVEM T,RCICWA
4246         SETZM RCICWA+1
4247         DATAO DPC,E             ;START DISK
4248 ];RP10P
4249 IFN RH10P,[
4250         MOVE T,[-2000_4,,QRCBUF-1]      ;DF10-C CHANNEL PROGRAM
4251         MOVEM T,RCIOWD
4252         SETZM RCIOWD+1
4253         MOVEI T,RCIOWD
4254         MOVEM T,RCICWA
4255         SETZM RCICWA+1
4256         SWPUA                   ;DUMP CACHE
4257         CONSZ 200000            ;IT'S INEFFICIENT, BUT WHAT THE HELL
4258          JRST .-1
4259         CONO DSK,%HOCLR+%HORAE+%HOATN+DSKCHN
4260         MOVSI A,%HRADR(Q)
4261         HRR A,E                 ;HEAD AND SECTOR (CYL DOESN'T CHANGE)
4262         PUSHJ P,RHSET
4263         MOVEI A,%HMRED+<RCICWA_6>
4264         TLO A,%HRCTL(Q)
4265         PUSHJ P,RHSET           ;START DISK
4266 ];RH10P
4267         MOVEM T,RDCPHS          ;RDCPHS POSITIVE MEANS DOING RD/CMP NOW
4268         JRST DSKEX              ;AWAIT COMPLETION
4269
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]
4274         LPMR PARPG
4275         MOVEI H,0               ;H DIFFERENCE COUNT
4276 IFN KA10P,[
4277         PUSH P,A                ;WILL DO COMPARE LOOP IN ACS
4278         PUSH P,C
4279         PUSH P,D
4280         MOVSI E,-2000           ;E ADDRESS WITHIN PAGE
4281         MOVSI D,[ MOVE T,400000+PAREP*2000(E)   ;A
4282                   CAMN T,QRCBUF(E)              ;B
4283                    AOBJN E,A                    ;C
4284                   JRST QRC3 ]                   ;D
4285         HRRI D,A
4286         BLT D,D
4287         JRST A
4288 ];KA10P
4289 .ELSE [
4290         MOVSI E,-2000           ;E ADDRESS WITHIN PAGE
4291         MOVE T,400000+PAREP*2000(E)
4292         CAMN T,QRCBUF(E)
4293 QRC2A:   AOBJN E,.-2
4294 ];NOT KA10P
4295 QRC3:   JUMPGE E,QRC5           ;JUMP IF DONE
4296         JUMPG H,QRC4            ;COMPARE ERROR, REPORT IT
4297         AOS NQCMPE(Q)
4298 IFN KA10P,[
4299         MOVE T,-1(P)            ;SAVED C
4300         BUG INFO,[DSK: READ-COMPARE ERROR #],DEC,NQCMPE(Q),[UNIT=],DEC,Q,[BLK=],OCT,QSGL(T)
4301 ];KA10P
4302 .ELSE   BUG INFO,[DSK: READ-COMPARE ERROR #],DEC,NQCMPE(Q),[UNIT=],DEC,Q,[BLK=],OCT,QSGL(C)
4303 QRC4:   ADDI H,1
4304         HRRZ T,E
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)
4307 IFN KA10P,JRST C
4308 .ELSE   JRST QRC2A
4309
4310 QRC5:
4311 IFN KA10P,[
4312         POP P,D
4313         POP P,C
4314         POP P,A
4315 ];KA10P
4316         MOVEI T,0               ;CLEAR MAP
4317         DPB T,[.PAREP+EXEUMP]
4318         LPMR PARPG
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
4322         JRST QOVR
4323 ];QRDCMP
4324 \f
4325 QUFDWF: MOVE TT,QDWIP
4326         CAMN Q,MDSK             ;WRITTEN TO MASTER DISK?
4327          SKIPN E,QSFBT(TT)      ;AND HAVE SOME BLOCKS TO FREE?
4328           JRST QUDWF1
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
4332         SKIPE 1(E)
4333          JRST [ MOVE E,1(E)
4334                 JRST .-1 ]
4335         MOVEM T,1(E)
4336         SKIPN T
4337          AOS NCORRQ             ;WAKE UP CORE JOB IF QFBTS HAD BEEN EMPTY
4338 QUDWF1: JSP D,QDWF
4339             QSNLCN(TT)
4340
4341 QMFDWF: JSP D,QDWF
4342             QMDRO
4343
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
4348         JSP D,QDWF
4349             QTUTO(TT)
4350
4351 QDWF:   MOVSI E,(SETZ)          ;UNLOCK DIR THAT WAS WRITTEN
4352         IOR E,DCHBT(Q)          ;COPY ON THIS DISK IS NOW UP TO DATE
4353         MOVE TT,QDWIP
4354         ANDCAM E,@(D)
4355         HLLZS QSRAC(C) .SEE %QMIDL      ;IDLE THE CHANNEL
4356         SETOM DWUSR
4357         JRST QINT1A             ;DON'T COUNT THIS AS DISK ACTIVITY
4358
4359 QUDRIN: MOVE TT,QUDPR(C)        ;USER DIR IN OK
4360         MOVE D,UDNAME(R)
4361         CAME D,QSNUD(TT)        ;COMPARE UNAME IN DIR WITH RQ'ED
4362          JRST QUDER1
4363         TLO R,40000             ;NOT PAWED OVER
4364         MOVEM R,QSNLCN(TT)
4365         MOVE R,QSLGL(C)
4366         MOVEM R,QSNMI(TT)
4367         MOVEI R,MU23UD          ;USER DIRECTORY
4368         PUSH P,A
4369         PUSH P,C
4370         MOVE C,TT
4371         PUSHJ P,QDIRCK          ;VERIFY NOT TOTALLY BASHED TO BEGIN WITH
4372         POP P,C                 ;CLOBBERS A,B,I
4373         POP P,A
4374 QINTU4: DPB R,[MUR,,MEMBLT(A)]
4375         DPB TT,[MNUMB,,MEMBLT(A)]
4376 QTUTI1: SETOM QUSR(C)           ;FREE THE DISK CHANNEL
4377         AOS QFCHN
4378         JRST QINT1A
4379
4380 QMDRIN: TLO R,2                 ;NOT RECONCILED
4381         MOVEM R,QMDRO           ;MASTER DIRECTORY IN
4382         MOVE TT,MDCHK(R)
4383         CAME TT,[SIXBIT /M.F.D./]
4384          BUG HALT,[MFD CLOBBERED]
4385         MOVE TT,MDNUDS(R)
4386         CAIE TT,NUDSL
4387          BUG HALT,[MFD HAS WRONG NUMBER OF DIRECTORIES]
4388         MOVE TT,(R)             ;ASCENDING DIR #
4389         SKIPGE QAMDNO
4390          MOVEM TT,QAMDNO        ;FIRST DISK IN STORE ASCENDING #
4391         MOVEI R,MU23MD          ;MASTER DIRECTORY
4392         MOVE TT,Q               ;DISK NO
4393         JRST QINTU4
4394
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
4400         JRST QTUTI1
4401 \f
4402 QSWPFN: MOVE Q,QDSKN(C)
4403         TLNE D,%QAPAR
4404          JRST QSWPF2            ;SWAP READ ERROR (I HOPE)
4405         MOVSI E,MMPTMP          ;PAGE NO LONGER IN TRANSIT
4406         TDNN E,@QSMMP(Q)
4407          BUG                    ;ALREADY WASN'T?
4408         ANDCAM E,@QSMMP(Q)
4409         SKIPL QSCRW(C)
4410          JRST QSWPIF
4411         PUSHJ P,IMEMR           ;SWAP-OUT COMPLETE, RETURN MEMORY
4412         MOVSI E,MMPPGB
4413         ANDCAM E,@QSMMP(Q)
4414         MOVSI E,MMPWOD          ;PAGE HAS BEEN WRITTEN ON DISK.  AND NO LONGER
4415         IORB E,@QSMMP(Q)        ;BEING PAGED BEHIND.
4416         TLNN E,MMPGON
4417          JRST QSWPF2
4418         MOVE A,QSMMP(Q)         ;WE'RE SUPPOSED TO RETURN THE MMP ENTRY
4419         PUSHJ P,RETMMP
4420 QSWPF2: SETOM SWUSR(Q)          ;SWAPPING IDLE
4421         JRST QINT1B
4422
4423 QSWPIF:
4424 ;SOME ERROR CHECKING
4425         MOVE E,QSMMP(Q)
4426         HLLZ TT,1(E)
4427         JUMPE TT,QSWPF3         ;ON INITIAL-SWAP-IN, ADDRESS IN MMP IS SUPPOSED TO BE ZERO
4428         LDB TT,[$MMPUN,,(E)]
4429         CAME TT,Q
4430          BUG
4431         HLRZ TT,1(E)
4432         CAME TT,QSGL(C)
4433          BUG
4434 QSWPF3: LDB TT,[MMMPX,,MEMBLT(A)]
4435         CAIE TT,-MMP(E)
4436          BUG
4437 ;END ERROR CHECKING
4438         MOVEI TT,MURUSR         ;SWAP IN OF PAGE COMPLETED
4439         DPB TT,[MUR,,MEMBLT(A)]
4440         SETZM MMSWP(A)
4441         MOVE D,(E)
4442         SKIPL CIRPSW
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
4445         HRR D,QSMMP(Q)
4446         PUSH P,C
4447         PUSH P,Q
4448         MOVE C,[2200,,MEMPNT(A)]
4449         PUSHJ P,PPIUM           ;PUT PAGE INTO USERS' MAPS
4450         POP P,Q
4451         POP P,C
4452         JRST QSWPF2
4453 \f
4454 QWOVFN: CLEARM QSCRW(C)         ;WRITE OVER SWITCH TO READ MODE
4455         HRRI D,%QMRD1
4456         TLZE D,%QAEFW
4457          HRRI D,%QMIDL          ;TRYING TO CLOSE, STOP CHANNEL
4458         MOVEM D,QSRAC(C)
4459         AOS QWBUFS              ;COMPENSATE FOR EXTRA SOS BELOW
4460
4461 QWRFIN: TLNN D,%QACTH           ;WRITE COMPLETE, RETURN BUFFER
4462          PUSHJ P,IMEMR
4463         TLNE D,%QACTH
4464          PUSHJ P,CIMEMR
4465         SOS QSBFS(C)
4466         SOS QWBUFS
4467         MOVE TT,QSGL(C)
4468         MOVEM TT,QSLBLK(C)
4469         JRST QINT1B
4470
4471 QRD1FN: HLLZS QSRAC(C) .SEE %QMIDL      ;BLOCK-AT-A-TIME READ COMPLETE, IDLE THE CHANNEL
4472
4473 QRDFIN: MOVEI B,.BM MLO         ;NORMAL READ COMPLETED
4474         ANDCAM B,MEMBLT(A)      ;THREAD ONTO CHANNEL LIST
4475         HLRZ B,QBFP(C)
4476         SKIPE B
4477          DPB A,[MLO,,MEMBLT(B)]
4478         SKIPN B
4479          MOVEM A,QBFP(C)
4480         HRLM A,QBFP(C)
4481         SKIPL B,QPIBSZ(C)       ;GET BYTE COUNT OF BLOCK
4482          JRST QRDFN1
4483         HRRZ B,1777(R)          ;FUNNY BLOCK, GET FROM LAST WORD
4484         HRRZ TT,QSBYTE(C)       ;AND MAKE SURE IT'S NOT TOO BIG
4485         IMULI TT,2000
4486         CAMLE B,TT
4487          MOVE B,TT
4488 QRDFN1: HRRZM B,MEMPNT(A)       ;PASS TO MAIN PROGRAM
4489         AOS QSBFS(C)
4490 IFE DMDSK,      LDB B,[XWBLK QXWDS]
4491      .ALSO      MOVEM B,QSLBLK(C)
4492
4493 ;XFER COMPLETE, DEACTIVATE CHANNEL
4494
4495 QINT1B: SETOM QACTTM
4496 QINT1A: SETOM QSGL(C)
4497         SETOM QSCABN(C)
4498 QINT1E:
4499 IFE DC10P, SETOM QSKT1(Q)
4500 IFN DC10P,[
4501         MOVE TT,QTRAN(Q)
4502         SETOM QSKT1(TT)
4503 ] ;DC10P
4504 IFN T300P,[
4505         CAIL Q,T300P
4506          SETOM QSDU1
4507         CAIGE Q,T300P
4508          SETOM QSDU
4509 ];T300P
4510 .ELSE   SETOM QSDU
4511 ;DROPS THROUGH
4512 \f;DROPS IN
4513
4514 ;ACTIVATE CHANNELS, LOOK FOR SEEKS AND TRANSFERS TO BE DONE
4515
4516 QINT1:  SETZM QHUNGF
4517         SETOM QTUNT             ;NO UNIT SELECTED YET
4518 IFN T300P, SETOM QTUNT1
4519         MOVE C,QTCHN            ;START SCAN IN SUITABLE PLACE
4520         MOVEM C,QLCHN
4521         JRST QINT2D
4522
4523 QINT2L: CAIGE C,NQCHN           ;IF DIR-WRITE OR SWAP CHANNEL, DON'T CHECK QUSR
4524          SKIPL QUSR(C)
4525           SKIPGE D,QSRAC(C)     .SEE %QALOK
4526            JRST QINT2C          ;CHANNEL LOCKED OR NOT OPEN, SKIP IT
4527         MOVE Q,QDSKN(C)
4528         SKIPL E,QSGL(C)
4529          JRST QINT4             ;JUMP IF CHANNEL ACTIVE ALREADY
4530         TLNE D,%QACTH+%QAOUT
4531          JRST QINT2C            ;CHANNEL BLOCKED BY CORE JOB, DON'T ACTIVATE
4532         TRNE D,-%QMMAX
4533          BUG
4534         XCT .+1(D)              ;INVOKE ACTIVATE HANDLER
4535         OFFSET -.
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
4552 %QMMAX::OFFSET 0
4553
4554 ; ACTIVATION ROUTINES
4555
4556 SWPACT: SKIPL SWUSR(Q)
4557          BUG                    ;SWAPPING ALREADY ACTIVE ON THIS DISK
4558         MOVE A,MEMFR
4559         SUB A,NCBCOM
4560         MOVEI B,0               ;CHECK FIRST FOR SWAP IN OR OUT
4561         CAIGE A,6               ;ACCORDING TO AVAIL MEM
4562          MOVEI B,1
4563         SKIPN @SWAPL(B)         ;IF NO TRAFFIC THAT DIRECTION, CHECK THE OTHER.
4564          TRC B,1
4565         HRRZ E,@SWAPL(B)
4566         JUMPE E,QINT2C          ;NO SWAPPING TRAFFIC THIS DISK.
4567         LDB A,[MLO,,MEMBLT(E)]  ;TAKE BLOCK OFF LIST
4568         SKIPN A
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)]
4574         TRNN TT,1
4575          BUG                    ;THIS PAGE SHOULD BE MARKED IN TRANSIT
4576         HRRZM D,QSMMP(Q)
4577         SOS SILNG(B)
4578         CAIGE E,TSYSM
4579         CAIGE E,SYSB
4580          BUG
4581         HRRZM E,QSCABN+NQCHN+1(Q)
4582         CLEARM SWUSR(Q)         ;CHNL ACTIVE
4583         HLRZ E,MEMPNT(E)
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
4589 \f
4590
4591 ; MORE ACTIVATION ROUTINES 
4592
4593 QRDACT: TLNE D,%QAACC           ;ACTIVATE READ CHANNEL
4594          JRST QINT2C            ;NOT IF USER HACKING RANDOM ACCESS NOW
4595         SETZM QERRS(C)
4596         MOVE J,QUDPR(C)
4597         SKIPGE QSNLCN(J)
4598          JRST QINT2C            ;USER DIRECTORY OUT OR LOCKED
4599         MOVE A,QSBFS(C)
4600         SKIPL QSMDN(C)
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
4604         SKIPE QSBI(C)
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
4607         CAIN A,UDWPH
4608          JRST QINT4B
4609         JUMPE A,QEOF            ;REACHED READ EOF
4610         TRZE A,40
4611          JRST QINT4C
4612         CAILE A,UDTKMX
4613          JRST QINT4D            ;SKIP AND TAKE
4614         MOVEM A,QSBI(C)         ;TAKE NEXT N
4615 QINT4A: SOS QSBI(C)
4616         AOS E,QSLGL(C)
4617 QINT4G: MOVEM E,QSGL(C)
4618         MOVSI B,%QALBK
4619         ANDCAM B,QSRAC(C)       ;CLEAR PROCESSING LAST BLOCK IN FILE BIT
4620         HRRZ A,QSBYTE(C)
4621         IMULI A,2000            ;NUMBER OF BYTES IN A FULL BLOCK
4622 IFN DMDSK,[
4623         MOVSI D,%QAFNY          ;FUNNY FILE
4624         TDNE D,QSRAC(C)
4625          SETO A,
4626 ]
4627         MOVEM A,QPIBSZ(C)       ;SET FUNNY BIT
4628         SKIPE QSBI(C)
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
4632         JUMPN A,QINT4
4633         MOVE A,QUDFPR(C)        ;THIS IS LAST BLOCK
4634         ADD A,QSNLCN(J)
4635         LDB D,[UNBYTE+UNREF(A)]
4636         PUSHJ P,QBDCD
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
4641         SKIPN E
4642          MOVEI E,2000
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
4647         MOVE E,QSGL(C)
4648         JRST QINT4
4649
4650 QINT4D: MOVEI E,1-UDTKMX(A)     ;SKIP N AND TAKE 1
4651         ADDB E,QSLGL(C)
4652         JRST QINT4G
4653
4654 QWRACT: SKIPN I,QBFP(C)         ;ACTIVATE WRITE CHANNEL
4655          JRST QINT2C            ;END OF WRITE LIST FOR NOW
4656         HRRZM I,QSCABN(C)
4657         LDB H,[MLO,,MEMBLT(I)]
4658         HRRM H,QBFP(C)
4659         SKIPN H
4660          SETZM QBFP(C)          ;LAST BLOCK, LIST NOW EMPTY
4661         HLRZ E,MEMPNT(I)
4662         MOVEM E,QSGL(C)
4663         JRST QINT4
4664
4665 QDRACT: MOVE E,QSLGL(C)         ;ACTIVATE DIRECTORY-READ CHANNEL
4666         MOVEM E,QSGL(C)
4667 ;       JRST QINT4              ;DROPS THROUGH
4668 \f;DROPS IN
4669 QINT4:  SKIPL QSCABN(C)         ;SKIP IF NEED MEMORY
4670          JRST QINT5
4671         PUSHJ P,IOMQ            ;GET MEMORY FOR READ BUFFER
4672          JRST QINT2C            ;CAN'T
4673 QINT5A: MOVEM A,QSCABN(C)
4674         MOVEI D,MU23B
4675         DPB D,[MUR,,MEMBLT(A)]
4676         DPB C,[MNUMB,,MEMBLT(A)]
4677
4678 QINT5:
4679 IFN DC10P, MOVE TT,QTRAN(Q)
4680 .ELSE      MOVE TT,Q
4681         SKIPN QSEEK(TT)         ;IGNORE SEEKING DRIVE
4682          SKIPGE QRCAL(TT)       ;IGNORE RECALIBRATING DRIVE
4683           JRST QINT2C
4684 IFN T300P,[                     ;IGNORE IF FOR CONTROLLER THAT IS NOT READY
4685         CAIL TT,T300P
4686          JRST [ SKIPGE QSDU1
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
4692         SKIPL QSDU
4693          JRST QINT2C
4694 ];T300P
4695         HRRZ B,QSKT1(TT)
4696         CAIN B,(C)
4697          JRST QINT2F            ;ALREADY SET FOR ME
4698         SKIPL QSKT1(TT)
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
4703         ADD E,[DSEEK]
4704         CONSZ DC0,DSSRUN+DSSACT
4705          JRST .-1
4706         DATAO DC0,E
4707         LDB B,[DCYL E]
4708         MOVE TT,QTRAN(Q)        ;PRETEND SEEK ALREADY COMPLETE
4709         MOVEM B,QPOSGL(TT)
4710         MOVEM B,QPOS(TT)
4711         JRST QINT2F             ;DON'T WAIT FOR SEEK, START TRANSFER RIGHT AWAY
4712 ] ;DC10P
4713 IFN RP10P,[
4714         TLO E,(DSEEKC)          ;DSK SEEK
4715         CONSZ DPC,20
4716          JRST 4,.-1
4717         LDB TT,[DCYL E]
4718         TRNE E,.BM DCYLXB
4719          ADDI TT,400
4720         CAMN TT,QPOS(Q)
4721          JRST QINT2F            ;IF WE'RE THERE, DON'T SEEK
4722         MOVEM TT,QPOSGL(Q)
4723         DATAO DPC,E
4724         MOVEM E,QSEEK(Q)
4725         JRST QINT2C             ;THIS ONE SEEKING, GO GET ANOTHER
4726 ] ;RP10P
4727 IFN RH11P,[
4728         PUSHJ P,RHSLCT          ; Select drive
4729         HRRZ A,E
4730         IOWRQ A,%HRADR          ; Set track and sector
4731         HLRZ A,E
4732         IOWRQ A,%HRCYL          ; Set cylinder
4733         CAMN A,QPOS(Q)
4734          JRST QINT2F            ; On cylinder, don't seek
4735         MOVEM A,QPOSGL(Q)
4736         MOVEI A,%HMSEK
4737         PUSHJ P,RHCMD           ; Start seeking
4738         SETOM QSEEK(Q)
4739         JRST QINT2C             ; Start other drives now?
4740 ] ;RH11P
4741 IFN RH10P,[
4742         MOVSI A,%HRCYL(Q)       ;STORE ADDRESS IN DRIVE
4743         HLR A,E
4744         PUSHJ P,RHSET
4745         MOVSI A,%HRADR(Q)
4746         HRR A,E
4747         PUSHJ P,RHSET
4748         HLRZ TT,E               ;GET CYLINDER PART OF ADDRESS
4749         CAMN TT,QPOS(Q)
4750          JRST QINT2F            ;ON CYLINDER, DON'T SEEK
4751         MOVEM TT,QPOSGL(Q)
4752         MOVSI A,%HRDCL(Q)       ;START SEEK
4753         HRRI A,%HMSEK
4754         PUSHJ P,RHSET
4755         SETOM QSEEK(Q)
4756         JRST QINT2C             ;THIS ONE SEEKING, START OTHER DRIVES
4757 ] ;RH10P
4758 \f
4759 IFN KL10P,[
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.
4763
4764 CSHSWP: SETZB A,B               ;A COUNTS WAIT TIME, B IS SWEEP INSTRUCTION
4765         XCT @(P)
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]
4771         MOVE E,[AOJA A,D]
4772         MOVSI TT,(POPJ P,)
4773         PUSHJ P,D               ;WAIT IN ACS TO MINIMIZE MBOX INTERFERENCE
4774         AOS R                   ;SWEEP SECOND HALF-PAGE
4775         XCT B
4776         PUSHJ P,D
4777         XCT @(P)
4778          AOSA NCSHU             ;COUNT NUMBER OF TIMES THIS DONE
4779           AOSA NCSHI
4780            JRST [ ADDM A,NCSHUL ? JRST .+2 ]
4781           ADDM A,NCSHIL         ;AND COUNT NUMBER OF LOOPS IN ACS
4782         LSH R,-1
4783         JRST POPJ1
4784 ]
4785
4786 ;VARIOUS EXITS FROM CHANNEL-CHECKING ROUTINES
4787
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
4795          SETO C,
4796         AOJA C,QINT2L           ;CHECK ANOTHER
4797
4798 QINT2E:
4799 IFN T300P,[
4800         MOVE C,QTCHN1
4801         SKIPL Q,QTUNT1          ;FOUND XFER FOR T-300?
4802          JRST QDE1              ;YES
4803 ];T300P 
4804         SKIPGE Q,QTUNT          ;FOUND XFER?
4805          JRST QINT3             ;IDLE
4806         MOVE C,QTCHN
4807 ;Q DISK TO TRANSFER ON, C CHANNEL.  START (OR RESTART) TRANSFER ON THEM.
4808 QDE1:   MOVE R,QSCABN(C)
4809 IFN KL10P,[
4810         PUSHJ P,CSHSWP
4811           SKIPGE QSCRW(C)
4812 ];KL10P
4813 IFN KS10P,[
4814         SKIPL QSCRW(C)
4815          CLRCSH
4816 ];KS10P
4817 IFE T300P, MOVEM C,QSDCH
4818 IFN T300P,[
4819         CAIL Q,T300P
4820          JRST T3IO              
4821         CAIGE Q,T300P
4822          MOVEM C,QSDCH
4823 ];T300P
4824         SKIPGE B,QSCRW(C)       ;LOAD R/W STATUS IN B
4825          JRST QINT6W
4826 \f;READ - DROPS IN
4827 IFN RP10P,[
4828         MOVSI T,(DREADC)
4829 QINT6A: IORI T,7000+QICWA       ;DON'T STOP FOR PARITY ERRORS (PLUS INITIAL CHNL ADR)
4830         MOVEM T,QCHPRG
4831         DPB Q,[DUNFLD+QCHPRG]
4832         HLLZS QIOWD
4833         DPB R,[121000,,QIOWD]
4834         LDB E,[100300,,R]       ;MA15-17
4835         TRC E,7
4836         DPB E,[410300,,QIOWD]   ;SET UP HIGH ADDR BITS.
4837         MOVE TT,QIOWD
4838         SOS TT
4839         HRRM TT,QIOWD
4840         SETZM QIOWD+1
4841         MOVEM Q,QSDU
4842         MOVE E,QSGL(C)
4843         PUSHJ P,QPOSR
4844         IORM E,QCHPRG
4845 QOVR:   CONSZ DPC,20
4846          JRST QOVR
4847         SKIPGE Q,QSDU
4848          BUG
4849         CONO DPC,175700+DSKCHN
4850 IFN QRDCMP,[
4851         SETZM RDCPHS            ;ASSUME NO READ-COMPARE WANTED
4852         SKIPE QRCSW
4853          SETOM RDCPHS           ;REMEMBER TO READ-COMPARE LATER
4854 ];QRDCMP
4855         MOVEI TT,QIOWD
4856         HRRZM TT,QICWA
4857         MOVE E,QCHPRG
4858         LDB TT,[DCYL E]
4859         TRNE E,.BM DCYLXB
4860          ADDI TT,400
4861         CAME TT,QPOS(Q)
4862          BUG                    ;DONT DO ANYTHING IF NOT WHERE YOU SHOULD BE
4863         SETZM QICWA+1
4864         DATAO DPC,QCHPRG        ;ENTRY ON OVERRUN
4865         MOVE A,TIME
4866         MOVEM A,LQTM
4867         MOVEM Q,QSDU
4868         CAILE C,NQCHN
4869          JRST .+5
4870           SKIPL B
4871            AOSA NRXFR
4872             AOS NWXFR
4873           JRST QINTX
4874         SKIPL B
4875          AOSA NSRXFR
4876           AOS NSWXFR
4877 QINTX:  JRST DSKEX
4878
4879 QHUNG:  CONO DPC,DCLEAR+20+DSKCHN       ;DISK NOTICED TO BE HUNG, RESET IT
4880         SETOM QHUNGF                    ;TELL P.I. LEVEL TO RETRY OPERATION
4881         MOVE Q,QSDU
4882         AOS NTQHNG(Q)
4883         BUG INFO,[DSK: HUNG ON UNIT ],DEC,QSDU,[QCHPRG=],OCT,QCHPRG
4884         POPJ P,
4885 ]
4886 \f;READ - DROPS IN
4887
4888 IFN RH11P,[
4889         MOVEI T,%HMRED
4890 QINT6A: MOVEM T,QCHPRG
4891         MOVEM Q,QSDU
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
4895         ADDI R,1
4896         IOWRQ R,UBAPAG+QUBPG_1+1
4897         MOVE E,[-4000,,QUBPG_14]
4898         MOVEM E,QIOWD
4899         MOVE E,QSGL(C)
4900         PUSHJ P,QPOSR
4901         MOVEM E,QCHPGA
4902 QOVR:   IORDQ TT,%HRCS1         ; Enter here to recover from PI level lossage
4903         TRNN TT,%HXRDY
4904          JRST QOVR
4905         SKIPGE Q,QSDU
4906          BUG
4907 QECCX:  ;; Enter here from ECC correction code
4908         PUSHJ P,RHCLRC          ; Clear controller errors and select drive
4909         HLRZ TT,QCHPGA
4910         CAME TT,QPOS(Q)
4911          JRST DSKEX             ; Punt if not positioned in right place
4912         IOWRQ TT,%HRCYL         ; Store cylinder in drive
4913         HRRZ TT,QCHPGA
4914         IOWRQ TT,%HRADR         ; Store track and sector
4915         HLRZ TT,QIOWD
4916         IOWRQ TT,%HRWC          ; Store halfword count
4917         HRRZ TT,QIOWD
4918         IOWRQ TT,%HRBA          ; Store Unibus base address
4919         MOVE A,QCHPRG
4920         PUSHJ P,RHCMD           ; Go!
4921         MOVE A,TIME
4922         MOVEM A,LQTM
4923         CAILE C,NQCHN
4924          JRST .+5
4925           SKIPL B
4926            AOSA NRXFR
4927             AOS NWXFR
4928           JRST QINTX
4929         SKIPL B
4930          AOSA NSRXFR
4931           AOS NSWXFR
4932 QINTX:  JRST DSKEX
4933
4934 QHUNG:  MOVEI A,%HYCLR          ; Sock controller in jaw
4935         IOWRQ A,%HRCS2
4936         MOVE Q,QSDU
4937         PUSHJ P,RHSLCT          ; Select drive
4938         PUSHJ P,RHCLRD          ; Redundantly clear drive
4939         SETOM QHUNGF
4940         AOS NTQHNG(Q)
4941         BUG INFO,[DSK: HUNG ON UNIT #],DEC,QSDU,[ADDR=],OCT,QCHPGA
4942         POPJ P,
4943
4944 ] ;RH11P
4945 \f;READ - DROPS IN
4946
4947 IFN RH10P,[
4948         MOVEI T,%HMRED
4949 QINT6A: IORI T,QICWA_6  .SEE $HCICWA
4950         TLO T,%HRCTL(Q)
4951         MOVEM T,QCHPRG
4952         MOVEM Q,QSDU
4953         LSH R,10.               ;ASSEMBLE DF10-C CONTROL WORD
4954         SUBI R,1
4955         MOVNI E,2000
4956         DPB E,[$DFWC R]
4957         MOVEM R,QIOWD
4958         SETZM QIOWD+1
4959         MOVE E,QSGL(C)
4960         PUSHJ P,QPOSR
4961         MOVEM E,QCHPGA
4962 QOVR:   CONSZ DSK,20            ;ENTER HERE FOR RECOVER FROM PI HALT, OVERRUN
4963          JRST QOVR
4964         SKIPGE Q,QSDU
4965          BUG
4966         MOVEI TT,QIOWD
4967         HRRZM TT,QICWA
4968 QECCX:  SETZM QICWA+1           ;ENTER HERE FROM ECC CORRECTION CODE
4969         CONO DSK,%HOCLR+%HORAE+%HOATN+DSKCHN
4970         HLRZ TT,QCHPGA
4971         CAME TT,QPOS(Q)
4972          JRST DSKEX             ;DONT DO ANYTHING IF NOT WHERE YOU SHOULD BE
4973         MOVSI A,%HRCYL(Q)       ;STORE ADDRESS IN DRIVE
4974         HLR A,QCHPGA
4975         PUSHJ P,RHSET
4976         MOVSI A,%HRADR(Q)
4977         HRR A,QCHPGA
4978         PUSHJ P,RHSET
4979         MOVE A,QCHPRG
4980         PUSHJ P,RHSET
4981 IFN QRDCMP,[
4982         SETZM RDCPHS            ;ASSUME NO READ-COMPARE WANTED
4983         SKIPE QRCSW
4984          SETOM RDCPHS           ;REMEMBER TO READ-COMPARE LATER
4985 ];QRDCMP
4986         MOVE A,TIME
4987         MOVEM A,LQTM
4988         CAILE C,NQCHN
4989          JRST .+5
4990           SKIPL B
4991            AOSA NRXFR
4992             AOS NWXFR
4993           JRST QINTX
4994         SKIPL B
4995          AOSA NSRXFR
4996           AOS NSWXFR
4997 QINTX:  JRST DSKEX
4998
4999 QHUNG:  CONO DSK,%HOCLR+%HORST+%HOSTP+DSKCHN    ;HUNG, CLEAR CONTROLLER
5000         SETOM QHUNGF
5001         MOVE Q,QSDU
5002         AOS NTQHNG(Q)
5003         MOVSI A,%HRDCL(Q)
5004         HRRI A,%HMCLR           ;CLEAR DRIVE
5005         PUSHJ P,RHSET
5006         BUG INFO,[DSK: HUNG ON UNIT ],DEC,QSDU,[ADDR=],OCT,QCHPGA
5007         POPJ P,
5008 ]
5009 \f;READ - DROPS IN
5010 IFN DC10P,[
5011         MOVSI T,(DREAD)
5012 QINT6A: MOVEM T,QCHPRG
5013         MOVEM Q,QSDU
5014         DPB R,[DCBN+QCHPR2]     ;MEM BLOCK #
5015         DPB R,[DCBN+QCHPR3]     ;FOR POSSIBLE READ COMPARE
5016         MOVE E,QSGL(C)
5017         PUSHJ P,QPOSR   ;QPOSR ALSO STORES MAPPED UNIT IN QCHPRG
5018         IORB E,QCHPRG
5019         CLEARM QCHPR4   ;STORE DHALT FOR NO RCC
5020         CAILE C,NQCHN
5021          JRST QINT6S    ;SWAPPING CHNL
5022         SKIPL B
5023          AOSA NRXFR
5024           AOS NWXFR
5025         CAIE C,NQCHN    ;ALWAYS R COMPARE DIR WRITES
5026          SKIPLE QRCSW   ;SKIP ON NOT READ COMP EVERYTHING
5027           JRST QINT6B   ;RCC
5028         SKIPL QRCSW
5029          JUMPL B,QINT6B ;RCC WRITES
5030         HRRZ D,QSRAC(C)
5031         CAIL D,%QMUDR
5032         CAILE D,%QMTTR
5033          JRST QINT6C    ;NOT DIR READ
5034 QINT6B: TLZ E,340000    ;CHANGE TO READ COMPARE
5035         MOVEM E,QCHPR4
5036 QINT6C: SETOM QERS1     ;ERR VERIFY IND
5037 QOVR:   CONSZ DC0,DSSRUN+DSSACT
5038          JRST QOVR
5039         DATAO DC0,[DJMP QCHPRG] ;ENTRY ON OVERRUN
5040 QOVR1:  CONO DC0,DCSET+DCIENB+DSKCHN    ;INTERRUPT WHEN DONE
5041         MOVE A,TIME
5042         MOVEM A,LQTM
5043 QINTX:  JRST DSKEX
5044
5045 QINT6S: SKIPL B
5046          AOSA NSRXFR
5047           AOS NSWXFR
5048         JUMPL B,QINT6B  ;RCC WRITES
5049         JRST QINT6C     ;NOT READS
5050
5051 QHUNG:  CONO DC0,DCCSET+DSKCHN  ;HUNG, CLEAR CONTROLLER
5052         SETOM QHUNGF
5053         MOVE Q,QSDU
5054         AOS NTQHNG(Q)
5055         BUG INFO,[DSK: HUNG ON UNIT ],DEC,QSDU,[QCHPRG=],OCT,QCHPRG
5056         POPJ P,
5057 ]
5058
5059 QINT6W:IFE DMDSK,[
5060         MOVE T,[QXWDS-1,,QXWDS]
5061         BLT T,QXWDS+3
5062         CAIL C,NQCHN
5063          JRST QNT6W2    ;SWAP OR DIR WRITE
5064         MOVE A,QUDPR(C)
5065         MOVE T,QSNUD(A)
5066         MOVEM T,QXWDS+XWSYSN
5067         HRRZ A,QSNLCN(A)
5068         ADD A,QUDFPR(C)
5069         MOVE T,UNFN1(A)
5070         MOVEM T,QXWDS+XWFN1
5071         MOVE T,UNFN2(A)
5072         MOVEM T,QXWDS+XWFN2
5073         MOVE T,QSLBLK(C)
5074         DPB T,[XWBLK+QXWDS]
5075         LDB T,[MWC,,MEMBLT(R)]
5076         DPB T,[XWAWC+QXWDS]
5077 QNT6W2:
5078 ]
5079 IFN DC10P,      MOVSI T,(DWRITE)
5080 IFN RP10P,      MOVSI T,(DWRITC)
5081 IFN RH10P,      MOVEI T,%HMWRT
5082 IFN RH11P,      MOVEI T,%HMWRT
5083         JRST QINT6A
5084 \f
5085 IFN T300P,[
5086 T3IO:   MOVEM C,QSDCH1          ;THIS IS MORE OR LESS QINT6A FOR T-300
5087         MOVEM Q,QSDU1
5088         MOVEI A,%DMRED
5089         SKIPGE B,QSCRW(C)
5090          MOVEI A,%DMWRT
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
5095         MOVEM R,DSCPNT(E)
5096         ADDI R,400
5097         AOBJN E,.-2
5098         MOVE D,QSGL(C)          ;DO LIKE QPOSR
5099         CAIL D,NBLKS1
5100          BUG
5101         IDIVI D,NBLKC1
5102         MOVEM D,DSCCYL
5103         IMULI E,SECBL1
5104         IDIVI E,NSECS1
5105         MOVEM E,DSCHED
5106         MOVEM TT,DSCSEC
5107         PUSHJ P,T3CMD
5108         CAILE C,NQCHN
5109          JRST .+5
5110           SKIPL B
5111            AOSA NRXFR1
5112             AOS NWXFR1
5113           JRST QINTX
5114         SKIPL B
5115          AOSA NSRXF1
5116           AOS NSWXF1
5117         JRST QINTX
5118
5119 ;START T-300, COMMAND IN A, DRIVE IN Q
5120 T3CMD:  MOVEI TT,2561
5121         MOVEM TT,DSCCHK
5122         MOVE TT,TIME
5123         MOVEM TT,LQTM1
5124         MOVEI TT,-T300P(Q)
5125         MOVEM TT,DSCDRV
5126         HRRZM A,DSCCMD
5127         SETZM DSCDON
5128         MOVEI T,1
5129         MOVEM T,DSCREQ
5130         CONO DLC,100040+TTYCHN  ;INTERRUPT 11
5131         POPJ P,
5132
5133 QHUNG1: MOVE Q,QSDU1
5134         AOS NTQHNG(Q)
5135         BUG INFO,[DSK: HUNG ON T-300 UNIT ],DEC,QSDU
5136         MOVEI TT,5*60.*30.      ;SHUT UP FOR FIVE MINUTES
5137         ADDM TT,LQTM1
5138         POPJ P,
5139 ];T300P
5140 \f
5141 QDE:    MOVE C,QSDCH
5142 IFN RP10P, PUSHJ P,QERSOFT
5143 IFN DC10P, AOSE PKIDM
5144          SKIPGE Q,QSDU
5145           BUG
5146 IFN DC10P,[
5147         TRNE TT,DCKSER
5148          JRST .+3       ;GET CKS ERR
5149           TRNE TT,DRCER
5150            AOS NQCMPE(Q) ;# COMPARE ERRORS [WITH NO OTHER ERROR]
5151 ];DC10P
5152 IFN T300P,T3DE:         ;ENTER HERE FOR ERROR ON T-300
5153         AOS NQDE(Q)
5154         SKIPL R,QSCRW(C)
5155          AOSA NQRDE(Q)
5156           AOS NQWDE(Q)
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
5160          JRST QDE1
5161         TRNN R,1000
5162          JRST QDE2      ;TRY REPOSITION ONCE
5163 QERV3:  MOVE D,QSRAC(C)
5164         TRNE D,-%QMMAX
5165          BUG
5166         XCT .+1(D)      ;INVOKE IRRECOV ERROR HANDLER
5167 QERV:   OFFSET -.
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       ;..
5172 %QMRD1::JRST QPE2D
5173         JRST 4,QERV+.   ;ILL CODE
5174 %QMUDR::JRST QUDER1
5175 %QMMDR::JRST QDE1
5176 %QMTTR::JRST QDE1
5177 %QMUDW::JRST QDE1
5178 %QMMDW::JRST QDE1
5179 %QMTTW::JRST QDE1
5180 %QMSWP::JRST QSWPER
5181         JRST 4,QERV+.   ;ILL CODE
5182         JRST 4,QERV+.   ;ILL CODE
5183         JRST 4,QERV+.   ;ILL CODE
5184 %QMMAX::OFFSET 0
5185
5186 QSWPER: SKIPGE CIRPSW           ;TRY XFER AGAIN IF CIRPSW NOT AVAILABLE
5187         SKIPGE QSCRW(C)
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
5190         PUSH P,C
5191         PUSH P,Q
5192         MOVE C,[2200,,MEMPNT(A)]
5193         PUSHJ P,UCPRL
5194           400000,,QSWER1
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.
5200         MOVEI D,2
5201         DPB D,[410200,,@QSMMP(Q)]       ;PAGE IS OUT
5202         JRST QPE2D
5203
5204 QSWER1: PUSH P,T
5205         MOVSI T,%PJPAR
5206         IORM T,PIRQC(U)
5207         JRST POPTJ
5208 \f
5209 IFN DC10P,[
5210 QERV1:  SKIPN QCHPR4
5211          JRST QERV2     ;NOT SET FOR RCC
5212         CLEARM QERS1
5213 QERL2:  CONSZ DC0,DSSRUN+DSSACT
5214          JRST .-1
5215         DATAO DC0,[DJMP QCHPR4]
5216         JRST QOVR1
5217
5218 QERL1:  AOS Q,QERS1
5219         CAIGE Q,50.
5220          JRST QERL2
5221         AOSA NQWIRE
5222 QEROK:   AOS NQWRE
5223         MOVE C,QSDCH
5224         MOVE Q,QSDU
5225         SETOM QERS1
5226         JRST QERV2
5227 ]
5228 QDE2:   MOVEI R,1000
5229         MOVEM R,QERRS(C)        ;CLOBBER QERRS
5230         JRST QREC               ;AND TRY REPOSITIONING
5231
5232 IFN RP10P,[
5233 QERSOFT:LDB A,[DCYL+QCHPRG]     ;PARSE STARTING DISK ADDRESS
5234         LDB B,[DCYLXB+QCHPRG]
5235         LSH B,8
5236         IOR A,B
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
5241         POPJ P,
5242
5243 QRECAT: CONI DPC,A
5244         BUG INFO,[DSK: SEEK ERR DATAO=],OCT,QSEEK(Q),[CONI=],OCT,A,[DATAI=],OCT,E
5245         SETZM QSEEK(Q)
5246         JRST QREC
5247 ];RP10P
5248
5249 QHE:    MOVE C,QSDCH
5250 IFN RP10P, PUSHJ P,QERSOFT
5251         SKIPGE Q,QSDU
5252          BUG
5253 IFN T300P,T3HE:         ;ENTER HERE FOR ID ERROR ON T-300
5254         AOS NQHE(Q)
5255         AOS E,QERRS(C)
5256         CAIL E,5.
5257          JRST QHE2
5258 QREC:
5259 IFN T300P,[
5260         CAIL Q,T300P
5261          JRST [ SETOM QRCAL(Q)
5262                 MOVEI A,%DMREC
5263                 PUSHJ P,T3CMD
5264                 MOVEM Q,QSDU1   ;CONTROLLER IS TIED UP BY RECAL BECAUSE
5265                 JRST QINT1 ]    ;IT'S TOO DAMNED PSEUDO-INTELLIGENT
5266 ];T300P
5267 IFN DC10P,[
5268         MOVE TT,QTRAN(Q)
5269 QREC0:  DPB TT,[DUNFLD+QRECAL]
5270         SETOM QRCAL(TT)
5271         SETOM QSKT1(TT)
5272         CLEARM QSPPS(TT)
5273         CLEARM QPOSGL(TT)
5274         SETOM QPOS(TT)
5275         MOVEI T,10.             ;5-SECOND RECALIBRATE TIMEOUT
5276         MOVEM T,QRCTIM(TT)
5277         DATAO DC0,QRECAL
5278         CONO DC0,DCSET+DCATEB+DSKCHN    ;ENABLE ATTENTION
5279 ]
5280 IFN RP10P,[
5281         DPB Q,[DUNFLD+QRECAL]
5282         SETOM QPOS(Q)
5283         DATAO DPC,QRECAL
5284         CLEARM QSPPS(Q)
5285         SETOM QSKT1(Q)
5286         SETOM QRCAL(Q)  ;INDICATE RECALIBRATING THIS DISK
5287         CLEARM QPOSGL(Q)
5288 ]
5289 IFN RH11P,[
5290         PUSHJ P,RHSLCT          ; Select drive
5291         PUSHJ P,RHCLRD          ; Clear errors
5292         MOVEI A,%HMREC
5293         PUSHJ P,RHCMD           ; Recalibrate
5294         CLEARM QSPPS(Q)
5295         CLEARM QPOSGL(Q)
5296         SETOM QPOS(Q)
5297         SETOM QSKT1(Q)
5298         SETOM QRCAL(Q)
5299 ] ;RH11P
5300 IFN RH10P,[
5301         MOVSI A,%HRDCL(Q)
5302         HRRI A,%HMCLR
5303         PUSHJ P,RHSET           ;CLEAR ERROR OUT OF DRIVE.
5304         MOVSI A,%HRDCL(Q)
5305         HRRI A,%HMREC           ;RECALIBRATE
5306         PUSHJ P,RHSET           ;MAYBE SHOULD TRY OFFSET FIRST?
5307         CLEARM QSPPS(Q)
5308         CLEARM QPOSGL(Q)
5309         SETOM QPOS(Q)
5310         SETOM QSKT1(Q)
5311         SETOM QRCAL(Q)
5312 ]
5313         SETOM QSDU
5314         JRST QINT1      ;LOOK FOR SOME OTHER TRANSFER
5315 \f
5316 QHE2:   SKIPL QSCRW(C)  ;HANG UP OR POSITIONING ERR (AFTER 5 TRIES)
5317          JRST QERV3     ;IF READ, PERFORM RECOVERY
5318
5319 QPE2D:  MOVSI R,%QAPAR  ;IRRECOVERABLE ERROR
5320         IORM R,QSRAC(C)
5321         AOS QIRRCV
5322         MOVE D,QSGL(C)
5323         MOVEM D,QIRCBK  ;BLOCK # AT IRRCV ERR
5324         MOVEM Q,QIRUNT  ;SAVE UNIT TOO
5325         CAILE C,NQCHN
5326          AOS NIRSWE     ;# IRRCV SWAPPING ERRS
5327         MOVE I,Q
5328         SKIPGE QTUTO(I)
5329          JRST QPE2E     ;DON'T MESS WITH LOCKED TUT
5330         PUSHJ P,TUTPNT
5331         CAIN B,TUTLK    ;PRINT MESSAGE IF NOT YET LOCKED OUT
5332          JRST QINTI
5333         MOVEI B,TUTLK
5334         DPB B,D
5335 QPE2E:  BUG INFO,[DSK: IRREC DATA ERR #],DEC,QIRRCV,[UNIT=],DEC,QIRUNT,[BLK=],OCT,QIRCBK
5336         JRST QINTI
5337
5338 QUDER1: MOVEI R,1(Q)    ;TRY TO READ DIR FROM OTHER DISKS
5339 QUDER2: CAIL R,NQS
5340          MOVEI R,0
5341         CAME R,QDSKN(C)
5342          JRST QUDER4
5343         JRST QDE1       ;NO OTHER DISK AVAIL TO READ FROM, TRY AGAIN
5344
5345 QUDER4: SKIPGE QACT(R)
5346          AOJA R,QUDER2
5347         HRRZM R,QDSKN(C)        ;TRY THIS DISK
5348 IFN T300P,[
5349         CAIL Q,T300P
5350          JRST [ SETOM QSDU1     ;FREE DRIVE FORMERLY HACKING
5351                 SETOM QTUNT1
5352                 JRST T3UDE4 ]
5353 ];T300P
5354 IFE DC10P, SETOM QSKT1(Q)       ;FREE DRIVE FORMERLY HACKING
5355 IFN DC10P,[
5356         MOVE TT,QTRAN(Q)
5357         SETOM QSKT1(TT)
5358 ]
5359         SETOM QSDU
5360         SETOM QTUNT
5361 IFN T300P,T3UDE4:
5362         MOVE E,QSGL(C)
5363         MOVE Q,QDSKN(C)
5364         SETZM QERRS(C)
5365         JRST QINT5
5366 \f
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
5369         IDIVI TT,UFDBPW
5370         HLL TT,QBTBL(I)
5371         HRRZ I,QSNLCN(J)
5372         ADDI TT,UDDESC(I)
5373         LDB A,TT
5374         POPJ P,
5375
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
5379         HLL TT,QBTBL(I)
5380         HRRZ I,QSNLCN(H)
5381         ADDI TT,UDDESC(I)
5382         LDB R,TT
5383         POPJ P,
5384
5385 ;REACHED EOF ON READ
5386 QEOF:   SOS QDIRP(C)            ;AVOID GC UNHAPPINESS
5387         MOVSI I,%QAEFR
5388         IORM I,QSRAC(C)
5389         HLLZS QSRAC(C) .SEE %QMIDL ;IDLE THE CHANNEL
5390         AOS QSBFS(C)            ;TO UNHANG M.P. WHICH IS WAITING FOR BUF TO APPEAR
5391         JRST QINT2C
5392
5393 QINT4C:
5394 IFN DMDSK,[
5395         MOVSI E,%QAFNY
5396         ANDCAM E,QSRAC(C)
5397         TRZE A,20       ; FUNNY FILE BLOCK
5398          IORM E,QSRAC(C); INDICATE SO
5399 ]
5400         MOVEI E,0
5401         DPB A,[140500,,E]
5402         PUSHJ P,QIDRCH
5403         DPB A,[060600,,E]
5404         PUSHJ P,QIDRCH
5405         DPB A,[0600,,E]
5406         MOVEM E,QSLGL(C)
5407         JRST QINT4G
5408
5409 ;DECODE UNBYTE SPEC IN D.
5410 ;RETURNS BYTE SIZE IN D, NUMBER OF UNUSED BYTES IN LAST WORD IN E.
5411 QBDCD:  TRZE D,400
5412          JRST [ IDIVI D,100 ? POPJ P, ]
5413         TRZE D,200
5414          JRST [ IDIVI D,20 ? POPJ P, ]
5415         SUBI D,44
5416         JUMPGE D,[ IDIVI D,4 ? POPJ P, ]
5417         MOVNS D
5418         SETZ E,
5419         POPJ P,
5420
5421 ;ENCODE BYTE SIZE IN Q AND RESIDUE IN R INTO UNBYTE SPEC IN RH(Q)
5422 QBENC:  CAIG Q,3
5423          JRST [ IMULI Q,100 ? ADDI Q,400(R) ? POPJ P, ]
5424         CAIG Q,7
5425          JRST [ IMULI Q,20 ? ADDI Q,200(R) ? POPJ P, ]
5426         CAIG Q,18.
5427          JRST [ IMULI Q,4 ? ADDI Q,44(R) ? POPJ P, ]
5428         MOVNI Q,-44(Q)
5429         POPJ P,
5430 \f
5431 QINT3:  SKIPL DWUSR
5432          JRST QINT3X    ;DIR CHNL IN USE
5433 IFN T300P,[
5434         SKIPGE QSDU     ;DON'T GET PAST HERE UNLESS BOTH CONTROLLERS ARE IDLE
5435          SKIPL QSDU1
5436           JRST QINT3X
5437 ];T300P
5438         AOSL QDWFAR
5439          JRST [ MOVNI H,10.
5440                 MOVEM H,QDWFAR
5441                 JRST .+3 ]
5442            SKIPG QACTTM ;LAST ACTIVITY TOO RECENT
5443             JRST QUDW
5444         SKIPGE H,QMDRO
5445          JRST QTDW
5446         MOVE J,QACTB
5447         TDNN J,H
5448          JRST QTDW
5449         MOVSI Q,-NQS
5450 QMDW:   SKIPGE QACT(Q)
5451          JRST QMDWA     ;UNIT NOT ACTIVE
5452         MOVE J,DCHBT(Q)
5453         TDNN J,QMDRO
5454          JRST QMDWA
5455         HRLI Q,(SETZ)   ;INDICATE MFD WRITE IN PROGRESS
5456         MOVEM Q,QDWIP
5457         HRRZM Q,DWSKN
5458         MOVEI TT,%QMMDW
5459         HRRZM TT,QSRAC+NQCHN
5460         MOVSI TT,(SETZ)
5461         IORB TT,QMDRO
5462         MOVE C,MDCHK(TT)
5463         CAME C,[SIXBIT /M.F.D./]
5464          BUG HALT,[MFD CLOBBERED]
5465         HRRZ C,Q
5466         CAMN C,MDSK
5467          AOSA C,QAMDNO
5468           MOVE C,QAMDNO
5469         MOVEM C,MDNUM(TT)
5470         SETZM DWUSR
5471         MOVEI TT,MFDBLK
5472         MOVEM TT,QSGL+NQCHN
5473         HRRZ TT,QMDRO
5474         LSH TT,-10.
5475         MOVEM TT,QSCABN+NQCHN
5476         JRST QINT1
5477
5478 QMDWA:  AOBJN Q,QMDW
5479 QTDW:   SKIPG QACTTM
5480          JRST QUDW
5481         MOVSI Q,-NQS
5482 QTDW1:  SKIPGE QACT(Q)
5483          JRST QTDWA
5484         MOVE J,DCHBT(Q)
5485         SKIPL QTUTO(Q)
5486         TDNN J,QTUTO(Q)
5487          JRST QTDWA
5488         MOVSI H,240000
5489         TDNE H,QTUTO(Q)
5490          JRST QTDWA1
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
5493         CAIGE TT,100.
5494          JRST QTDWA
5495         ADDM TT,QTWRTM(Q)
5496         HRLI Q,200000
5497         MOVEM Q,QDWIP
5498         HRRZM Q,DWSKN
5499         MOVEI TT,%QMTTW
5500         HRRZM TT,QSRAC+NQCHN
5501         MOVSI TT,(SETZ)
5502         IORB TT,QTUTO(Q)
5503         MOVE H,QPKNM(Q)         ;VERIFY THAT TUT IS NOT BEING CLOBBERED
5504         MOVE C,QPKID(Q)
5505         CAMN H,QPAKID(TT)
5506          CAME C,QPKNUM(TT)
5507           BUG HALT,[TUT ],DEC,Q,[CLOBBERED]
5508         SETZM DWUSR
5509         MOVEI TT,MFDBLK         ;INITIATE WRITING OF FIRST BLOCK OF TUT
5510         SUB TT,NTBL(Q)
5511         MOVEM TT,QSGL+NQCHN
5512         LDB TT,[121000,,QTUTO(Q)]
5513         MOVEM TT,QSCABN+NQCHN
5514         JRST QINT1
5515 \f
5516 QTDWA1: ANDCAM J,QTUTO(Q)
5517 QTDWA:  AOBJN Q,QTDW1
5518 QUDW:   MOVSI C,-QNUD
5519 QDW4A:  MOVE J,QACTB    ;BITS CORRESP TO ACTIVE DISKS
5520 QDW4:   SKIPE TT,QSNUD(C)
5521         SKIPGE QSNLCN(C)
5522          JRST QDW3      ;SLOT VACANT OR LOCKED
5523         TDNE J,QSNLCN(C)
5524          JRST QUDW1     ;NEEDS TO BE WRITTEN ON SOME UNIT
5525 QDW3:   AOBJN C,QDW4A
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.
5528 IFN T300P,[
5529         SKIPL QSDU
5530          JRST DSKEX     ;STUFF NEEDS TO BE DONE BUT CANT NOW
5531 ] ;T300P
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
5537
5538 QUDW1:  MOVSI J,%QUDWM  ;WRITE RIGHT AWAY IF %QUDWM IS ON
5539         TDNN J,QSNLCN(C)
5540          SKIPE QSFBT(C) ;OR DISK BLOCKS (AND CORE) WAITING TO BE FREED
5541           JRST QUDW6
5542         SKIPG QACTTM    ; ACTIVITY TOO RECENT
5543          SKIPN QSNNR(C) ; THEN ONLY WRITE IF NOTHING POINTING TO DIRECTORY
5544           SKIPA
5545            JRST QDW3
5546         MOVSI Q,-NQS
5547 QUDW4:  SKIPGE QACT(Q)
5548          JRST QUDW3
5549         MOVE J,DCHBT(Q)
5550         TDNE J,QSNLCN(C)
5551          JRST QUDW2
5552 QUDW3:  AOBJN Q,QUDW4
5553         JRST QDW3
5554
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)
5557
5558 QUDW2:  MOVE I,QMDRO
5559         TLNE I,40000    ;IS THIS CODE OBSOLETE? LEFT FROM DAYS OF 1 MFD PER DRIVE?
5560          JRST QUDW2B    ;MASTER DIR NOT IN
5561         HRRZS Q
5562         CAMN Q,MDSK     ;SKIP IF NOT WRITING ON MASTER DISK
5563          PUSHJ P,QDIRCK ;BLESS THIS UFD!!!
5564         MOVSI TT,(SETZ)
5565         IORB TT,QSNLCN(C)       ;LOCK USER DIRECTORY
5566         MOVEI J,%QMUDW
5567         HRRZM J,QSRAC+NQCHN
5568         MOVE A,1(TT)            ;NAME AREA PTR
5569         MOVE J,QSNUD(C)
5570         CAMN J,UDNAME(TT)       ;MAKE SURE NOT ABOUT TO WRITE BAD DIRECTORY
5571          CAILE A,2000
5572           JSP TT,QUDCLB
5573         SUBI A,11.
5574         IMULI A,6
5575         SKIPL J,(TT)
5576         CAMLE J,A       ;FS PTR BAD?
5577          JSP TT,QUDCLB
5578         CLEARM DWUSR
5579         MOVEM Q,DWSKN
5580         MOVE TT,QSNMI(C)
5581         MOVEM TT,QSGL+NQCHN
5582         HRRZ TT,QSNLCN(C)
5583         LSH TT,-10.
5584         MOVEM TT,QSCABN+NQCHN
5585         HRRZM C,QDWIP
5586         CLEARM QERRS+NQCHN
5587         JRST QINT1
5588
5589 QUDW2B: ANDCAM J,QSNLCN(C)      ;CLEAR BIT + GO AWAY
5590         JRST QUDW3
5591
5592 ;GENERALLY GET HERE BY JSP TT,
5593 QUDCLB: BUG HALT,[DIR ],OCT,C,SIXBIT,QSNUD(C),[CLOBBERED]
5594 \f
5595 QDIRCK: PUSH P,TT       ;CHECKS FILES FOR REASONABLE DESCRIPTORS -
5596                         ; PRECEDING BYTE =0, FIRST BYTE NOT=0
5597         HRRZ A,QSNLCN(C)
5598         MOVEI B,1777(A) ;END OF NAMES
5599         ADD A,1(A)      ;BEGIN NAMES
5600 QDIRC1: CAMG B,A
5601          JRST POPTTJ    ;DONE
5602         SKIPN (A)
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
5606         IDIVI TT,6
5607         HLL TT,SBTBL(I) ;BYTE POINTER
5608         ADDI TT,UDDESC-1777(B)
5609         LDB I,TT
5610         JUMPN I,QUDCLB
5611         ILDB I,TT
5612         JUMPE I,QUDCLB
5613 QDIRC2: ADDI A,LUNBLK
5614         JRST QDIRC1
5615
5616 IFN RP10P,[
5617 QPOSR:  CAIL E,MBLKS
5618          BUG                    ;TOO BIG EVEN FOR RP03
5619 IFN DMDSK,[
5620         IMULI E,SECBLK
5621         IDIVI E,NSECS
5622         SETZM D
5623         DPB TT,[DSECT+D]
5624         IDIVI E,NHEDS
5625         DPB TT,[DSURF+D]
5626         DPB E,[DCYL+D]
5627         MOVEM E,QSPPS(Q)
5628         LSH E,-8
5629         DPB E,[DCYLXB+D]
5630         DPB Q,[DUNFLD+D]
5631 ]
5632 IFE DMDSK,[
5633         MOVEI D,0
5634         IDIVI E,NBLKSC
5635         DPB E,[DCYL+D]
5636         MOVEM E,QSPPS(Q)
5637         LSH E,-8
5638         DPB E,[DCYLXB+D]
5639         MOVE E,TT
5640         IMULI E,NSSECS
5641         IDIVI E,NHSECS
5642         DPB E,[DSURF+D]
5643         DPB TT,[DSECT+D]
5644         DPB Q,[DUNFLD+D]
5645 ]
5646         MOVE E,D
5647         POPJ P,
5648 ]
5649 IFN RH10P+RH11P,[
5650 IFE DMDSK, .ERR CHANGE QPOSR FOR 9-SECTOR BLOCKS!
5651 QPOSR:  CAIL E,NBLKS
5652          BUG
5653         IDIVI E,NBLKSC
5654         HRLZ D,E                ;CYLINDER IN LH
5655         MOVEM E,QSPPS(Q)
5656         MOVE E,TT
5657         IMULI E,SECBLK
5658         IDIVI E,NSECS
5659         LSH E,8
5660         IOR E,D                 ;SURFACE IN 1.9-2.4
5661         IOR E,TT                ;SECTOR IN 1.1-1.5
5662         POPJ P,
5663 ] ;RH10P+RH11P
5664 \f
5665 IFN DC10P,[
5666 QPOSR:  CAIL E,NBLKS
5667          BUG
5668         IDIVI E,NSECS
5669         MOVSI D,(DUNENB)
5670         DPB TT,[DSECT+D]
5671         IDIVI E,NHEDS
5672         DPB TT,[DSURF+D]
5673         SKIPGE TT,QTRAN(Q)
5674          ADDI E,NCYLS+XCYLS
5675         DPB E,[DCYL+D]
5676         MOVEM E,QSPPS(TT)
5677         MOVE E,D
5678         DPB TT,[DUNFLD+E]
5679         DPB TT,[DUNFLD+QCHPRG]
5680         SKIPGE TT,QPKID(Q)
5681          JRST QPOSRI
5682         DPB TT,[DPKID+E]
5683         POPJ P,
5684
5685 QPOSRI: MOVE TT,QTRAN(Q)        ;NEED PACK ID BEFORE PROCEEDING
5686         DPB TT,[DUNFLD+GPKID]
5687         SETOM QSKT1(TT)
5688         MOVEI A,TUTCYL
5689         SKIPGE QTRAN(Q)
5690          ADDI A,NCYLS+XCYLS
5691         DPB A,[DCYL+GPKID]
5692         MOVEM A,QPOS(TT)        ;WILL SEEK TO HERE AUTOMATICALLY
5693         MOVEM A,QPOSGL(TT)
5694         DATAO DC0,[DJMP GPKID]
5695         MOVEM Q,QSDU
5696         SETOM PKIDM
5697         JRST QINTX
5698
5699 QSPKID: CONSZ DC1,1777
5700          BUG            ;ERRORS
5701         LDB TT,[DPKID+RPKID]
5702         MOVEM TT,QPKID(Q)
5703         SETOM QSDU
5704         JRST QINT1
5705 ]
5706 \f
5707 SUBTTL DISK IOT ROUTINES
5708
5709 OVHMTR UUO      ;MORE RANDOM UUOS
5710
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.
5714
5715 QBO:    MOVEI T,BLKT
5716         JRST QUO1
5717
5718         SKIPA T,[SIOKT]
5719 QUIO:
5720 QUAO:    MOVEI T,CHRKT
5721 QUO1:   PUSH P,T
5722         PUSH P,TT
5723         PUSH P,D
5724         MOVE T,QSRAC(A)
5725         TLNE T,%QAACC+%QALNK
5726          PUSHJ P,QBWRA1 ;RANDOM ACCESS MODE HACK
5727         POP P,D
5728         POP P,TT
5729         MOVE E,QSBYTE(A)
5730         JSP B,CPOPJ     ;TRANSFER TO CHRKT, SIOKT, OR BLKT
5731 QBOV:   SETZ QSMPRP(A)
5732         QSMPRC(A)
5733         QSBWG
5734         SETZ QSBWW
5735         JRST QOCL
5736         TRNA
5737
5738 QBI:    MOVEI T,BLKT
5739         JRST QUI1
5740
5741         SKIPA T,[SIOKT]
5742 QUII:
5743 QUAI:    MOVEI T,CHRKTI
5744 QUI1:   PUSH P,T
5745         PUSH P,TT
5746         MOVE T,QSRAC(A)
5747         TLNE T,%QAACC+%QALNK
5748          PUSHJ P,QBRRA1
5749         POP P,TT
5750         MOVE E,QSBYTE(A)
5751         JSP B,CPOPJ             ;TRANSFER TO CHRKTI, SIOKT, OR BLKT
5752 QBIV:   QSMPRP(A)
5753         QSMPRC(A)
5754         QSBGB
5755         QSBRB
5756         JRST QICL
5757         SKIPG QSBFS(A)
5758 \f
5759 QBWRA1: TLNE T,%QALNK
5760          JRST IOCR10
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
5765         SKIPL QSGL(A)
5766          PUSHJ P,UFLS
5767         SKIPGE QSMDN(A)
5768          JRST QBWRA2
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
5772         MOVE Q,T
5773         SUB T,QMPBSZ(A)         ;SIZE OF CURRENT BUFFER IN BYTES
5774         JUMPL T,QBWRA3          ;SAME BLOCK AS NOW
5775 QBWRA2: PUSH P,R
5776         PUSH P,I
5777         PUSH P,C
5778         PUSHJ P,QSOCL5          ;CLEAR ANY CURRENT BUFFERS ETC
5779         PUSHJ P,QUDULK
5780         MOVE Q,QRADAD(A)
5781         PUSHJ P,QFNTR           ;LOCKS DIR IF SKIPS
5782          JRST QBWRA4            ;OFF END OF FILE
5783 QBWRA5: PUSHJ P,QUDULK
5784 QBWRA9: POP P,C
5785         POP P,I
5786         POP P,R
5787         CLEARM QSCRW(A)         ;SWITCH TO WRITE OVER MODE
5788         MOVSI Q,%QAMPU+%QAMWO   ;SET UPDATE ADR AND WRITE OVER
5789         IORM Q,QSRAC(A)
5790         CLEARM QSMPRC(A)
5791         MOVSI Q,%QAEFR+%QAEFW+%QAACC    ;CLEAR EOF, WRITE EOF, AND ACCESS FLAGS
5792         ANDCAM Q,QSRAC(A)
5793         MOVEI Q,%QMRD1          ;AND READ IN THE CURRENT BLOCK
5794         HRRM Q,QSRAC(A)
5795         POPJ P,
5796
5797 QBWRA4: JUMPE Q,QBWRA0
5798         CAME J,Q                ;MIGHT BE ADDING TO END OF FULL BLOCK
5799          JRST IOCER2
5800         JRST QBWRA9
5801
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
5805         POP P,C
5806         POP P,I
5807         POP P,R
5808         POPJ P,
5809 \f
5810 QBWRA3: SKIPGE TT,QSMDN(A)
5811          BUG                    ;NO BUFFER REALLY ACTIVE AT M.P.
5812         MOVSI J,%QAWOV
5813         TDNN J,QSRAC(A)
5814          JRST QBWRA7
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
5824          IBP TT
5825          SOJG J,.-1
5826         MOVEM TT,QSMPRP(A)
5827         SUB T,QMPBSZ(A)         ;MINUS # BYTES LEFT IN BLOCK
5828         MOVNM T,QSMPRC(A)
5829 QBRRA4: MOVSI Q,%QAACC
5830         ANDCAM Q,QSRAC(A)
5831         POPJ P,
5832
5833 QSKFRC: MOVN B,QSMPRC(A)
5834         ADD B,QMPBSZ(A)         ;NUMBER OF BYTES WRITTEN IN BLOCK
5835         MOVE C,QSRAC(A)
5836         TLNE C,%QAMWO
5837          TLNE C,%QAWOV
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)
5840                 JRST .+1 ]
5841         SETZM QSMPRC(A)         ;BUFFER WILL BE DISPOSED OF
5842         MOVSI E,%QUDWM
5843         SKIPGE QSMDN(A)
5844          SETZB B,E              ;NO BUFFER AFTER ALL
5845         ADD B,QFBLNO(A)         ;CURRENT POSITION IN FILE
5846         MOVSI C,%QAACC
5847         TDNN C,QSRAC(A)
5848          MOVEM B,QRADAD(A)      ;ACCESS BACK ON NEXT IOT
5849         IORB C,QSRAC(A)
5850         PUSHJ P,[TLNE C,%QAWOV  ;WRITE OUT THE BUFFER
5851                   JUMPN E,QSBWO2
5852                  JRST QSBWW ]
5853         SKIPE QMPTC(A)
5854          MOVSI E,%QUDWM
5855         PUSHJ P,QOCL2           ;STORE QMPTC IF NECESSARY
5856         IORM E,QSNLCN(H)        ;WRITE OUT DIR FAST IF CHANGED
5857         PUSHJ P,QUDULK
5858         JRST POPJ1
5859
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
5864                  PUSHJ P,UFLS
5865                 JRST QSKFIN ]
5866         CAIN T,%QMWRT           ;IF WRITE MODE
5867          JRST [ SKIPE QSBFS(A)  ;THEN WAIT FOR ALL BUFFERS TO GET WRITTEN
5868                  PUSHJ P,UFLS
5869                 JRST .+1 ]
5870         MOVE H,QUDPR(A)
5871         MOVE T,MDSK             ;HAS THE DIR BEEN CHANGED AND NOT WRITTEN
5872         MOVE T,DCHBT(T)         ;YET TO THE MASTER DISK?
5873         TDNN T,QSNLCN(H)
5874          JRST POPJ1
5875         MOVSI TT,%QUDWM         ;YES, WRITE IT OUT IMMEDIATELY
5876         IORM TT,QSNLCN(H)       ;AND DON'T RETURN UNTIL IT IS WRITTEN
5877         TDNE T,QSNLCN(H)
5878          PUSHJ P,UFLS
5879         JRST POPJ1
5880 \f
5881 QBRRA1: TLNE T,%QALNK
5882          JRST IOCR10
5883         SKIPGE QSMDN(A)
5884          JRST QBRRA2            ;NO MAIN PRGM BUFFER
5885         MOVE T,QRADAD(A)
5886         SUB T,QFBLNO(A)
5887         JUMPL T,QBRRA2
5888         MOVE Q,T
5889         SUB T,QMPBSZ(A)         ;SIZE OF CURRENT BUFFER
5890         JUMPL T,QBRRA3          ;SAME BLOCK AS NOW
5891 QBRRA2: PUSH P,R
5892         PUSH P,I
5893         PUSH P,C
5894         PUSHJ P,QICLW1          ;STOP THE CHANNEL AND FLUSH CURRENT BUFFERS
5895         MOVE A,D
5896         CLEARM QSBFS(A)         ;FLUSH POSSIBLE EXTRA AOSES WHEN PI HIT EOF
5897         MOVE Q,QRADAD(A)
5898         PUSHJ P,QFNTR
5899          JRST QBRRA5            ;OFF END OF FILE (DIR ALREADY UNLOCKED)
5900         POP P,C
5901         POP P,I
5902         POP P,R
5903         CLEARM QSMPRC(A)
5904         MOVSI Q,%QAMPU
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
5907         ANDCAM Q,QSRAC(A)
5908         MOVEI Q,%QMRD           ;START READING AGAIN
5909         HRRM Q,QSRAC(A)
5910         JRST QUDULK
5911
5912 QBRRA5: POP P,C
5913         POP P,I
5914         POP P,R
5915         CAME J,Q
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
5919         AOS QSBFS(A)
5920         SETZM QSMPRC(A)         ;AND READS ZERO WORDS
5921         JRST QBRRA4
5922
5923 QBRRA3: SKIPGE TT,QSMDN(A)
5924          JRST QBRRA2
5925         JRST QBWRA7
5926 \f
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
5932          HRRM Q,QSRAC(A)
5933         SKIPG QSBFS(A)
5934          PUSHJ P,UFLS
5935         POP P,A
5936 ;BLKT-SIOKT-CHRKT GET-BUFFER ROUTINE FOR DISK INPUT.
5937 QSBGB:  MOVSI Q,%QAPAR
5938         TDNE Q,QSRAC(A)
5939          JRST QSBGB2
5940         CONO PI,UTCOFF
5941         HRRZ Q,QBFP(A)
5942         JUMPE Q,[MOVSI J,%QAEFR ;SAID TO BE BUFFERS, BUT NONE THERE
5943                  TDNN J,QSRAC(A)
5944                   BUG           ;SHOULDN'T HAPPEN EXCEPT AT EOF
5945                  JRST QSBGB5 ]
5946         LDB J,[MLO,,MEMBLT(Q)]
5947         HRRM J,QBFP(A)
5948         SKIPN J
5949          SETZM QBFP(A)          ;LAST BLOCK, LIST NOW EMPTY
5950         HRRZ J,MEMPNT(Q)        ;GET SIZE OF BUFFER IN BYTES
5951         MOVEM J,QMPBSZ(A)
5952         LDB TT,[$QAMOD,,QSRAC(A)]
5953         SKIPN TT                ;DONT SOS IF IN WRITE OVER MODE
5954          SOS QSBFS(A)
5955 QSBWG4: MOVE TT,Q
5956         LSH TT,10.              ;RETURN ADDR OF BUFFER
5957         MOVEM Q,QSMDN(A)
5958         CONO PI,UTCON
5959         HLL TT,QSBYTE(A)
5960         MOVSI Q,%QAMPU
5961         TDNN Q,QSRAC(A)
5962          JRST SIOBG2
5963         MOVE Q,QRADAD(A)        ;DIDDLE PNTRS TO TAKE CARE OF RANDOM ACCESS WITHIN BLOCK
5964         SUB Q,QFBLNO(A)         ;DESIRED OFFSET WITHIN BLOCK
5965         SUB J,Q
5966         JUMPL J,IOCER2          ;OFF END OF FILE
5967         JUMPL Q,IOCER2          ;OFF FRONT OF FILE (NEGATIVE .ACCESS PNTR)
5968         PUSH P,J
5969         IDIVI Q,@QSBYTE(A)
5970         ADD TT,Q                ;ADJUST BYTE POINTER
5971         JUMPE J,.+3
5972          IBP TT
5973          SOJG J,.-1
5974         POP P,J
5975         MOVSI Q,%QAMPU          ;NOW IS SAFE TO TURN OFF FLAG
5976         ANDCAM Q,QSRAC(A)
5977         JRST SIOBG2
5978
5979 ;GET-BUFFER DETECTED EOF ON INPUT OR WRITE-OVER.
5980 QSBGB5: CONO PI,UTCON
5981         MOVE Q,QSRAC(A)
5982         TLNE Q,%QALNK
5983          JRST IOCR10
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
5988
5989 QWOG2:  SKIPGE QSCRW(A)         ;WAIT FOR WRITE TO FINISH
5990          PUSHJ P,UFLS
5991         JRST POPAJ              ;NOW RECYCLE AND WAIT FOR READ
5992 \f
5993 ;LEAVE WRITE OVER MODE
5994 QLWO:   MOVE H,QUDPR(A)
5995         PUSHJ P,QUDLK
5996         CONO PI,UTCOFF
5997         SETZM QBFP(A)           ;WRITEOVER MODE EXTEND FILE (SWITCH TO NORMAL MODE)
5998         CLEARM QSBFS(A)
5999         SETOM QSCRW(A)
6000         MOVE Q,QSLGL(A)
6001         HRRZM Q,QMPTN(A)        ;STORE BASE TRACK
6002         MOVSI Q,%QAEFR+%QAMWO   ;CLEAR EOF AND WRITEOVER
6003         ANDCAM Q,QSRAC(A)
6004         MOVEI Q,%QMWRT          ;NORMAL WRITE MODE
6005         HRRM Q,QSRAC(A)
6006         CLEARM QMPTC(A)         ;TRACK COUNT FOR TAKE N
6007         SETOM QMTTR(A)          ;NO TRACK RESERVED
6008         SETOM QMFTP(A)          ;GET NEW DECADE RESERVATION
6009         CONO PI,UTCON
6010         MOVE TT,QDIRP(A)        ;SEE IF GARBAGE COLLECTION NEEDED
6011         PUSH P,R
6012         PUSH P,I
6013         PUSHJ P,QMPDC1          ;CONV CHAR ADR TO BYTE PNTR (AND LDB IN R)
6014         POP P,I
6015         SKIPE R
6016          BUG
6017         MOVE R,QDIRP(A)
6018         ADDI R,NXLBYT+2
6019         CAMGE R,@QSNLCN(H)
6020          JRST QLWO1             ;DON'T NEED TO EXPAND F.S.
6021         MOVEI R,LUNBLK(TT)
6022         MOVE Q,QSNLCN(H)
6023         SUBI R,(Q)
6024         CAML R,UDNAMP(Q)
6025          JRST QSBWG7            ;DON'T HAVE ROOM.  GC
6026         MOVEI R,3*6             ;HAVE ROOM
6027         ADDM R,(Q)
6028 QLWO1:
6029 REPEAT NXLBYT+2,[
6030         ILDB R,TT
6031         JUMPN R,QSBWG7
6032 ]
6033         JRST QSBWG8             ;OK
6034
6035 QSBWG7: MOVSI R,%QAFUL          ;NO ROOM, GC BEFORE COMMITTING NEXT TRACK
6036         IORM R,QSRAC(A)
6037 QSBWG8: POP P,R
6038         JRST QUDULK
6039
6040 QSBGB2: ANDCAM Q,QSRAC(A)       ;DISK READ ERROR
6041         JRST IOCER3             ;TELL USER
6042 \f
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
6047         PUSH P,A
6048         TLNE Q,%QAMWO
6049          JRST QWOG1             ;JUMP IF WRITE OVER MODE
6050         HRRZ Q,QBFP(A)          ;NORMAL MODE
6051         JUMPE Q,QSBWG1          ;CAN ALWAYS HAVE ONE BUFFER
6052         MOVE Q,QWBUFS
6053         CAML Q,QWBFMX
6054          JRST POPAJ             ;TOO MANY WRITE BUFFERS QUEUED
6055 QSBWG1: PUSHJ P,QSTWG
6056         PUSHJ P,TCALL
6057           JRST IOMQ
6058          JRST QSBWG5            ;MEM FROZE OR NOT AVAILABLE
6059         MOVE Q,(P)              ;DISK CHNL #
6060         DPB Q,[MNUMB,,MEMBLT(A)]
6061         MOVEI Q,MU23B
6062         DPB Q,[MUR,,MEMBLT(A)]
6063         MOVE Q,A
6064         POP P,A
6065         AOS QSBFS(A)
6066         AOS QWBUFS
6067         HRRZ J,QSBYTE(A)
6068         IMULI J,2000
6069         MOVEM J,QMPBSZ(A)       ;FRESH BLOCK SIZE
6070         JRST QSBWG4
6071
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
6077 IFN QRSRVP,[
6078         HRRZ J,UDALLO(Q)
6079         JUMPE J,QSTWG0          ;NO ALLOCATION
6080         HRRZ H,UDBLKS(Q)        ;GET BLOCKS USED
6081         CAML H,J
6082          JRST IOCR13            ;HAS ALLOCATION AND USER IS TRYING TO EXCEED IT
6083 ]
6084 QSTWG0: MOVE J,QDSKN(A)
6085         SOSL QSFT(J)            ;RESERVE A TRACK
6086          POPJ P,
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?
6091          POPJ P,
6092         AOS QSFT(J)             ;NO, GIVE UP AND ERR OUT
6093         JRST IOCER9
6094
6095 QSTWG1: MOVE H,QUDPR(A)
6096         PUSHJ P,QUDLK
6097         PUSHJ P,QGC
6098          JRST IOCR12            ;DIR FULL
6099         PUSHJ P,QUDULK
6100         ANDCAM Q,QSRAC(A) .SEE %QAFUL
6101         JRST QSTWG
6102
6103 QSBWG5: POP P,A                 ;GET BACK QSK CHANNEL #
6104         MOVE J,QDSKN(A)
6105         AOS QSFT(J)             ;NO MEMORY; GIVE EVERYTHING BACK
6106         POPJ P,
6107 \f
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
6113         SKIPL D,QMTTR(A)
6114          JRST QTG1              ;TRACK ALREADY RESERVED
6115         PUSH P,I
6116         MOVE I,QDSKN(A)
6117         PUSHJ P,QGTRK           ;GET A TRACK
6118         POP P,I
6119         MOVEM D,QMTTR(A)
6120 QTG1:   MOVE H,QUDPR(A)         ;TRACK IN D
6121         PUSHJ P,QUDLK
6122         MOVE TT,QSNLCN(H)
6123         AOS UDBLKS(TT)
6124         MOVE TT,QMPTN(A)        ;GET PREVIOUS TRACK#
6125         CAIN D,1(TT)
6126          JRST QTG2              ;THIS TRACK IS CONSECUTIVE
6127         SKIPN QMPTC(A)          ;THIS TRACK NOT CONSEC CHECK COUNT OF PREV CONSEC BLOCKS
6128          JRST QTG3
6129         PUSH P,D                ;NON-ZERO SO STORE IN USER DIRECTORY
6130         MOVE D,QMPTC(A)
6131         CLEARM QMPTC(A)
6132         PUSHJ P,QUDS
6133         POP P,D
6134 QTG3:   MOVE J,QMTTR(A)         ;DESCRIPTOR WILL BE STORED
6135         MOVEM J,QMPTN(A)
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
6139          JRST QTG4              ;ALSO NO
6140         ADDI D,UDTKMX           ;NEXT BLOCK WITHIN N
6141         PUSHJ P,QUDS            ;STORE APPROPRIATE SKIP
6142 QTG5A:
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
6150         PUSH P,R
6151         IDIVI J,@QSBYTE(A)      ;CONVERT TO WORD COUNT
6152         JUMPE R,QTG7            ;EXACT MULTIPLE OF WORD
6153         AOS J
6154         MOVNS R
6155         ADDI R,@QSBYTE(A)       ;# BYTES RESIDUE IN LAST WORD
6156 QTG7:   DPB J,[MWC,,MEMBLT(Q)]  ;STORE ACTIVE WORD COUNT
6157         MOVE D,QSRAC(A)
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
6162         MOVE D,QUDFPR(A)
6163         ADD D,QSNLCN(H)
6164         DPB J,[UNWRDC+UNRNDM(D)] ;SET WORD COUNT OF LAST BLOCK
6165         LDB Q,[QSBSIZ(A)]
6166         PUSHJ P,QBENC           ;ENCODE BYTE CRUFT
6167         DPB Q,[UNBYTE+UNREF(D)]
6168         MOVE J,QACTB
6169         IORM J,QSNLCN(H)
6170 QTG6:   POP P,R
6171         PUSHJ P,QUDULK
6172         MOVE Q,QSMDN(A)
6173         MOVEI J,.BM MLO
6174         ANDCAM J,MEMBLT(Q)      ;SET END OF LIST INDICATOR IN MEMORY BLOCK
6175         CONO PI,UTCOFF
6176         HLRZ J,QBFP(A)          ;STORE MEMORY BLOCK IN OUTPUT LIST
6177         JUMPE J,QSBWW1
6178         DPB Q,[MLO,,MEMBLT(J)]
6179 QSBWW2: HRLM Q,QBFP(A)
6180         CONO PI,UTCON
6181         SETOM QSMDN(A)          ;MN PROG BUFFER NOW WRITTEN
6182         JRST QSTRTR             ;START ACTION IF 2311 IDLE AND RETURN
6183 \f
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
6188         HRRZ D,QSBYTE(A)
6189         IMULI D,2000
6190         SUB D,QMPBSZ(A)
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
6196         MOVSI D,%QAWOV
6197         IORM D,QSRAC(A)         ;FILLING LAST BLK PAST ORIG EOF
6198         POPJ P,                 ;FINISH OUT BLOCK
6199
6200 QSBWO2: MOVSI D,%QAWOV
6201         ANDCAM D,QSRAC(A)
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
6204         MOVE H,QUDPR(A)
6205         PUSHJ P,QUDLK
6206         SETOM QSCRW(A)          ;SWITCH TO WRITE MODE
6207         MOVEI Q,%QMWOV
6208         HRRM Q,QSRAC(A)
6209         JRST QTG5
6210
6211
6212 QTG4:   LDB D,[140500,,QMTTR(A)] ;WRITE LOAD ADDRESS
6213         IORI D,40
6214         PUSHJ P,QUDS
6215         LDB D,[060600,,QMTTR(A)]
6216         PUSHJ P,QUDS
6217         LDB D,[0600,,QMTTR(A)]
6218         PUSHJ P,QUDS
6219         JRST QTG5A
6220 \f 
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
6223         PUSH P,B
6224         PUSH P,E
6225         HRRZ R,QTUTO(I)
6226 QGTK4A: SKIPGE Q,QMFTP(A)
6227          JRST QGTK3A            ;FIRST TRACK
6228         IDIVI Q,DECADE
6229         HRREI J,-DECADE(J)      ;COMPUTE TRACKS REMAINING IN DECADE
6230         MOVE D,QMFTP(A)
6231         PUSHJ P,TUTPNT
6232         ADD D,[TUTBYT_14,,]     ;MAKE INTO ILDB-TYPE POINTER
6233         MOVE TT,QMFTP(A)
6234         EXCH D,TT
6235 QGTK3:  CAML D,QLASTB(R)
6236          JRST QGTK3A            ;REACHED END OF DISK
6237         ILDB Q,TT
6238         JUMPE Q,QGTK2
6239         AOJGE J,QGTK3A          ;DECADE OUT
6240         AOJA D,QGTK3
6241
6242 QGTK3A: CAILE A,NQCHN
6243          JRST QGTK3C            ;SWAP CHANNEL
6244 QGTK3D: MOVEI Q,DECADE
6245         ADDB Q,QTUTP(R)
6246 QGTK3B: MOVEM Q,QMFTP(A)
6247         CAMGE Q,QLASTB(R)
6248          JRST QGTK4A
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
6251         IDIVI Q,DECADE
6252         IMULI Q,DECADE
6253         MOVEM Q,QTUTP(R)
6254         JRST QGTK3B
6255
6256 QGTK2:  MOVEI B,1
6257         DPB B,TT
6258         MOVEM D,QMFTP(A)
6259         MOVE J,DCHBT(I)
6260         IORM J,QTUTO(I)
6261         POP P,E
6262         POP P,B
6263         POP P,R
6264         CAILE A,NQCHN
6265          POPJ P,                ;CALLED FROM SWAP OUT
6266         JRST QTULK
6267
6268 QGTK3C: CAML D,QSWAPA(R)
6269          JRST QGTK3D            ;IN NON-SWAP AREA
6270         AOS D
6271         CAMN D,QSWAPA(R)
6272          MOVEI D,NUDSL
6273         MOVEM D,QMFTP(A)
6274         JRST QGTK4A
6275 \f;STORE CHR IN D CHNL IN A USER DIR PNTR IN H
6276 ;CANNOT PCLSR NOR GC
6277
6278 QUDS:   PUSH P,I
6279         PUSH P,Q
6280         MOVE I,QDIRP(A)
6281         CAIGE I,2000*UFDBPW
6282         CAML I,@QSNLCN(H)       ;UDESCP
6283          BUG                    ;WRITING ABOVE F.S. PNTR?
6284         AOS QDIRP(A)
6285         IDIVI I,UFDBPW
6286         MOVE Q,QBTBL(Q)
6287         ADD Q,I
6288         SKIPL I,QSNLCN(H)
6289          BUG                    ;UFD WAS NOT LOCKED
6290         ADDI Q,UDDESC(I)
6291         LDB I,Q
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
6294         DPB D,Q
6295         ILDB I,Q                ;MAKE SURE FILE DESC WILL ALWAYS BE FOLLOWED BY ZERO
6296         SKIPE I
6297          BUG
6298 REPEAT NXLBYT+2,[               ;MAKE SURE THERE'S ROOM FOR ONE MORE TRACK
6299         ILDB I,Q
6300         JUMPN I,QUDS1
6301 ]
6302         MOVE I,QDIRP(A)
6303         ADDI I,NXLBYT+2
6304         CAMGE I,@QSNLCN(H)      ;UDESCP
6305          JRST QUDSX             ;DESC AREA NOT COLLIDING WITH LIM OF DESC SPACE
6306         MOVEI Q,LUNBLK(Q)
6307         MOVE I,QSNLCN(H)
6308         SUBI Q,(I)
6309         CAML Q,UDNAMP(I)
6310          JRST QUDS1             ;NO ROOM.
6311         MOVEI Q,3*UFDBPW        ;EXPAND DESC AREA
6312         ADDM Q,UDESCP(I)
6313         JRST QUDSX
6314
6315 QUDS1:  MOVSI Q,%QAFUL          ;NEED GC BEFORE STARTING ON NEXT TRACK
6316         IORM Q,QSRAC(A)
6317 QUDSX:  MOVE Q,QACTB
6318         IORM Q,QSNLCN(H)        ;SET DIRECTORY CHANGED
6319         POP P,Q
6320         POP P,I
6321         POPJ P,
6322
6323 QSBWW1: HRRM Q,QBFP(A)
6324         JRST QSBWW2
6325
6326 QSBRB1: MOVE A,D
6327 QSBRB:  PUSH P,A
6328         SKIPGE A,QSMDN(A)
6329          JRST POPAJ
6330         PUSHJ P,MEMR
6331         POP P,A
6332         HRRZ TT,QMPBSZ(A)
6333         ADDM TT,QFBLNO(A)       ;INCREMENT BYTE ADR IN FILE OF BEG OF NEXT BLOCK
6334         SETOM QSMDN(A)
6335         JRST QSTRTR
6336
6337 QTG2:   MOVE J,QMTTR(A)         ;INDICATE WE WILL STORE DESCRIPTOR FOR NEXT TRACK.
6338         MOVEM J,QMPTN(A)
6339         AOS D,QMPTC(A)          ;NEXT BLOCK IS CONSECUTIVE
6340         CAIGE D,UDTKMX
6341          JRST QTG5A
6342         SETZM QMPTC(A)          ;MAX # CONSECUTIVE BLOCKS, STORE DESC NOW
6343         PUSHJ P,QUDS
6344         JRST QTG5A
6345 \f
6346 SUBTTL  DIRHNG DEVICE
6347
6348 ;WHENEVER THE DIRECTORY SPECIFIED AS THE SNAME WHEN DIRHNG IS OPENED
6349 ;IS MODIFIED, YOU GET AN INTERRUPT ON THE DIRHNG DEVICE CHANNEL.
6350
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.
6358         HRRI A,DNDIRH
6359         MOVEM A,(R)     ;SET UP THE IOCHNM WITH IOTTB INDEX AND LIST CHAIN.
6360         HRLZM R,DIRHNG
6361         JRST CLKOJ1
6362
6363 ;CLOSE A DIRHNG DEVICE CHANNEL.
6364 DIRHCL: PUSHJ P,DIRHPS  ;REMOVE IT FROM THE LIST, AND
6365         SETZM (R)       ;MARK IT CLOSED.
6366         POPJ P,
6367
6368 ;IOPUSH A DIRHNG DEVICE CHANNEL.  REMOVE IT FROM THE LIST OF ALL SUCH.
6369 DIRHPS: MOVEI A,DIRHNG
6370         CONO PI,CLKOFF
6371 ;FIND THE PLACE THAT POINTS AT THIS IOCHNM WORD.
6372 DIRHC1: HLRZ B,(A)
6373         CAIN B,(R)
6374          JRST DIRHC2
6375         SKIPN A,B       ;END OF LIST REACHED =>
6376          BUG            ;THIS IOCHNM ISN'T IN THE LIST.  BUT IT IS SUPPOSED TO BE!
6377         JRST DIRHC1
6378
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
6381         HRLM B,(A)
6382         JRST CLKONJ
6383
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.
6386
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.
6392          BUG
6393         MOVE A,R
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.
6397         IORM A,IFPIR(U)
6398         POPJ P,
6399
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.
6402 ;CLOBBERS B, C, D.
6403 DIRSIG: CONO PI,CLKOFF
6404         MOVEI B,DIRHNG
6405 DIRSI0: HLRZ B,(B)      ;GET IOCHNM ADDR OF NEXT DIRHNG DEVICE.
6406         JUMPE B,CLKONJ
6407         HRRZ C,IOCHST-IOCHNM(B)
6408         CAIE C,(A)      ;DOES IT LOOK AT THIS DIRECTORY?
6409          JRST DIRSI0
6410         MOVEI C,-IOCHNM(B)      ;YES => FIGURE OUT USER INDEX OF JOB IT BELONGS TO.
6411         IDIVI C,LUBLK
6412         IMULI C,LUBLK   ;C NOW HAS USER INDEX.
6413         MOVNI D,IOCHNM(C)
6414         ADD D,B         ;D GETS CHANNEL NUMBER
6415         MOVE D,CHNBIT(D)
6416         AND D,MSKST2(C) ;INTERRUPT THE USER ON THAT CHANNEL, IF IT'S ENABLED.
6417         IORM D,IFPIR(C)
6418         JRST DIRSI0