1 ; SCCSID = @(#)buf.asm 1.1 85/04/09
2 TITLE BUF
- MSDOS buffer management
4 ; Low level routines for buffer cache management
24 ; AN000 version 4.00 Jan. 1988
25 ; A004 PTM 3765 -- Disk reset failed
27 ; NEW PROCS FOR BUFFERS FIX:
37 ; get the appropriate segment definitions
42 CODE SEGMENT BYTE PUBLIC 'CODE'
43 ASSUME
SS:DOSGROUP
,CS:DOSGROUP
56 i_need LastBuffer
,DWORD
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;
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
87 i_am BUF_EMS_MAP_BUF
,12,<0,0,0,0,0,0,0,0,0,0,0,0>
90 extrn SAVE_USER_MAP
:near
91 extrn RESTORE_USER_MAP
:near
95 Break <GETCURHEAD
-- Get current buffer header
>
98 ; DX= sector number (LOW)
99 ; [HIGH_SECTOR]= sector number (HIGH)
101 ; Hash into a buffer group and activate the extended memory if
104 ; [CurHashEntry] = current Hash entry addr
105 ; DS:DI = 1st buffer addr of the current Hash entry
106 ; No other registers altered
108 procedure GETCURHEAD
,NEAR
109 ASSUME
DS:NOTHING
,ES:NOTHING
111 PUSH DX ;LB. save regs ;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;
122 LDS DI,[BUF_HASH_PTR
] ;LB. get Hash Table addr ;AN000;
123 ADD DI,DX ;LB position to entry ;AN000;
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;
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;
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;
149 EndProc GETCURHEAD
;AN000;
152 Break <SET_MAP_PAGE
- map handle
and page
> ;AN000;
154 ; BX= logical page ;AN000;
156 ; Map handle and logical page to frame 0 page 0 ;AN000;
158 ; AH=0 success ;AN000;
159 ; No other registers altered ;AN000;
161 Procedure SET_MAP_PAGE
,NEAR ;AN000;
162 ASSUME
DS:NOTHING
,ES:NOTHING
;AN000;
166 CMP [BUF_EMS_MODE
],-1 ;LB. EMS support ;AN000;
167 JZ No_map
;LB. no ;AN000;
170 CMP [ACT_PAGE
],BX ;LB. already mapped ? ;AN000;
171 JZ No_map
;LB. yes ;AN000;
173 MOV [ACT_PAGE
],BX ;LB. save active page mapped ;AN000;
176 cmp [BUF_EMS_SAFE_FLAG
], 1
179 call detect_collision
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;
189 EndProc SET_MAP_PAGE
;AN000;
194 Break <SAVE_MAP
- save map
> ;AN000;
201 ; No other registers altered ;AN000;
203 Procedure SAVE_MAP
,NEAR ;AN000;
204 ASSUME
DS:NOTHING
,ES:NOTHING
;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;
215 MOV SI,OFFSET DOSGROUP
:BUF_EMS_SEG_CNT
;LB. ;AN000;
216 MOV DI,OFFSET DOSGROUP
:BUF_EMS_MAP_BUF
;LB. ;AN000;
221 POP DS ;LB. ds:si -> ems seg count ;AN000;
223 MOV AX,4F00H
;LB. save map ;AN000;
224 EnterCrit critDisk
;LB. enter critical section ;AN000;
226 LeaveCrit critDisk
;LB. leave critical section ;AN000;
228 POP SI ;LB. restore regs ;AN000;
231 POP AX ;LB. restore ;AN000;
234 EndProc SAVE_MAP
;AN000;
237 Break <RESTORE_MAP
- retore map
> ;AN000;
241 ; restore_map ;AN000;
244 ; No other registers altered ;AN000;
246 Procedure RESTORE_MAP
,NEAR ;AN000;
247 ASSUME
DS:NOTHING
,ES:NOTHING
;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;
254 MOV SI,OFFSET DOSGROUP
:BUF_EMS_MAP_BUF
;LB. ;AN000;
258 MOV AX,4F01H
;LB. restore map ;AN000;
259 EnterCrit critDisk
;LB. enter critical section ;AN000;
261 LeaveCrit critDisk
;LB. leave critical section ;AN000;
262 POP SI ;LB. restore regs ;AN000;
267 EndProc RESTORE_MAP
;AN000;
273 Break <SCANPLACE
, PLACEBUF
-- PUT A BUFFER BACK
IN THE POOL
>
278 ; Save scan location and call PLACEBUF
280 ; DS:DI Points to saved scan location
281 ; SI destroyed, other registers unchanged
283 procedure ScanPlace
,near
284 ASSUME
DS:NOTHING
,ES:NOTHING
287 ;; LES SI,[DI.buf_link] ; Save scan location
288 MOV SI,[DI.buf_next
] ; Save scan location
291 ;; POP DS ; Restore scan location
297 ; Rewritten PLACEBUF (LKR), eliminates loops
300 ; DS:DI points to buffer (DS->BUFFINFO array, DI=offset in array)
302 ; Remove buffer from queue and re-insert it in proper place.
303 ; NO registers altered
305 procedure PLACEBUF
,NEAR
306 ASSUME
DS:NOTHING
,ES:NOTHING
309 push AX ;Save only regs we modify ;AN000;
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;
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;
329 lookend: ;(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;
337 ; invoke restore_world ;AN000;
338 pop ES ;Restore regs we modified ;AN000;
343 cmp [DI.buf_ID
],-1 ; Buffer FREE? ;AN000;
345 invoke PLACEHEAD
; Buffer is free, belongs at hea;AN000;
347 bufloop: ;(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;
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
359 procedure PLACEHEAD
,NEAR ;AN000;
360 ASSUME
DS:NOTHING
,ES:NOTHING
;AN000;
363 les SI,[CurHashEntry
] ;AN000;
364 mov word ptr ES:[SI.BUFFER_BUCKET
],DI ;AN000;
368 EndProc PLACEHEAD
;AN000;
371 Break <POINTCOMP
-- 20 BIT POINTER COMPARE
>
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
377 procedure PointComp
,NEAR
378 ASSUME
DS:NOTHING
,ES:NOTHING
392 Break <GETBUFFR
-- GET A SECTOR
INTO A BUFFER
>
395 ; AL = 0 means sector must be 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
402 ; Get the specified local sector into one of the I/O buffers
403 ; And shuffle the queue
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
410 procedure GETBUFFR
,NEAR
411 DOSAssume
CS,<DS>,"GetBuffr"
418 Assert ISDPB
,<ES,BP>,"GetBuffr"
420 MOV AL,ES:[BP.dpb_drive
]
423 MOV CX,[HIGH_SECTOR
] ; F.C. >32mb ;AN000;
424 CMP DI,-1 ; Recency pointer valid?
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;
432 JNZ SKBUF
; Wrong Drive
434 JMP JUSTBUF
; Just asked for same buffer
436 CALL GETCURHEAD
;LB. get cuurent Hash entry ;AN000;
439 CMP DX,WORD PTR [DI.buf_sector
] ; F.C. >32mb ;AN000;
441 CMP CX,WORD PTR [DI.buf_sector
+2] ; F.C. >32mb ;AN000;
442 JNZ BUMP
; F.C. >32mb ;AN000;
451 mov DI,[DI.buf_next
] ;;;;;;1/19/88 ;AN000;
452 cmp DI,[FIRST_BUFF_ADDR
] ;;;;;;1/19/88 ;AN000;
454 ;;;; LDS DI,[CurHashEntry] ;LB. secondary cache's use ;AN000;
455 ;;;; LDS DI,[DI.BUFFER_BUCKET] ;LB. ;AN000;
457 PUSH [HIGH_SECTOR
] ;F.C. >32mb ;AN000;
462 CALL BUFWRITE
; Write out the dirty buffer
467 POP [HIGH_SECTOR
] ;F.C. >32mb ;AN000;
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
479 LEA BX,[DI.BufInSiz
] ; Point at buffer
484 ; Note: As far as I can tell, all disk reads into buffers go through this point. -mrw 10/88
487 cmp [buf_ems_mode
], -1
490 push ds ; save ds:bx --> ems_buffer
493 mov bx, offset dosgroup
:low_ems_buf
; ds:bx --> low_ems_buffer
499 MOV AH,buf_isFAT
; Set buf_flags
500 JMP SHORT GOTTHESEC
; Buffer is marked free if read barfs
502 invoke DREAD
; Buffer is marked free if read barfs
503 MOV AH,0 ; Set buf_flags to no type, DO NOT XOR!
504 GOTTHESEC: ; Carry set by either FATSECRD or DREAD
508 cmp [buf_ems_mode
], -1
513 pop bx ; restore ems_buffer pointer
516 push cx ; save regs to be used by rep mov
522 pop es ; es:di --> ems_buf
523 mov si, offset dosgroup
:low_ems_buf
525 pop ds ; ds:si --> low_ems_buf
529 pop es ; restore regs.
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
548 MOV [DI.buf_wrtcnt
],1 ; Default to not a FAT sector ;AC000;
549 XOR AX,AX ;>32mb ;AN000;
552 MOV AL,ES:[BP.dpb_FAT_count
]
553 MOV [DI.buf_wrtcnt
],AL ;>32mb ;AN000;
554 MOV AX,ES:[BP.dpb_FAT_size
]
556 MOV [DI.buf_wrtcntinc
],AX ;>32mb ;AC000;
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
569 Break <FLUSHBUF
-- WRITE
OUT DIRTY BUFFERS
>
573 ; AL = Physical unit number local buffers only
574 ; = -1 for all units and all remote buffers
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)
581 procedure FlushBuf
,NEAR
582 DOSAssume
CS,<DS>,"FlushBuf"
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;
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;
600 PUSH DS ;LB. save regs ;AN000;
602 invoke Map_Entry
;LB. ds:di -> first buffer addr ;AN000;
604 CALL CHECKFLUSH
; Ignore Carry return from CHECKFLUSH.
605 ; FAILERR is set if user FAILed.
608 CMP AL,BYTE PTR [WPERR
]
610 TEST [DOS34_FLAG
],FROM_DISK_RESET
;MS. from disk reset ;AN000;
611 JNZ Zap
;MS. yes ;AN000;
615 mov DI,[DI.buf_next
] ;;;;1/19/88 ;AN000;
616 CMP DI,[FIRST_BUFF_ADDR
] ;;;;1/19/88 ;AN000;
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;
627 JNZ FLSHBad
; Carry clear if JMP
630 STC ; Return error if user FAILed
633 MOV WORD PTR [DI.buf_ID
],00FFH ; Invalidate buffer, it is inconsistent
638 procedure CHECKFLUSH
,NEAR
639 ASSUME
DS:NOTHING
,ES:NOTHING
640 ; Carry set if problem (currently user FAILed to I 24)
642 Assert ISBUF
,<DS,DI>,"CheckFlush"
644 retz
; Skip free buffers, carry clear
646 JZ DOBUFFER
; Do all dirty buffers
649 retnz
; Buffer not for this unit or SFT
651 TEST [DI.buf_flags
],buf_dirty
652 retz
; Buffer not dirty, carry clear by TEST
654 PUSH WORD PTR [DI.buf_ID
]
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
665 Break <BUFWRITE
-- WRITE
OUT A BUFFER
IF DIRTY
>
668 ; DS:DI Points to the buffer
670 ; Write out all the buffer if dirty.
673 ; Carry set if error (currently user FAILed to I 24)
674 ; DS:DI Preserved, ALL others destroyed (ES too)
676 procedure BufWrite
,NEAR
677 ASSUME
DS:NOTHING
,ES:NOTHING
679 Assert ISBUF
,<DS,DI>,"BufWrite"
681 XCHG AX,WORD PTR [DI.buf_ID
] ; Free, in case write barfs
683 retz
; Buffer is free, carry clear.
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;
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]
698 MOV AX,[DI.buf_wrtcntinc
] ;>32mb ;AC000;
699 MOV [ALLOWED
],allowed_RETRY
+ allowed_FAIL
700 TEST [DI.buf_flags
],buf_isDATA
702 OR [ALLOWED
],allowed_IGNORE
704 PUSH DI ; Save buffer pointer
705 XOR DI,DI ; Indicate failure
710 ; Note: As far as I can tell, all disk reads into buffers go through this point. -mrw 10/88
714 cmp [buf_ems_mode
], -1
722 mov si, bx ; ds:si --> ems_buffer
723 mov di, offset dosgroup
:low_ems_buf
725 pop es ; es:di --> low_ems_buffer
736 mov bx, offset dosgroup
:low_ems_buf
738 pop ds ; ds:bx --> low_ems_buffer
742 invoke DWRITE
; Write out the dirty buffer
745 pushf ; save carry flag from DWRITE
746 cmp [buf_ems_mode
], -1
748 popf ; need to get at stack
749 pop bx ; ds:bx --> ems_buffer
751 pushf ; put it back, so we can pop it
753 popf ; restore carry flag
756 RestoreReg
<DS,DX,BX>
757 RestoreReg
<AX,CX,DI>
759 INC DI ; If at least ONE write succeedes, the operation
763 OR DI,DI ; Clears carry
764 JNZ BWROK
; At least one write worked
765 STC ; DI never got INCed, all writes failed.
771 Break <SET_RQ_SC_PARMS
-set requesting drive for SC
>
774 ; ES:BP = drive parameter block
776 ; Set requesting drive, and sector size
778 ; [SC_SECTOR_SIZE]= drive sector size
779 ; [SC_DRIVE]= drive #
781 ; All registers preserved
783 procedure SET_RQ_SC_PARMS
,NEAR
784 ASSUME
DS:NOTHING
,ES:NOTHING
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;
794 POP DX ;LB. restore dx ;AN000;
798 EndProc SET_RQ_SC_PARMS
;LB. return ;AN000;
800 Break <INC_DIRTY_COUNT
-increment dirty count
>
805 ; increment dirty buffers count
807 ; dirty buffers count in the current hash entry is incremented
809 ; All registers preserved
811 procedure INC_DIRTY_COUNT
,NEAR
812 ASSUME
DS:NOTHING
,ES:NOTHING
814 PUSH DS ;LB. save regs ;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;
821 EndProc INC_DIRTY_COUNT
;LB. return ;AN000;
823 Break <DEC_DIRTY_COUNT
-decrement dirty count
>
828 ; decrement dirty buffers count
830 ; dirty buffers count in the current hash entry is decremented
832 ; All registers preserved
834 procedure DEC_DIRTY_COUNT
,NEAR
835 ASSUME
DS:NOTHING
,ES:NOTHING
837 PUSH DS ;LB. save regs ;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;
844 POP SI ;LB. restore regs ;AN000;
847 EndProc DEC_DIRTY_COUNT
;LB. return ;AN000;
850 Break <MAP_ENTRY
- map the buffers of this
entry>
853 ; DS:DI ponits to hash entry
855 ; map the buferrs of this entry
857 ; the buffers are mapped
859 ; All registers preserved
861 procedure Map_Entry
,NEAR
862 ASSUME
DS:NOTHING
,ES:NOTHING
864 PUSH DX ;LB. save regs ;AN000;
867 JMP Map_Entry2
;LB. ;AN000;
868 EndProc Map_Entry
;LB. ;AN000;
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.
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 ;---------------------------------------------------------------------------
889 Procedure detect_collision
, near
890 ASSUME
DS:NOTHING
,ES:NOTHING
896 cmp [BUF_EMS_MODE
], -1
899 mov ax, [CURADD
] ; current offset
907 shr ax, cl ; convert to paragraphs
908 mov bx, word ptr [DMAADD
+2] ; get original segment
909 add ax, bx ; get current segment
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
917 mov ax, word ptr [DMAADD
]
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
939 EndProc detect_collision
941 Procedure Setup_EMS_Buffers
,Near
942 ASSUME
DS:NOTHING
,ES:NOTHING
;AN000;
944 cmp [BUF_EMS_MODE
], -1
953 mov bx, [BUF_HASH_COUNT
] ; # of hash table entries
954 lds di, [BUF_HASH_PTR
] ; ds:di -> hash table
959 mov ax, [BUF_EMS_PFRAME
]
960 mov word ptr ds:[di.BUFFER_BUCKET
+2], ax
961 add di, 8 ; next has entry.
975 EndProc Setup_EMS_Buffers