⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bambi.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 5 页
字号:
;            case.

	jmp     no_partial_on_front
skip_cache_em:
	add     curblk_l,1
	adc     curblk_h,0
	add     di,cache_block_bytes
	loop    skip_cache_em
	jmp     short   done_cache_em


;       pass read error condition back to caller.

got_fatal_error:
	les     bx,user_reqblk
	mov     es:[bx.reqstat],ax       ; pass error code back to caller
	mov     es:word ptr [bx.count],0 ; no sectors complete
	ret

;       d_count is now less than a full cache block
;         we are cache block aligned

do_last_partial:
	cmp     d_count,0               ; *IS* there a partial?
	jz      reading_done            ;  skip if not

	call    check_supercache_match
	jc      last_partial_moveit     ; just move it from supercache if so

;       last partial not in supercache.  Try regular cache next.

	call    check_hit               ; is last block in cache?
	jz      need_to_read_last_partial

;       Got it in regular cache!

	ifdef   USE_VALID
	mov     ax,d_count              ; ah=0, al=sectors we need
	call    make_sure_sectors_are_valid ; make sure they're valid
	jc      got_fatal_error         ; BUG1 fatal exit if read error
	endif

	mov     ax,d_count              ; starting with zero, read d_count
	les     di,d_trans
	mov     bp,cache_element_index
	call    read_part_cache_block   ; read it from cache
	jmp     short reading_done      ;  done!  exit okay!

;       We've gotta hit the disk.  Maybe we'll do a readahead too.

need_to_read_last_partial:

	call    readahead_check         ; should we readahead?
	mov     cx,1                    ; just read this one block if we're
;                                       ;  not sequential from last time
	jnz     last_partial_no_readahead

	mov     cx,max_valid_buffers    ; read/cache this many blocks if seq.

last_partial_no_readahead:

	call    get_curblks_into_cache  ; get those suckers into cache
	jnc     last_partial_readok     ; done if no read error

;       read error.  We'd better try reading just exactly what the
;         user requested.

	mov     ah,byte ptr d_count     ; get count
	xor     al,al                   ; start reading from front of block
	les     di,d_trans
	call    read_part_curblk_from_disk
	jnc     reading_done            ; done if read ok!!!
	jmp     got_fatal_error         ; fatal error if disk read error

last_partial_readok:
	mov     si,word ptr local_buf   ; we know the data is in the
					;  front of the local_buf

;       We will enter here when we're moving the data out of the
;       supercache.

last_partial_moveit:

	mov     ax,d_count
	mul     sector_size_bytes
	mov     cx,ax                   ; copy this many
	shr     cx,1                    ; convert to words

	les     di,d_trans
	mov     ds,lb_seg
	assume  ds:nothing
	rep     movsw

	push    cs
	pop     ds                      ; restore addressability
	assume  ds:zseg

reading_done:
	mov     ax,curblk_l
	mov     lastblk_l,ax            ; copy curblk to lastblk
	mov     al,curblk_h
	mov     lastblk_h,al

readwrite_done:
	les     bx,user_reqblk
	mov     es:[bx.reqstat],100h    ; normal completion
	ret                             ; no error checking for now


cache_reads     endp

;-----------------------------------------------------------------------
;
;       subroutine to check to see if curblk is just past lastblk;
;         this condition is used during a read of anything besides
;         a first partial, to trigger readahead.  Zero is set
;         when (curblk-1) == lastblk
;
;       ****Note:  For now, we'll also return zero when curblk==lastblk.
;           Depending on the exact exit path taken, lastblk may or may not
;           be updated to point past the end of the previous read.
;
;       trashes ax, cl

readahead_check proc    near
	assume  cs:zseg,ds:zseg,es:nothing

	mov     ax,curblk_l
	mov     cl,curblk_h
	sub     ax,lastblk_l
	sbb     cl,lastblk_h
	and     al,0feh         ; was result 0 or 1?
	or      al,ah
	or      al,cl           ; set zero flag if so
	ret

readahead_check endp

	ifdef   USE_VALID

;-----------------------------------------------------------------------
;
;       make sure that the currently needed sectors of the current
;         block are indeed valid.  If not, we've gotta read the
;         whole block and mark it valid.
;
;       Entry:  ah=first sector we need, al=number of sectors we need
;       Exit:   carry set if we had a read error
;               ax == error code if carry set   BUG1
;
;       Trashes:  all

make_sure_sectors_are_valid     proc    near
	assume  cs:zseg,ds:zseg,es:nothing

	mov     cx,ax                   ; get our counts into cx
	mov     ax,1
	shl     ax,cl                   ; get one bits for each of ours
	dec     ax
	mov     cl,ch                   ; now shift that for starting place
	shl     ax,cl

make_sure_sectors_are_valid     endp    ; fall into similar routine w/ mask

;-----------------------------------------------------------------------
;
;       make sure that the sectors in the currently looked-up cache
;        block whose mask is in ax are valid.  Otherwise, we've got
;        to force the whole damn cache block to be valid.
;
;       Entry:  ax == mask of sectors required from this block
;       Exit:   carry set if we had a read error
;               ax == error code if carry set BUG1
;
;       Trashes:  all

make_sure_sectors_are_valid_mask        proc    near
	assume  cs:zseg,ds:zseg,es:nothing

	log_it  0               ; tracker:  bambi type zero

	mov     cx,valid_mask           ; here is what's valid
	not     cx
	and     cx,ax                   ; were any of our 1 bits zero bits?
	jnz     make_cache_block_valid

	clc                             ; return with no error
	ret

make_cache_block_valid:

	log_it  1               ; tracker:  bambi type one

	mov     num_valid_buffers,0     ; invalidate supercache

	les     di,local_buf
	mov     ax,1                    ; block count
	push    cx                      ; BUG1 -- save mask of needed sectors
	call    read_curblks_from_disk  ; read it into buffer
	pop     cx                      ; BUG1 -- restore mask of needed secs
	jc      make_cache_readerror    ; skip if read error!!!!

	log_it  2               ; tracker:  time stamp reading done

;       Now we've got to copy only the NON-DIRTY sectors into
;       the cache, so that we don't replace data that hasn't yet
;       made it onto the disk.

	mov     cx,dirty_mask
	not     cx                      ; get NON-DIRTY bits
	and     cx,cache_mask

	xor     ah,ah                   ; ah=0 (sector zero)

;       Here we will assume CX != 0.  If all of the bits in
;       that block were DIRTY, they would also have to be VALID
;       and we'd never be here in the first place.

find_one_to_copy:
	inc     ah                      ; count it
	shr     cx,1
	jnc     find_one_to_copy        ; bypass clean block

	dec     ah                      ; this is the sector number
	xor     al,al                   ; count=1+number of contig ones in cl

find_number_to_copy:
	inc     al
	shr     cx,1
	jc      find_number_to_copy     ; loop while we find more ones

	shl     cx,1                    ; put a zero bit back
	push    cx                      ; save mask

	push    ax                      ; save count
	mov     al,ah                   ; get starting sector
	xor     ah,ah
	mul     sector_size_bytes
	les     di,local_buf            ; find location in disk buffer
	add     di,ax
	pop     ax                      ; restore count

	push    ax                      ; save count again
	mov     bp,cache_element_index
	call    write_part_cache_block  ; write into cache
	pop     ax
	pop     cx                      ; restore continuing mask

	log_it  3               ; tracker: xms written

	add     ah,al                   ; update sector number
	or      cx,cx
	jnz     find_one_to_copy

	mov     bx,cache_mask           ; valid == all
	mov     valid_mask,bx
	mov     cx,dirty_mask
	mov     bp,cache_element_index
	call    set_dirtyindex          ; mark it all valid
	clc
	ret                             ; return with carry set if error

;       BUG1 -- BEGIN NEW CODE!!!!!

;        -- the following error exit was totally messed up
;               in the Win 3.1 version of this code, causing
;               potential data loss in this case of bad adjacent blocks.
;       
;        the block we need is only partially valid, but trying
;        the usual technique of making the whole thing valid
;        won't work because there are bad sectors in the block.
;        We must try to read exactly the missing sectors we
;        need.  If this succeeds, we'll stick them in the
;        cache, otherwise, we'll bomb out with a fatal error.

make_cache_readerror:

;       Here is the old, wrong code.

;BUG1   mov     bp,cache_element_index
;BUG1   call    invalidate_element
;BUG1   stc                             ; return error condition, ax == code
;BUG1   ret

	push    cx                      ; save mask of new sectors to read
	xor     ah,ah                   ; ah=0 (sector zero)

;       Here we will assume cx != 0, because it is the mask of
;       sectors we need which are not valid in the cache.

find_one_to_read:
	inc     ah                      ; count it
	shr     cx,1
	jnc     find_one_to_read        ; bypass unneeded block

	dec     ah                      ; this is the sector number
	xor     al,al                   ; count=1+number of contig ones in cx

find_number_to_read:
	inc     al
	shr     cx,1
	jc      find_number_to_read     ; loop while we find more ones

	shl     cx,1                    ; put a zero bit back
	push    cx                      ; save mask

	push    ax                      ; save count
	mov     al,ah                   ; get starting sector
	xor     ah,ah
	mul     sector_size_bytes
	les     di,local_buf            ; find location in disk buffer
	add     di,ax
	pop     ax                      ; restore count

;       Now we have to read those sectors into the buffer.


	push    ax
	xchg    ah,al                           ; swap count and start
	push    es
	push    di
	call    read_part_curblk_from_disk      ; read the sectors we need
	pop     di
	pop     es
	jc      make_sure_fatal_read_error      ; abort if error
	pop     ax                      ; restore start sector and count

	push    ax                      ; save count again
	mov     bp,cache_element_index
	call    write_part_cache_block  ; write into cache
	pop     ax

	pop     cx                      ; restore continuing mask

	log_it  3                       ; tracker: xms written

	add     ah,al                   ; update sector number
	or      cx,cx
	jnz     find_one_to_read

	pop     ax                      ; get mask of sectors we just cached

	or      valid_mask,ax
	mov     bx,valid_mask
	mov     cx,dirty_mask
	mov     bp,cache_element_index
	call    set_dirtyindex          ; mark new sectors valid
	clc
	ret                             ; return no carry, no error

make_sure_fatal_read_error:
	add     sp,6                    ; get rid of count, running mask, and
;                                       ;  overall mask of missing sectors
	stc                             ; set error condition
	ret                             ; and return with error code in ax

;       BUG1 -- end of new code

make_sure_sectors_are_valid_mask        endp

	endif                           ; ifdef USE_VALID

;-----------------------------------------------------------------------
;
;       Now let's do a write function, caching any data that's
;         appropriate.

cache_write_data        proc    near
	assume  cs:zseg,ds:zseg,es:nothing

	test    flags_and_unit,40h      ; should we delay writes?
	jz      write_without_delay
if 1
	push    es                              ;check if this is a 
	les     si,accessing_swap_file_ptr      ;swapfile access, if so
	cmp     byte ptr es:[si],0              ;dont cache it
	pop     es
	jne     write_without_delay
endif
	jmp     short do_delayed_writes

;       Writes are not delayed.  Just make sure it's all in the
;         cache (except for first partial block with no hit), then
;         pass it through to the driver and return the error.

write_without_delay:
	mov     num_valid_buffers,0     ; invalidate supercache
	cmp     byte ptr curblk_index,0 ; partial block at the front?
	jz      wnodel_no_first_partial

;       count is min (cache_block_sectors - curblk_index, d_count)

	mov     ax,cache_block_sectors
	sub     ax,curblk_index         ; how many left in block?
	cmp     ax,d_count              ; do we want that many?
	jb      wnodel_need_em_all      ; skip if so

	mov     ax,d_count              ; only transfer what we need

wnodel_need_em_all:
	push    ax                      ; save the count
	call    check_hit               ; see if we hit on curblk
	pop     ax                      ; restore count into ax!!!!

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -