summaryrefslogtreecommitdiff
path: root/v4.0/src/DOS/BUF.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/DOS/BUF.ASM')
-rw-r--r--v4.0/src/DOS/BUF.ASM982
1 files changed, 982 insertions, 0 deletions
diff --git a/v4.0/src/DOS/BUF.ASM b/v4.0/src/DOS/BUF.ASM
new file mode 100644
index 0000000..f6a6b7d
--- /dev/null
+++ b/v4.0/src/DOS/BUF.ASM
@@ -0,0 +1,982 @@
1; SCCSID = @(#)buf.asm 1.1 85/04/09
2TITLE BUF - MSDOS buffer management
3NAME BUF
4; Low level routines for buffer cache management
5;
6; GETCURHEAD
7; SET_MAP_PAGE
8; SAVE_MAP
9; RESTORE_MAP
10; SETVISIT
11; ScanPlace
12; PLACEBUF
13; PLACEHEAD
14; PointComp
15; GETBUFFR
16; GETBUFFRB
17; FlushBuf
18; BufWrite
19; SKIPVISIT
20; SET_RQ_SC_PARMS
21;
22; Revision history:
23;
24; AN000 version 4.00 Jan. 1988
25; A004 PTM 3765 -- Disk reset failed
26
27; NEW PROCS FOR BUFFERS FIX:
28
29; SAVE_USER_MAP
30; RESTORE_USER_MAP
31; DETECT_COLLISION
32; SETUP_EMS_BUFFERS
33;
34
35
36;
37; get the appropriate segment definitions
38;
39.xlist
40INCLUDE dosseg.asm
41
42CODE SEGMENT BYTE PUBLIC 'CODE'
43 ASSUME SS:DOSGROUP,CS:DOSGROUP
44
45.xcref
46INCLUDE DOSSYM.INC
47INCLUDE DEVSYM.INC
48include version.inc
49.cref
50.list
51
52Installed = TRUE
53
54 i_need BuffHead,DWORD
55 i_need PreRead,WORD
56 i_need LastBuffer,DWORD
57 i_need CurBuf,DWORD
58 i_need WPErr,BYTE
59 i_need ALLOWED,BYTE
60 i_need FAILERR,BYTE
61 i_need HIGH_SECTOR,WORD ; DOS 4.00 >32mb ;AN000;
62 i_need CurHashEntry,DWORD ; DOS 4.00 current Hash entry ;AN000;
63 i_need BUF_HASH_PTR,DWORD ; DOS 4.00 Hash table pointer ;AN000;
64 i_need BUF_HASH_COUNT,WORD ; DOS 4.00 Hash table entries ;AN000;
65 i_need SC_CACHE_PTR,DWORD ; DOS 4.00 seconadary cache table ;AN000;
66 i_need SC_CACHE_COUNT,WORD ; DOS 4.00 secondary cache entries ;AN000;
67 i_need BUF_EMS_MODE,BYTE ; DOS 4.00 EMS mode ;AN000;
68 i_need BUF_EMS_HANDLE,WORD ; DOS 4.00 buffer EMS handle ;AN000;
69 i_need SC_SECTOR_SIZE,WORD ; DOS 4.00 sector size ;AN000;
70 i_need SC_DRIVE,BYTE ; DOS 4.00 drive ;AN000;
71 i_need ACT_PAGE,WORD ; DOS 4.00 active logical EMS page ;AN000;
72 i_need DOS34_FLAG,WORD ; DOS 4.00 common flag ;AN000;
73 i_need BUF_EMS_SEG_CNT,WORD ; DOS 4.00 EMS seg count ;AN000;
74 i_need BUF_EMS_MAP_BUFF,BYTE ; DOS 4.00 EMS map buffer ;AN000;
75 i_need FIRST_BUFF_ADDR,WORD ; DOS 4.00 beginning of the chain ;AN000;
76 i_need BUF_EMS_PAGE_FRAME,WORD ; DOS 4.00 EMS page frame ;AN000;
77
78IF BUFFERFLAG
79 i_need BUF_EMS_PFRAME,WORD
80 i_need BUF_EMS_LAST_PAGE,WORD
81 i_need BUF_EMS_FIRST_PAGE,WORD
82 i_need BUF_EMS_SAFE_FLAG,byte
83 i_need BUF_EMS_NPA640,WORD
84 i_need NEXTADD,WORD
85 i_need DMAADD,DWORD
86 i_need BYTCNT1,WORD
87 i_am BUF_EMS_MAP_BUF,12,<0,0,0,0,0,0,0,0,0,0,0,0>
88 i_am CURADD,WORD
89 i_am low_ems_buf,512
90 extrn SAVE_USER_MAP:near
91 extrn RESTORE_USER_MAP:near
92ENDIF
93
94
95Break <GETCURHEAD -- Get current buffer header>
96
97; Inputs:
98; DX= sector number (LOW)
99; [HIGH_SECTOR]= sector number (HIGH)
100; Function:
101; Hash into a buffer group and activate the extended memory if
102; necessary
103; Outputs:
104; [CurHashEntry] = current Hash entry addr
105; DS:DI = 1st buffer addr of the current Hash entry
106; No other registers altered
107
108 procedure GETCURHEAD,NEAR
109 ASSUME DS:NOTHING,ES:NOTHING
110
111 PUSH DX ;LB. save regs ;AN000;
112 PUSH AX ;LB. ;AN000;
113 PUSH BX ;LB. ;AN000;
114 MOV AX,DX ;LB. ;AN000;
115; MOV DX,[HIGH_SECTOR] ;LB. HASH(sector#) and get entry # ;AN000;
116 XOR DX,DX ;LB. to avoid divide overflow ;AN000;
117 DIV [BUF_HASH_COUNT] ;LB. get remainder ;AN000;
118 ADD DX,DX ;LB. 8 bytes per entry ;AN000;
119 ADD DX,DX ;LB. ;AN000;
120 ADD DX,DX ;LB. times 8 ;AN000;
121
122 LDS DI,[BUF_HASH_PTR] ;LB. get Hash Table addr ;AN000;
123 ADD DI,DX ;LB position to entry ;AN000;
124Map_Entry2:
125 MOV WORD PTR [CurHashEntry+2],DS ;LB. update current Hash entry ptr ;AN000;
126 MOV WORD PTR [CurHashEntry],DI ;LB. ;AN000;
127 MOV WORD PTR [LASTBUFFER],-1 ;LB. invalidate last buffer ;AN000;
128 MOV BX,[DI.EMS_PAGE_NUM] ;LB. logical page ;AN000;
129
130IF NOT BUFFERFLAG
131 LDS DI,[DI.BUFFER_BUCKET] ;LB. ds:di is 1st buffer addr ;AN000;
132 MOV [FIRST_BUFF_ADDR],DI ;LB. 1/19/88 save first buffer addr ;AN000;
133 CALL SET_MAP_PAGE ;LB. activate handle if EMS there ;AN000;
134ELSE
135 push ax
136 mov ax, [NEXTADD]
137 mov [CURADD], ax
138 pop ax
139 CALL SET_MAP_PAGE ;LB. activate handle if EMS there ;AN000;
140 LDS DI,[DI.BUFFER_BUCKET] ;LB. ds:di is 1st buffer addr ;AN000;
141 MOV [FIRST_BUFF_ADDR],DI ;LB. 1/19/88 save first buffer addr ;AN000;
142ENDIF
143
144 ;AN000;
145 POP BX ;LB. ;AN000;
146 POP AX ;LB. ;AN000;
147 POP DX ;LB. ;AN000;
148 return ;LB. ;AN000;
149EndProc GETCURHEAD ;AN000;
150
151 ;AN000;
152Break <SET_MAP_PAGE - map handle and page > ;AN000;
153; Inputs: ;AN000;
154; BX= logical page ;AN000;
155; Function: ;AN000;
156; Map handle and logical page to frame 0 page 0 ;AN000;
157; Outputs: ;AN000;
158; AH=0 success ;AN000;
159; No other registers altered ;AN000;
160 ;AN000;
161Procedure SET_MAP_PAGE,NEAR ;AN000;
162 ASSUME DS:NOTHING,ES:NOTHING ;AN000;
163
164; int 3
165 ;AN000;
166 CMP [BUF_EMS_MODE],-1 ;LB. EMS support ;AN000;
167 JZ No_map ;LB. no ;AN000;
168
169IF NOT BUFFERFLAG
170 CMP [ACT_PAGE],BX ;LB. already mapped ? ;AN000;
171 JZ No_map ;LB. yes ;AN000;
172ENDIF
173 MOV [ACT_PAGE],BX ;LB. save active page mapped ;AN000;
174
175IF BUFFERFLAG
176 cmp [BUF_EMS_SAFE_FLAG], 1
177 je no_coll
178; int 3
179 call detect_collision
180no_coll:
181ENDIF
182
183 MOV DX,[BUF_EMS_HANDLE] ;LB. ;AN000;
184 MOV AH,44H ;LB. activate current handle ;AN000;
185 MOV AL,BYTE PTR [BUF_EMS_PAGE_FRAME] ;LB. page frame number ;AN000;
186 INT 67H ;LB. ;AN000;
187No_map: ;AN000;
188 return ;AN000;
189EndProc SET_MAP_PAGE ;AN000;
190 ;AN000;
191
192IF BUFFERFLAG
193
194Break <SAVE_MAP - save map > ;AN000;
195; Inputs: ;AN000;
196; none ;AN000;
197; Function: ;AN000;
198; save map ;AN000;
199; Outputs: ;AN000;
200; none ;AN000;
201; No other registers altered ;AN000;
202 ;AN000;
203Procedure SAVE_MAP,NEAR ;AN000;
204 ASSUME DS:NOTHING,ES:NOTHING ;AN000;
205 ;AN000;
206 CMP [BUF_EMS_MODE],-1 ;LB. EMS support ;AN000;
207 JZ No_save ;LB. no ;AN000;
208 MOV [ACT_PAGE],-1 ;LB. invalidate active page ;AN000;
209 MOV WORD PTR [LASTBUFFER],-1 ;LB. and last buffer pointer ;AN000;
210 PUSH AX ;LB. save regs ;AN000;
211 PUSH DS ;LB. save regs ;AN000;
212 PUSH ES ;LB. ;AN000;
213 PUSH SI ;LB. ;AN000;
214 PUSH DI ;LB. ;AN000;
215 MOV SI,OFFSET DOSGROUP:BUF_EMS_SEG_CNT ;LB. ;AN000;
216 MOV DI,OFFSET DOSGROUP:BUF_EMS_MAP_BUF ;LB. ;AN000;
217
218 PUSH CS
219 POP ES
220 PUSH CS ;LB. ;AN000;
221 POP DS ;LB. ds:si -> ems seg count ;AN000;
222
223 MOV AX,4F00H ;LB. save map ;AN000;
224 EnterCrit critDisk ;LB. enter critical section ;AN000;
225 INT 67H ;LB. ;AN000;
226 LeaveCrit critDisk ;LB. leave critical section ;AN000;
227 POP DI ;LB. ;AN000;
228 POP SI ;LB. restore regs ;AN000;
229 POP ES ;LB. ;AN000;
230 POP DS ;LB. ;AN000;
231 POP AX ;LB. restore ;AN000;
232No_save: ;AN000;
233 return ;AN000;
234EndProc SAVE_MAP ;AN000;
235 ;AN000;
236
237Break <RESTORE_MAP- retore map > ;AN000;
238; Inputs: ;AN000;
239; none ;AN000;
240; Function: ;AN000;
241; restore_map ;AN000;
242; Outputs: ;AN000;
243; none ;AN000;
244; No other registers altered ;AN000;
245 ;AN000;
246Procedure RESTORE_MAP,NEAR ;AN000;
247 ASSUME DS:NOTHING,ES:NOTHING ;AN000;
248 ;AN000;
249 CMP [BUF_EMS_MODE],-1 ;LB. EMS support ;AN000;
250 JZ No_restore ;LB. no ;AN000;
251 PUSH AX ;LB. save regs ;AN000;
252 PUSH DS ;LB. save regs ;AN000;
253 PUSH SI ;LB. ;AN000;
254 MOV SI,OFFSET DOSGROUP:BUF_EMS_MAP_BUF ;LB. ;AN000;
255
256 PUSH CS
257 POP DS
258 MOV AX,4F01H ;LB. restore map ;AN000;
259 EnterCrit critDisk ;LB. enter critical section ;AN000;
260 INT 67H ;LB. ;AN000;
261 LeaveCrit critDisk ;LB. leave critical section ;AN000;
262 POP SI ;LB. restore regs ;AN000;
263 POP DS ;LB. ;AN000;
264 POP AX ;LB. ;AN000;
265No_restore: ;AN000;
266 return ;AN000;
267EndProc RESTORE_MAP ;AN000;
268
269ENDIF
270 ;AN000;
271 ;AN000;
272
273Break <SCANPLACE, PLACEBUF -- PUT A BUFFER BACK IN THE POOL>
274
275; Inputs:
276; Same as PLACEBUF
277; Function:
278; Save scan location and call PLACEBUF
279; Outputs:
280; DS:DI Points to saved scan location
281; SI destroyed, other registers unchanged
282
283 procedure ScanPlace,near
284ASSUME DS:NOTHING,ES:NOTHING
285
286;; PUSH ES
287;; LES SI,[DI.buf_link] ; Save scan location
288 MOV SI,[DI.buf_next] ; Save scan location
289 CALL PLACEBUF
290;; PUSH ES
291;; POP DS ; Restore scan location
292 MOV DI,SI
293;; POP ES
294 return
295EndProc ScanPlace
296
297; Rewritten PLACEBUF (LKR), eliminates loops
298;
299; Input:
300; DS:DI points to buffer (DS->BUFFINFO array, DI=offset in array)
301; Function:
302; Remove buffer from queue and re-insert it in proper place.
303; NO registers altered
304
305 procedure PLACEBUF,NEAR
306ASSUME DS:NOTHING,ES:NOTHING
307
308; invoke save_world
309 push AX ;Save only regs we modify ;AN000;
310 push BX ;AN000;
311 push SI ;AN000;
312 push ES ;AN000;
313
314 les SI,[CurHashEntry] ;ES:SI -> Current Hash entry ;AN000;
315 mov BX,word ptr ES:[SI.BUFFER_BUCKET] ;BX = offset of head of list ;AN000;
316
317 cmp [DI.buf_next],BX ;Buf = last? ;AN000;
318 je nret ;Yes, special case ;AN000;
319 cmp DI,BX ;Buf = first? ;AN000;
320 je bufloop ;Yes, special case ;AN000;
321 mov SI,[DI.buf_prev] ;No, SI = prior Buf ;AN000;
322 mov AX,[DI.buf_next] ;Now delete Buf from list ;AN000;
323 mov [SI.buf_next],AX ;AN000;
324 push SI ;Save si ;AN000;
325 mov SI,[DI.buf_next] ;Update backward pointer ;AN000;
326 mov AX,[DI.buf_prev] ; ;AN000;
327 mov [SI.buf_prev],AX ; ;AN000;
328 pop si ;Restore si ;AN000;
329lookend: ;(label is now a misnomer) ;AN000;
330 mov SI,[BX.buf_prev] ;SI-> last buffer ;AN000;
331 mov [SI.buf_next],DI ;Add Buf to end of list ;AN000;
332 mov [BX.buf_prev],DI ;AN000;
333 mov [DI.buf_prev],SI ;Update linkage in Buf too ;AN000;
334 mov [DI.buf_next],BX ;AN000;
335nret: ;AN000;
336 ;AN000;
337; invoke restore_world ;AN000;
338 pop ES ;Restore regs we modified ;AN000;
339 pop SI ;AN000;
340 pop BX ;AN000;
341 pop AX ;AN000;
342 ;AN000;
343 cmp [DI.buf_ID],-1 ; Buffer FREE? ;AN000;
344 retnz ; No ;AN000;
345 invoke PLACEHEAD ; Buffer is free, belongs at hea;AN000;
346 return ;AN000;
347bufloop: ;(label is now a misnomer) ;AN000;
348 mov BX,[DI.buf_next] ;Set new head position ;AN000;
349 mov word ptr ES:[SI.BUFFER_BUCKET],BX ;AN000;
350 jmp nret ;Continue with repositioning ;AN000;
351
352EndProc PLACEBUF
353
354; SAME AS PLACEBUF except places buffer at head
355; NOTE:::::: ASSUMES THAT BUFFER IS CURRENTLY THE LAST
356; ONE IN THE LIST!!!!!!!
357; Rewritten PLACEBUF, takes buffer from end of list to head of list
358
359 procedure PLACEHEAD,NEAR ;AN000;
360ASSUME DS:NOTHING,ES:NOTHING ;AN000;
361 push ES ;AN000;
362 push SI ;AN000;
363 les SI,[CurHashEntry] ;AN000;
364 mov word ptr ES:[SI.BUFFER_BUCKET],DI ;AN000;
365 pop SI ;AN000;
366 pop ES ;AN000;
367 return ;AN000;
368EndProc PLACEHEAD ;AN000;
369
370
371Break <POINTCOMP -- 20 BIT POINTER COMPARE>
372
373; Compare DS:SI to ES:DI (or DS:DI to ES:SI) for equality
374; DO NOT USE FOR < or >
375; No Registers altered
376
377 procedure PointComp,NEAR
378ASSUME DS:NOTHING,ES:NOTHING
379
380 CMP SI,DI
381 retnz
382 PUSH CX
383 PUSH DX
384 MOV CX,DS
385 MOV DX,ES
386 CMP CX,DX
387 POP DX
388 POP CX
389 return
390EndProc PointComp
391
392Break <GETBUFFR -- GET A SECTOR INTO A BUFFER>
393
394; Input:
395; AL = 0 means sector must be pre-read
396; ELSE no pre-read
397; DX = Desired physical sector number (LOW)
398; [HIGH_SECTOR]= Desired physical sector number (HIGH)
399; ES:BP = Pointer to drive parameters
400; [ALLOWED] set in case of INT 24
401; Function:
402; Get the specified local sector into one of the I/O buffers
403; And shuffle the queue
404; Output:
405; [CURBUF] Points to the Buffer for the sector
406; THE BUFFER TYPE FIELD OF buf_flags = 0, caller must set it
407; Carry set if error (currently user FAILed to INT 24)
408; DS,DX,ES:BP unchanged, all other registers destroyed
409
410 procedure GETBUFFR,NEAR
411 DOSAssume CS,<DS>,"GetBuffr"
412 ASSUME ES:NOTHING
413
414 XOR SI,SI
415
416 entry GETBUFFRB
417
418 Assert ISDPB,<ES,BP>,"GetBuffr"
419 MOV [PREREAD],AX
420 MOV AL,ES:[BP.dpb_drive]
421 LDS DI,[LASTBUFFER]
422ASSUME DS:NOTHING
423 MOV CX,[HIGH_SECTOR] ; F.C. >32mb ;AN000;
424 CMP DI,-1 ; Recency pointer valid?
425 JZ SKBUF ; No
426
427 CMP DX,WORD PTR [DI.buf_sector]
428 JNZ SKBUF ; Wrong sector
429 CMP CX,WORD PTR [DI.buf_sector+2] ; F.C. >32mb ;AN000;
430 JNZ SKBUF ; F.C. >32mb ;AN000;
431 CMP AL,[DI.buf_ID]
432 JNZ SKBUF ; Wrong Drive
433
434 JMP JUSTBUF ; Just asked for same buffer
435SKBUF:
436 CALL GETCURHEAD ;LB. get cuurent Hash entry ;AN000;
437; LDS DI,[BUFFHEAD]
438NXTBFF:
439 CMP DX,WORD PTR [DI.buf_sector] ; F.C. >32mb ;AN000;
440 JNZ BUMP
441 CMP CX,WORD PTR [DI.buf_sector+2] ; F.C. >32mb ;AN000;
442 JNZ BUMP ; F.C. >32mb ;AN000;
443 CMP AL,[DI.buf_ID]
444if not bufferflag
445 JZ SETINF
446else
447 jnz bump
448 jmp setinf
449endif
450BUMP:
451 mov DI,[DI.buf_next] ;;;;;;1/19/88 ;AN000;
452 cmp DI,[FIRST_BUFF_ADDR] ;;;;;;1/19/88 ;AN000;
453 JNZ NXTBFF
454;;;; LDS DI,[CurHashEntry] ;LB. secondary cache's use ;AN000;
455;;;; LDS DI,[DI.BUFFER_BUCKET] ;LB. ;AN000;
456 ; LDS DI,[BUFFHEAD]
457 PUSH [HIGH_SECTOR] ;F.C. >32mb ;AN000;
458 PUSH SI
459 PUSH DX
460 PUSH BP
461 PUSH ES
462 CALL BUFWRITE ; Write out the dirty buffer
463 POP ES
464 POP BP
465 POP DX
466 POP SI
467 POP [HIGH_SECTOR] ;F.C. >32mb ;AN000;
468if not bufferflag
469 JC GETBERR
470else
471 jnc skip_getberr
472 jmp getberr
473skip_getberr:
474endif
475 CALL SET_RQ_SC_PARMS ;LB. set parms ;AN000;
476 XOR AH,AH ; initial flags
477 TEST BYTE PTR [PREREAD],-1 ; Read in the new sector
478 JNZ SETBUF
479 LEA BX,[DI.BufInSiz] ; Point at buffer
480 MOV CX,1
481 PUSH SI
482 PUSH DI
483 PUSH DX
484; Note: As far as I can tell, all disk reads into buffers go through this point. -mrw 10/88
485if bufferflag
486; int 3
487 cmp [buf_ems_mode], -1
488 jz normread
489 push bx
490 push ds ; save ds:bx --> ems_buffer
491 push cs
492 pop ds
493 mov bx, offset dosgroup:low_ems_buf ; ds:bx --> low_ems_buffer
494normread:
495endif
496 OR SI,SI
497 JZ NORMSEC
498 invoke FATSECRD
499 MOV AH,buf_isFAT ; Set buf_flags
500 JMP SHORT GOTTHESEC ; Buffer is marked free if read barfs
501NORMSEC:
502 invoke DREAD ; Buffer is marked free if read barfs
503 MOV AH,0 ; Set buf_flags to no type, DO NOT XOR!
504GOTTHESEC: ; Carry set by either FATSECRD or DREAD
505if bufferflag
506 pushf
507 jc skipreadtrans
508 cmp [buf_ems_mode], -1
509 je skipreadtrans
510
511 popf
512 pop ds
513 pop bx ; restore ems_buffer pointer
514 pushf
515
516 push cx ; save regs to be used by rep mov
517 push ds
518 push es
519
520 mov di, bx
521 push ds
522 pop es ; es:di --> ems_buf
523 mov si, offset dosgroup:low_ems_buf
524 push cs
525 pop ds ; ds:si --> low_ems_buf
526 mov cx, 512/2
527 rep movsw
528
529 pop es ; restore regs.
530 pop ds
531 pop cx
532skipreadtrans:
533 popf
534endif
535 POP DX
536 POP DI
537 POP SI
538 JC GETBERR
539SETBUF:
540 MOV CX,[HIGH_SECTOR] ; F.C. >32mb ;AN000;
541 MOV WORD PTR [DI.buf_sector+2],CX ; F.C. >32mb ;AN000;
542 MOV WORD PTR [DI.buf_sector],DX ; F.C. >32mb ;AN000;
543 MOV WORD PTR [DI.buf_DPB],BP
544 MOV WORD PTR [DI.buf_DPB+2],ES
545 MOV AL,ES:[BP.dpb_drive]
546 MOV WORD PTR [DI.buf_ID],AX ; Sets buf_flags too, to AH
547SETINF:
548 MOV [DI.buf_wrtcnt],1 ; Default to not a FAT sector ;AC000;
549 XOR AX,AX ;>32mb ;AN000;
550 OR SI,SI
551 JZ SETSTUFFOK
552 MOV AL,ES:[BP.dpb_FAT_count]
553 MOV [DI.buf_wrtcnt],AL ;>32mb ;AN000;
554 MOV AX,ES:[BP.dpb_FAT_size]
555SETSTUFFOK:
556 MOV [DI.buf_wrtcntinc],AX ;>32mb ;AC000;
557 CALL PLACEBUF
558JUSTBUF:
559 MOV WORD PTR [CURBUF+2],DS
560 MOV WORD PTR [LASTBUFFER+2],DS
561 MOV WORD PTR [CURBUF],DI
562 MOV WORD PTR [LASTBUFFER],DI
563 CLC
564GETBERR:
565 Context DS
566 return
567EndProc GETBUFFR
568
569Break <FLUSHBUF -- WRITE OUT DIRTY BUFFERS>
570
571; Input:
572; DS = DOSGROUP
573; AL = Physical unit number local buffers only
574; = -1 for all units and all remote buffers
575; Function:
576; Write out all dirty buffers for unit, and flag them as clean
577; Carry set if error (user FAILed to I 24)
578; Flush operation completed.
579; DS Preserved, all others destroyed (ES too)
580
581 procedure FlushBuf,NEAR
582 DOSAssume CS,<DS>,"FlushBuf"
583 ASSUME ES:NOTHING
584
585 MOV AH,-1
586; LDS DI,[BUFFHEAD]
587ASSUME DS:NOTHING
588
589 LDS DI,[BUF_HASH_PTR] ;LB. get Hash Table addr ;AN000;
590 MOV CX,[BUF_HASH_COUNT] ;LB. get Hash entry count ;AN000;
591 XOR DX,DX ;LB. set initial index to 0 ;AN000;
592
593NXTBUFF2:
594 PUSH CX ;LB. save Hash entry count ;AN000;
595 TEST [DOS34_FLAG],FROM_DISK_RESET ;MS. from disk reset ;AN004;
596 JNZ Zapzap ;MS. yes ;AN004;
597 CMP [DI.Dirty_Count],0 ;LB. dirty entry ? ;AN000;
598 JZ getnext ;LB. no ;AN000;
599Zapzap: ;AN004;
600 PUSH DS ;LB. save regs ;AN000;
601 PUSH DI ;LB. ;AN000;
602 invoke Map_Entry ;LB. ds:di -> first buffer addr ;AN000;
603NXTBUFF:
604 CALL CHECKFLUSH ; Ignore Carry return from CHECKFLUSH.
605 ; FAILERR is set if user FAILed.
606 PUSH AX
607 MOV AL,[DI.buf_ID]
608 CMP AL,BYTE PTR [WPERR]
609 JZ ZAP
610 TEST [DOS34_FLAG],FROM_DISK_RESET ;MS. from disk reset ;AN000;
611 JNZ Zap ;MS. yes ;AN000;
612
613NOZAP:
614 POP AX
615 mov DI,[DI.buf_next] ;;;;1/19/88 ;AN000;
616 CMP DI,[FIRST_BUFF_ADDR] ;;;;1/19/88 ;AN000;
617 JNZ NXTBUFF
618
619 POP DI ;LB. ;AN000;
620 POP DS ;LB. ;AN000;
621getnext:
622 ADD DI,size BUFFER_HASH_ENTRY ;LB. position to next entry ;AN000;
623 POP CX ;LB. restore entry count ;AN000;
624 LOOP NXTBUFF2 ;LB. get next entry buffer ;AN000;
625 Context DS
626 CMP [FAILERR],0
627 JNZ FLSHBad ; Carry clear if JMP
628 return
629FlshBad:
630 STC ; Return error if user FAILed
631 return
632Zap:
633 MOV WORD PTR [DI.buf_ID],00FFH ; Invalidate buffer, it is inconsistent
634 JMP NoZap
635
636EndProc FlushBuf
637
638 procedure CHECKFLUSH,NEAR
639ASSUME DS:NOTHING,ES:NOTHING
640; Carry set if problem (currently user FAILed to I 24)
641
642 Assert ISBUF,<DS,DI>,"CheckFlush"
643 CMP [DI.buf_ID],AH
644 retz ; Skip free buffers, carry clear
645 CMP AH,AL
646 JZ DOBUFFER ; Do all dirty buffers
647 CMP AL,[DI.buf_ID]
648 CLC
649 retnz ; Buffer not for this unit or SFT
650DOBUFFER:
651 TEST [DI.buf_flags],buf_dirty
652 retz ; Buffer not dirty, carry clear by TEST
653 PUSH AX
654 PUSH WORD PTR [DI.buf_ID]
655 CALL BUFWRITE
656 POP AX
657 JC LEAVE_BUF ; Leave buffer marked free (lost).
658 AND AH,NOT buf_dirty ; Buffer is clean, clears carry
659 MOV WORD PTR [DI.buf_ID],AX
660LEAVE_BUF:
661 POP AX ; Search info
662 return
663EndProc CHECKFLUSH
664
665Break <BUFWRITE -- WRITE OUT A BUFFER IF DIRTY>
666
667; Input:
668; DS:DI Points to the buffer
669; Function:
670; Write out all the buffer if dirty.
671; Output:
672; Buffer marked free
673; Carry set if error (currently user FAILed to I 24)
674; DS:DI Preserved, ALL others destroyed (ES too)
675
676 procedure BufWrite,NEAR
677ASSUME DS:NOTHING,ES:NOTHING
678
679 Assert ISBUF,<DS,DI>,"BufWrite"
680 MOV AX,00FFH
681 XCHG AX,WORD PTR [DI.buf_ID] ; Free, in case write barfs
682 CMP AL,0FFH
683 retz ; Buffer is free, carry clear.
684 TEST AH,buf_dirty
685 retz ; Buffer is clean, carry clear.
686 invoke DEC_DIRTY_COUNT ; LB. decrement dirty count
687 CMP AL,BYTE PTR [WPERR]
688 retz ; If in WP error zap buffer
689 MOV [SC_DRIVE],AL ;LB. set it for invalidation ;AN000;
690 LES BP,[DI.buf_DPB]
691 LEA BX,[DI.BufInSiz] ; Point at buffer
692 MOV DX,WORD PTR [DI.buf_sector] ;F.C. >32mb ;AN000;
693 MOV CX,WORD PTR [DI.buf_sector+2] ;F.C. >32mb ;AN000;
694 MOV [HIGH_SECTOR],CX ;F.C. >32mb ;AN000;
695 MOV CL,[DI.buf_wrtcnt] ;>32mb ;AC000;
696; MOV AL,CH ; [DI.buf_wrtcntinc]
697 XOR CH,CH
698 MOV AX,[DI.buf_wrtcntinc] ;>32mb ;AC000;
699 MOV [ALLOWED],allowed_RETRY + allowed_FAIL
700 TEST [DI.buf_flags],buf_isDATA
701 JZ NO_IGNORE
702 OR [ALLOWED],allowed_IGNORE
703NO_IGNORE:
704 PUSH DI ; Save buffer pointer
705 XOR DI,DI ; Indicate failure
706WRTAGAIN:
707 SaveReg <DI,CX,AX>
708 MOV CX,1
709 SaveReg <BX,DX,DS>
710; Note: As far as I can tell, all disk reads into buffers go through this point. -mrw 10/88
711
712if bufferflag
713; int 3
714 cmp [buf_ems_mode], -1
715 jz skipwritetrans
716
717 push es
718 push di
719 push si
720 push cx
721
722 mov si, bx ; ds:si --> ems_buffer
723 mov di, offset dosgroup:low_ems_buf
724 push cs
725 pop es ; es:di --> low_ems_buffer
726 mov cx, 512/2
727 rep movsw
728
729 pop cx
730 pop si
731 pop di
732 pop es
733
734 push ds
735 push bx
736 mov bx, offset dosgroup:low_ems_buf
737 push cs
738 pop ds ; ds:bx --> low_ems_buffer
739skipwritetrans:
740endif
741
742 invoke DWRITE ; Write out the dirty buffer
743
744if bufferflag
745 pushf ; save carry flag from DWRITE
746 cmp [buf_ems_mode], -1
747 jz normwrite
748 popf ; need to get at stack
749 pop bx ; ds:bx --> ems_buffer
750 pop ds
751 pushf ; put it back, so we can pop it
752normwrite:
753 popf ; restore carry flag
754endif
755
756 RestoreReg <DS,DX,BX>
757 RestoreReg <AX,CX,DI>
758 JC NOSET
759 INC DI ; If at least ONE write succeedes, the operation
760NOSET: ; succeedes.
761 ADD DX,AX
762 LOOP WRTAGAIN
763 OR DI,DI ; Clears carry
764 JNZ BWROK ; At least one write worked
765 STC ; DI never got INCed, all writes failed.
766BWROK:
767 POP DI
768 return
769EndProc BufWrite
770
771Break <SET_RQ_SC_PARMS-set requesting drive for SC>
772
773; Input:
774; ES:BP = drive parameter block
775; Function:
776; Set requesting drive, and sector size
777; Output:
778; [SC_SECTOR_SIZE]= drive sector size
779; [SC_DRIVE]= drive #
780;
781; All registers preserved
782
783 procedure SET_RQ_SC_PARMS,NEAR
784ASSUME DS:NOTHING,ES:NOTHING
785
786 CMP [SC_CACHE_COUNT],0 ;LB. do it only secondary cache exists ;AN000;
787 JZ nosec ;LB. ;AN000;
788 PUSH DX ;LB. save dx ;AN000;
789 MOV DX,ES:[BP.dpb_sector_size] ;LB. save sector size ;AN000;
790 MOV [SC_SECTOR_SIZE],DX ;LB. ;AN000;
791 MOV DL,ES:[BP.dpb_drive] ;LB. save drive # ;AN000;
792 MOV [SC_DRIVE],DL ;LB. ;AN000;
793 ;AN000;
794 POP DX ;LB. restore dx ;AN000;
795
796nosec:
797 return
798EndProc SET_RQ_SC_PARMS ;LB. return ;AN000;
799
800Break <INC_DIRTY_COUNT-increment dirty count>
801
802; Input:
803; none
804; Function:
805; increment dirty buffers count
806; Output:
807; dirty buffers count in the current hash entry is incremented
808;
809; All registers preserved
810
811 procedure INC_DIRTY_COUNT,NEAR
812ASSUME DS:NOTHING,ES:NOTHING
813
814 PUSH DS ;LB. save regs ;AN000;
815 PUSH SI ;LB. ;AN000;
816 LDS SI,[CurHashEntry] ;LB. get current hash entry ;AN000;
817 INC [SI.Dirty_Count] ;LB. add 1 ;AN000;
818 POP SI ;LB. restore regs ;AN000;
819 POP DS ;LB. ;AN000;
820 return
821EndProc INC_DIRTY_COUNT ;LB. return ;AN000;
822
823Break <DEC_DIRTY_COUNT-decrement dirty count>
824
825; Input:
826; none
827; Function:
828; decrement dirty buffers count
829; Output:
830; dirty buffers count in the current hash entry is decremented
831;
832; All registers preserved
833
834 procedure DEC_DIRTY_COUNT,NEAR
835ASSUME DS:NOTHING,ES:NOTHING
836
837 PUSH DS ;LB. save regs ;AN000;
838 PUSH SI ;LB. ;AN000;
839 LDS SI,[CurHashEntry] ;LB. get current hash entry ;AN000;
840 CMP [SI.Dirty_Count],0 ;LB. in case if 0 ;AN000;
841 JZ nodec ;LB. do nothing ;AN000;
842 DEC [SI.Dirty_Count] ;LB. sub 1 ;AN000;
843nodec:
844 POP SI ;LB. restore regs ;AN000;
845 POP DS ;LB. ;AN000;
846 return
847EndProc DEC_DIRTY_COUNT ;LB. return ;AN000;
848
849
850Break <MAP_ENTRY- map the buffers of this entry>
851
852; Input:
853; DS:DI ponits to hash entry
854; Function:
855; map the buferrs of this entry
856; Output:
857; the buffers are mapped
858;
859; All registers preserved
860
861 procedure Map_Entry,NEAR
862ASSUME DS:NOTHING,ES:NOTHING
863
864 PUSH DX ;LB. save regs ;AN000;
865 PUSH AX ;LB. ;AN000;
866 PUSH BX ;LB. ;AN000;
867 JMP Map_Entry2 ;LB. ;AN000;
868EndProc Map_Entry ;LB. ;AN000;
869
870
871IF BUFFERFLAG
872
873;-------------------------------------------------------------------------
874; Procedure name : detect collision
875; Inputs : [DMAADD] - user Xaddr
876; [CURADD] - current offset
877; [BYTCNT1] - for partial sector read
878; SAFE_FLAG - cleared - indicating that the
879; current page is unsafe.
880;
881; Outputs : es - physical page segment to use
882; di - corresponding page number
883; SAFE_FLAG is set is a collision is detected
884; and the current page is switched form
885; LAST_PAGE to FIRST_PAGE.
886;---------------------------------------------------------------------------
887;
888
889Procedure detect_collision, near
890ASSUME DS:NOTHING,ES:NOTHING
891
892 push ax
893 push bx
894 push cx
895
896 cmp [BUF_EMS_MODE], -1
897 jz fin_detect_coll
898
899 mov ax, [CURADD] ; current offset
900
901 cmp [BYTCNT1], 0
902 je no_partial_sector
903 add ax, [BYTCNT1]
904
905no_partial_sector:
906 mov cl, 4
907 shr ax, cl ; convert to paragraphs
908 mov bx, word ptr [DMAADD+2] ; get original segment
909 add ax, bx ; get current segment
910
911 and ax, 0fc00h ; get ems page of current segment
912 cmp ax, [BUF_EMS_LAST_PAGE] ; is the current segment = last segment
913 jne fin_detect_coll ; page is still safe
914
915; int 3
916 push ax
917 mov ax, word ptr [DMAADD]
918 mov ax, [NEXTADD]
919 mov ax, [CURADD]
920 mov ax, [BYTCNT1]
921 pop ax
922
923 call restore_user_map
924 mov word ptr [LASTBUFFER], -1
925 mov ax, [BUF_EMS_FIRST_PAGE]
926 mov [BUF_EMS_PFRAME], ax
927 mov ax, [BUF_EMS_FIRST_PAGE+2]
928 mov [BUF_EMS_PAGE_FRAME], ax
929 mov [BUF_EMS_SAFE_FLAG], 1
930 call Setup_EMS_buffers
931 call save_user_map
932
933fin_detect_coll:
934 pop cx
935 pop bx
936 pop ax
937 ret
938
939EndProc detect_collision
940
941Procedure Setup_EMS_Buffers,Near
942 ASSUME DS:NOTHING,ES:NOTHING ;AN000;
943
944 cmp [BUF_EMS_MODE], -1
945 jz setup_ems_ret
946
947 push bx
948 push cx
949 push ax
950 push ds
951 push di
952
953 mov bx, [BUF_HASH_COUNT] ; # of hash table entries
954 lds di, [BUF_HASH_PTR] ; ds:di -> hash table
955
956 xor cx, cx
957
958next_bucket:
959 mov ax, [BUF_EMS_PFRAME]
960 mov word ptr ds:[di.BUFFER_BUCKET+2], ax
961 add di, 8 ; next has entry.
962 inc cx
963 cmp cx, bx
964 jne next_bucket
965
966 pop di
967 pop ds
968 pop ax
969 pop cx
970 pop bx
971
972setup_ems_ret:
973 ret
974
975EndProc Setup_EMS_Buffers
976
977ENDIF
978
979
980CODE ENDS
981 END
982 \ No newline at end of file