summaryrefslogtreecommitdiff
path: root/v2.0/source/BUF.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v2.0/source/BUF.ASM')
-rw-r--r--v2.0/source/BUF.ASM508
1 files changed, 508 insertions, 0 deletions
diff --git a/v2.0/source/BUF.ASM b/v2.0/source/BUF.ASM
new file mode 100644
index 0000000..f1ad800
--- /dev/null
+++ b/v2.0/source/BUF.ASM
@@ -0,0 +1,508 @@
1;
2; buffer management for MSDOS
3;
4
5INCLUDE DOSSEG.ASM
6
7CODE SEGMENT BYTE PUBLIC 'CODE'
8 ASSUME SS:DOSGROUP,CS:DOSGROUP
9
10.xlist
11.xcref
12INCLUDE DOSSYM.ASM
13INCLUDE DEVSYM.ASM
14.cref
15.list
16
17 i_need BuffHead,DWORD
18 i_need PreRead,WORD
19 i_need LastBuffer,DWORD
20 i_need CurBuf,DWORD
21 i_need WPErr,BYTE
22
23SUBTTL SETVISIT,SKIPVISIT -- MANAGE BUFFER SCANS
24PAGE
25 procedure SETVISIT,near
26ASSUME DS:NOTHING,ES:NOTHING
27
28; Inputs:
29; None
30; Function:
31; Set up a scan of I/O buffers
32; Outputs:
33; All visit flags = 0
34; NOTE: This pre-scan is needed because a hard disk error
35; may cause a scan to stop in the middle leaving some
36; visit flags set, and some not set.
37; DS:DI Points to [BUFFHEAD]
38; No other registers altered
39
40 LDS DI,[BUFFHEAD]
41 PUSH AX
42 XOR AX,AX
43SETLOOP:
44 MOV [DI.VISIT],AL
45 LDS DI,[DI.NEXTBUF]
46 CMP DI,-1
47 JNZ SETLOOP
48 LDS DI,[BUFFHEAD]
49 POP AX
50 return
51
52 entry SKIPVISIT
53ASSUME DS:NOTHING,ES:NOTHING
54
55; Inputs:
56; DS:DI Points to a buffer
57; Function:
58; Skip visited buffers
59; Outputs:
60; DS:DI Points to next unvisited buffer
61; Zero is set if skip to LAST buffer
62; No other registers altered
63
64 CMP DI,-1
65 retz
66 CMP [DI.VISIT],1
67 retnz
68 LDS DI,[DI.NEXTBUF]
69 JMP SHORT SKIPVISIT
70 return
71SetVisit ENDP
72
73
74SUBTTL SCANPLACE, PLACEBUF -- PUT A BUFFER BACK IN THE POOL
75PAGE
76 procedure ScanPlace,near
77ASSUME DS:NOTHING,ES:NOTHING
78
79; Inputs:
80; Same as PLACEBUF
81; Function:
82; Save scan location and call PLACEBUF
83; Outputs:
84; DS:DI Points to saved scan location
85; SI destroyed, other registers unchanged
86
87 PUSH ES
88 LES SI,[DI.NEXTBUF] ; Save scan location
89 CALL PLACEBUF
90 PUSH ES
91 POP DS ; Restore scan location
92 MOV DI,SI
93 POP ES
94 return
95ScanPlace ENDP
96
97NRETJ: JMP SHORT NRET
98
99 procedure PLACEBUF,NEAR
100ASSUME DS:NOTHING,ES:NOTHING
101
102; Input:
103; DS:DI points to buffer
104; Function:
105; Remove buffer from queue and re-insert it in proper place.
106; If buffer doesn't go at end, and isn't free, decrement
107; priorities.
108; NO registers altered
109;
110; DS:SI -- Curbuf, current buffer in list
111; ES:DI -- Buf, buffer passed as argument
112; BP:CX -- Pointsave, saved Buf.nextbuf
113; DX:BX -- Lastbuf, previous buffer in list
114; AL -- Inserted, Buf has been inserted
115; AH -- Removed, Buf has been removed
116
117 IF IBM
118 IF NOT IBM
119 invoke save_world
120 XOR AX,AX ; Inserted = Removed = FALSE
121 LES CX,[DI.NEXTBUF]
122 MOV BP,ES ; Pointsave = Buf.nextbuf
123 MOV SI,DS
124 MOV ES,SI ; Buf is ES:DI
125 LDS SI,[BUFFHEAD] ; Curbuf = HEAD
126 CALL POINTCOMP ; Buf == HEAD?
127 JNZ TNEWHEAD
128 CMP CX,-1 ; Buf is LAST?
129 JZ NRETJ ; Only one buffer, nothing to do
130 MOV WORD PTR [BUFFHEAD],CX
131 MOV WORD PTR [BUFFHEAD+2],BP ; HEAD = Pointsave
132 INC AH ; Removed = TRUE
133 MOV DS,BP
134 MOV SI,CX ; Curbuf = HEAD
135TNEWHEAD:
136 MOV BL,ES:[DI.BUFPRI]
137 CMP BL,[SI.BUFPRI]
138 JGE BUFLOOP
139NEWHEAD: ; If Buf.pri < HEAD.pri
140 MOV WORD PTR ES:[DI.NEXTBUF],SI
141 MOV WORD PTR ES:[DI.NEXTBUF+2],DS ; Buf.nextbuf = HEAD
142 MOV WORD PTR [BUFFHEAD],DI
143 MOV WORD PTR [BUFFHEAD+2],ES ; HEAD = Buf
144 INC AL ; Inserted = TRUE
145 OR AH,AH
146 JNZ NRET ; If Removed == TRUE
147BUFLOOP:
148 PUSH DS
149 PUSH SI
150 LDS SI,[SI.NEXTBUF]
151 CALL POINTCOMP
152 POP SI
153 POP DS
154 JNZ TESTINS
155 MOV WORD PTR [SI.NEXTBUF],CX ; If Curbuf.nextbuf == buf
156 MOV WORD PTR [SI.NEXTBUF+2],BP ; Curbuf.nextbuf = Pointsave
157 INC AH ; Removed = TRUE
158 OR AL,AL
159 JNZ SHUFFLE ; If Inserted == TRUE
160TESTINS:
161 OR AL,AL
162 JNZ LOOKBUF
163 PUSH CX ; If NOT Inserted
164 MOV CL,ES:[DI.BUFPRI]
165 CMP CL,[SI.BUFPRI]
166 POP CX
167 JGE LOOKBUF
168 PUSH DS ; If Buf.pri < Curbuf.pri
169 MOV DS,DX
170 MOV WORD PTR [BX.NEXTBUF],DI
171 MOV WORD PTR [BX.NEXTBUF+2],ES ; Lastbuf.nextbuf = Buf
172 POP DS
173 MOV WORD PTR ES:[DI.NEXTBUF],SI
174 MOV WORD PTR ES:[DI.NEXTBUF+2],DS ; Buf.nextbuf = Curbuf
175 INC AL ; Inserted = TRUE
176 OR AH,AH
177 JNZ SHUFFLE ; If Removed == TRUE
178LOOKBUF:
179 MOV BX,SI
180 MOV DX,DS ; Lastbuf = Curbuf
181 CMP WORD PTR [SI.NEXTBUF],-1
182 JZ ISLAST
183 LDS SI,[SI.NEXTBUF] ; Curbuf = Curbuf.nextbuf
184 JMP SHORT BUFLOOP
185ISLAST: ; If Curbuf is LAST
186 MOV WORD PTR [SI.NEXTBUF],DI
187 MOV WORD PTR [SI.NEXTBUF+2],ES ; Curbuf.nextbuf = Buf
188 MOV WORD PTR ES:[DI.NEXTBUF],-1
189 MOV WORD PTR ES:[DI.NEXTBUF+2],-1 ; Buf is LAST
190NRET:
191 invoke restore_world
192 return
193
194SHUFFLE:
195 LDS DI,[BUFFHEAD]
196DECLOOP:
197 CMP [DI.BUFPRI],FREEPRI
198 JZ NODEC
199 DEC [DI.BUFPRI]
200NODEC:
201 LDS DI,[DI.NEXTBUF]
202 CMP DI,-1
203 JNZ DECLOOP
204 JMP SHORT NRET
205 ENDIF
206 ENDIF
207
208 invoke save_world
209 LES CX,[DI.NEXTBUF]
210 CMP CX,-1 ; Buf is LAST?
211 JZ NRET ; Buffer already last
212 MOV BP,ES ; Pointsave = Buf.nextbuf
213 PUSH DS
214 POP ES ; Buf is ES:DI
215 LDS SI,[BUFFHEAD] ; Curbuf = HEAD
216 CALL POINTCOMP ; Buf == HEAD?
217 JNZ BUFLOOP
218 MOV WORD PTR [BUFFHEAD],CX
219 MOV WORD PTR [BUFFHEAD+2],BP ; HEAD = Pointsave
220 JMP SHORT LOOKEND
221
222BUFLOOP:
223 PUSH DS
224 PUSH SI
225 LDS SI,[SI.NEXTBUF]
226 CALL POINTCOMP
227 JZ GOTTHEBUF
228 POP AX
229 POP AX
230 JMP SHORT BUFLOOP
231
232GOTTHEBUF:
233 POP SI
234 POP DS
235 MOV WORD PTR [SI.NEXTBUF],CX ; If Curbuf.nextbuf == buf
236 MOV WORD PTR [SI.NEXTBUF+2],BP ; Curbuf.nextbuf = Pointsave
237LOOKEND:
238 PUSH DS
239 PUSH SI
240 LDS SI,[SI.NEXTBUF]
241 CMP SI,-1
242 JZ GOTHEEND
243 POP AX
244 POP AX
245 JMP SHORT LOOKEND
246
247GOTHEEND:
248 POP SI
249 POP DS
250 MOV WORD PTR [SI.NEXTBUF],DI
251 MOV WORD PTR [SI.NEXTBUF+2],ES ; Curbuf.nextbuf = Buf
252 MOV WORD PTR ES:[DI.NEXTBUF],-1
253 MOV WORD PTR ES:[DI.NEXTBUF+2],-1 ; Buf is LAST
254NRET:
255 invoke restore_world
256 return
257
258PLACEBUF ENDP
259
260 procedure PLACEHEAD,NEAR
261ASSUME DS:NOTHING,ES:NOTHING
262
263; SAME AS PLACEBUF except places buffer at head
264
265 invoke save_world
266 PUSH DS
267 POP ES
268 LDS SI,[BUFFHEAD]
269 MOV WORD PTR [BUFFHEAD],DI
270 MOV WORD PTR [BUFFHEAD+2],ES
271 MOV WORD PTR ES:[DI.NEXTBUF],SI
272 MOV WORD PTR ES:[DI.NEXTBUF+2],DS
273LOOKEND2:
274 PUSH DS
275 PUSH SI
276 LDS SI,[SI.NEXTBUF]
277 CALL POINTCOMP
278 JZ GOTHEEND2
279 POP AX
280 POP AX
281 JMP SHORT LOOKEND2
282
283GOTHEEND2:
284 POP SI
285 POP DS
286 MOV WORD PTR [SI.NEXTBUF],-1
287 MOV WORD PTR [SI.NEXTBUF+2],-1 ; Buf is LAST
288 JMP SHORT NRET
289
290PLACEHEAD ENDP
291
292SUBTTL POINTCOMP -- 20 BIT POINTER COMPARE
293PAGE
294 procedure PointComp,NEAR
295ASSUME DS:NOTHING,ES:NOTHING
296
297; Compare DS:SI to ES:DI (or DS:DI to ES:SI) for equality
298; DO NOT USE FOR < or >
299; No Registers altered
300
301 CMP SI,DI
302 retnz
303 PUSH CX
304 PUSH DX
305 MOV CX,DS
306 MOV DX,ES
307 CMP CX,DX
308 POP DX
309 POP CX
310 return
311PointComp ENDP
312
313SUBTTL GETBUFFR -- GET A SECTOR INTO A BUFFER
314PAGE
315 procedure GETBUFFR,NEAR
316ASSUME DS:DOSGROUP,ES:NOTHING
317
318; Input:
319; AH = Priority buffer is to have
320; AL = 0 means sector must be pre-read
321; ELSE no pre-read
322; DX = Desired physical sector number
323; ES:BP = Pointer to drive parameters
324; Function:
325; Get the specified sector into one of the I/O buffers
326; And shuffle the queue
327; Output:
328; [CURBUF] Points to the Buffer for the sector
329; DX,ES:BP unchanged, all other registers destroyed
330
331 XOR SI,SI
332 entry GETBUFFRB
333 MOV [PREREAD],AX
334 MOV AL,ES:[BP.dpb_drive]
335 LDS DI,[LASTBUFFER]
336ASSUME DS:NOTHING
337 CMP DI,-1 ; Recency pointer valid?
338 JZ SKBUF ; No
339 CMP DX,[DI.BUFSECNO]
340 JNZ SKBUF ; Wrong sector
341 CMP AL,[DI.BUFDRV]
342 JNZ SKBUF ; Wrong Drive
343 JMP SHORT JUSTBUF ; Just asked for same buffer
344SKBUF:
345 LDS DI,[BUFFHEAD]
346NXTBFF:
347 CMP DX,[DI.BUFSECNO]
348 JNZ BUMP
349 CMP AL,[DI.BUFDRV]
350 JNZ BUMP
351 JMP SHORT SETINF
352BUMP:
353 LDS DI,[DI.NEXTBUF]
354 CMP DI,-1
355 JNZ NXTBFF
356 LDS DI,[BUFFHEAD]
357 PUSH SI
358 PUSH DX
359 PUSH BP
360 PUSH ES
361 CALL BUFWRITE ; Write out the dirty buffer
362 POP ES
363 POP BP
364 POP DX
365 POP SI
366RDSEC: ; Read in the new sector
367 TEST BYTE PTR [PREREAD],-1
368 JNZ SETBUF
369 LEA BX,[DI.BufInSiz] ; Point at buffer
370 MOV CX,1
371 PUSH SI
372 PUSH DI
373 PUSH DX
374 OR SI,SI
375 JZ NORMSEC
376 invoke FATSECRD
377 JMP SHORT GOTTHESEC ; Buffer is marked free if read barfs
378NORMSEC:
379 invoke DREAD ; Buffer is marked free if read barfs
380GOTTHESEC:
381 POP DX
382 POP DI
383 POP SI
384SETBUF:
385 MOV [DI.BUFSECNO],DX
386 MOV WORD PTR [DI.BUFDRVDP],BP
387 MOV WORD PTR [DI.BUFDRVDP+2],ES
388 XOR AH,AH
389 MOV AL,ES:[BP.dpb_drive]
390 MOV WORD PTR [DI.BUFDRV],AX
391SETINF:
392 MOV AX,1 ; Default to not a FAT sector
393 OR SI,SI
394 JZ SETSTUFFOK
395 MOV AL,ES:[BP.dpb_FAT_count]
396 MOV AH,ES:[BP.dpb_FAT_size]
397SETSTUFFOK:
398 MOV WORD PTR [DI.BUFWRTCNT],AX
399 CALL PLACEBUF
400JUSTBUF:
401 MOV WORD PTR [CURBUF+2],DS
402 MOV WORD PTR [LASTBUFFER+2],DS
403 PUSH SS
404 POP DS
405ASSUME DS:DOSGROUP
406 MOV WORD PTR [CURBUF],DI
407 MOV WORD PTR [LASTBUFFER],DI
408 return
409GETBUFFR ENDP
410
411
412SUBTTL FLUSHBUF -- WRITE OUT DIRTY BUFFERS
413PAGE
414 procedure FlushBuf,NEAR
415ASSUME DS:DOSGROUP,ES:NOTHING
416
417; Input:
418; DS = DOSGROUP
419; AL = Physical unit number
420; = -1 for all units
421; Function:
422; Write out all dirty buffers for unit, and flag them as clean
423; DS Preserved, all others destroyed (ES too)
424
425 LDS DI,[BUFFHEAD]
426ASSUME DS:NOTHING
427 MOV AH,-1
428NXTBUFF:
429 CMP [DI.BUFDRV],AH
430 JZ SKIPBFF ; Skip free buffers
431 CMP AH,AL
432 JZ DOBUFFER ; Do all dirty buffers
433 CMP AL,[DI.BUFDRV]
434 JNZ SKIPBFF ; Buffer not for this unit
435DOBUFFER:
436 CMP BYTE PTR [DI.BUFDIRTY],0
437 JZ SKIPBFF ; Buffer not dirty
438 PUSH AX
439 PUSH WORD PTR [DI.BUFDRV]
440 CALL BUFWRITE
441 POP AX
442 XOR AH,AH ; Buffer is clean
443 CMP AL,BYTE PTR [WPERR]
444 JNZ NOZAP
445 MOV AL,0FFH ; Invalidate buffer, it is inconsistent
446NOZAP:
447 MOV WORD PTR [DI.BUFDRV],AX
448 POP AX ; Search info
449SKIPBFF:
450 LDS DI,[DI.NEXTBUF]
451 CMP DI,-1
452 JNZ NXTBUFF
453 PUSH SS
454 POP DS
455 return
456FlushBuf ENDP
457
458
459SUBTTL BUFWRITE -- WRITE OUT A BUFFER IF DIRTY
460PAGE
461 procedure BufWrite,NEAR
462ASSUME DS:NOTHING,ES:NOTHING
463
464; Input:
465; DS:DI Points to the buffer
466; Function:
467; Write out all the buffer if dirty.
468; Output:
469; Buffer marked free
470; DS:DI Preserved, ALL others destroyed (ES too)
471
472 MOV AX,00FFH
473 XCHG AX,WORD PTR [DI.BUFDRV] ; Free, in case write barfs
474 CMP AL,0FFH
475 retz ; Buffer is free.
476 OR AH,AH
477 retz ; Buffer is clean.
478 CMP AL,BYTE PTR [WPERR]
479 retz ; If in WP error zap buffer
480 LES BP,[DI.BUFDRVDP]
481 LEA BX,[DI.BufInSiz] ; Point at buffer
482 MOV DX,[DI.BUFSECNO]
483 MOV CX,WORD PTR [DI.BUFWRTCNT]
484 MOV AL,CH ; [DI.BUFWRTINC]
485 XOR CH,CH
486 MOV AH,CH
487 PUSH DI
488WRTAGAIN:
489 PUSH CX
490 PUSH AX
491 MOV CX,1
492 PUSH BX
493 PUSH DX
494 invoke DWRITE ; Write out the dirty buffer
495 POP DX
496 POP BX
497 POP AX
498 POP CX
499 ADD DX,AX
500 LOOP WRTAGAIN
501 POP DI
502 return
503BufWrite ENDP
504
505do_ext
506
507CODE ENDS
508 END