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