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

📄 bdevio.a86

📁 与MS-DOS兼容的DOS操作系统
💻 A86
📖 第 1 页 / 共 3 页
字号:
title 'BDEVIF - Block DEVice Input/Output support'
;    File              : $BDEVIO.A86$
;
;    Description       :
;
;    Original Author   : DIGITAL RESEARCH
;
;    Last Edited By    : $CALDERA$
;
;-----------------------------------------------------------------------;
;    Copyright Work of Caldera, Inc. All Rights Reserved.
;      
;    THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
;    PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
;    ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
;    WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
;    THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
;    HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
;    AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
;    AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
;    COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
;    CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
;    TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
;    CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
;    AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
;    CIVIL LIABILITY.
;-----------------------------------------------------------------------;
;
;    *** Current Edit History ***
;    *** End of Current Edit History ***
;
;    $Log$
;    BDEVIO.A86 1.27 94/11/30 16:25:22
;    added delayed retry for read/write to locked region
;    added support for using multiple FAT copies on reads if one fails;    
;    BDEVIO.A86 1.26 94/02/22 17:11:25
;    Fix where corrupt dir entry results in read beyond end-of-chain (Filelink bug)
;    BDEVIO.A86 1.25 93/12/15 03:07:11
;    New ddioif entry point so Int 25/26 bypasses address normalisation
;    BDEVIO.A86 1.24 93/12/08 03:15:14
;    Force rebuild_ldt_root if root in JOIN's subdirectory
;    BDEVIO.A86 1.23 93/11/19 18:29:29
;    Fix for SERVER print queue viewing problem
;    BDEVIO.A86 1.22 93/09/21 12:43:37
;    On fdos read/write do EOF checks before SHARE LOCK checks
;    BDEVIO.A86 1.21 93/09/14 20:02:50
;    Trust LFLG_PHYSICAL
;    BDEVIO.A86 1.20 93/09/02 22:22:56
;    Use 32 bit sectors to read fat for build bpb if appropriate (SYQUEST bug)
;    BDEVIO.A86 1.19 93/08/27 18:46:49
;    int 26 discards hash codes
;    BDEVIO.A86 1.18 93/07/20 22:42:25
;    Even fewer checks on int 25/26 
;    BDEVIO.A86 1.12 93/06/23 02:57:07
;    Add auto-commit to fdowrw
;    BDEVIO.A86 1.11 93/05/14 13:47:41
;    Shorten media change code slightly
;    BDEVIO.A86 1.9 93/03/16 22:30:21 IJACK
;    UNDELETE support changes
;    ENDLOG

	eject ! include i:mserror.equ	; F_DOS erros
	eject ! include i:fdos.equ
	eject ! include i:driver.equ
	eject ! include i:doshndl.def
	eject ! include bdos.equ
	eject ! include rh.equ

;*****************************************************
;*
;*	bdos data area
;*
;*****************************************************

PCMODE_DATA	dseg	word
	extrn	current_ddsc:dword
	extrn	current_dhndl:dword
	extrn	current_dsk:byte	; default drive
	extrn	current_ldt:dword	; currently selected LDT
	extrn	dma_offset:word		; DTA offset
	extrn	dma_segment:word	; DTA segment
	extrn	ddsc_ptr:dword
	extrn	err_drv:byte
	extrn	error_dev:dword		; failing device for Int 24's
	extrn	fdos_stub:dword
	extrn	ioexerr:byte
	extrn	last_drv:byte
	extrn	ldt_ptr:dword
	extrn	lock_bios:dword
	extrn	phys_drv:byte
	extrn	rwmode:byte
	extrn	share_stub:dword
	extrn	unlock_bios:dword
	extrn	verify_flag:byte
	extrn	net_retry:word

BDOS_DATA	dseg	word

	extrn	bcb_root:dword
	extrn	deblock_seg:word
	extrn	fdos_hds_drv:byte
	extrn	fdos_hds_blk:word
	extrn	fdos_hds_root:word
	extrn	fdos_ret:word

	public	adrive
	public	clsize
	public	dosfat
	public	cur_dma
	public	cur_dma_seg
	public	datadd
	public	diradd
	public	dirinroot
	public	dirperclu
	public	fatadd
	public	hdsaddr
	public	lastcl
	public	logical_drv
	public	mult_sec
	public	nfatrecs
	public	nfats
	public	pblock
	public	physical_drv
	public	psecsiz
	public	req_hdr
	public	secperclu

eject
; The following specify the drive selected for the current operation

hdsaddr		dw	0		; current HDS address (0 means at root)
logical_drv	db	0		; logical drive number
physical_drv	db	0		; physical disk number

; The following describe the currently active drive - not this may differ from
; the currently selected drive above due to eg. flushing dirty buffers

; Local copy of DDSC_ variables - ORDER CRITICAL - must match DDSC_

local_ddsc	rb	0
psecsiz		dw	0		; byte size of sector
clmsk		db	0
clshf		db	0
fatadd		dw	0		; sector offset of 1st FAT sector
byte_nfats	db	0		; number of FAT's
dirinroot	dw	0		; # dir entries in root
datadd		dw	0		; sector offset of data sector
lastcl		dw	0		; # last cluster (after adjustment)
if DOS5
		dw	0		; # sectors per FAT
else
		db	0		; # sectors per FAT (nb. may be inaccurate on large drives)
endif
diradd		dw	0		; sector offset of 1st root DIR sector

LOCAL_DDSC_LEN	equ	offset $ - offset local_ddsc

;	some extra parameters calculated from local_ddsc for convenience

nfats		dw	0		; # FAT's (WORD is handier)
nfatrecs	dw	0		; # sectors per FAT (accurate version)
clsize		dw	0		; cluster size in bytes
secperclu	dw	0		; # sectors per cluster
dirperclu	dw	0		; # dir enrties in subdir

dosfat		dw	0		; FAT length indicator (FAT12 or FAT16)

; The following specify the next block read/write operation on the active drive

adrive		db	0ffh		; currently active disk
pblock		dw	0, 0		; absolute block address
mult_sec	dw	1		; multi sector count passed to xios
cur_dma		dw	0
cur_dma_seg	dw	0

fdrwreq		dw	0		; requested count (roundup)

	public	fdrwflg
fdrwflg		db	0		; bdosrw flags
fdrwcnt		dw	0		; requested byte count for read/write
fdrwptr		rd	0		; disk transfer address for read/write
fdrwoff		dw	0		; offset for R/W DTA
fdrwseg		dw	0		; segment for R/W DTA

fdrwsec		rd	1		; physical block for fdosrw
fdrwsecoff	dw	0		; offset within sector
fdrwdircnt	dw	0		; # sectors in direct xfer

byteoff		dw	0		; fdosrw local variable
		dw	0		; byte offset with file

blk		dw	0		; current cluster of filepos
blkidx		dw	0		; current cluster index within file
blkoffset	dw	0		; offset within cluster

;	static request header for DOS device driver I/O

	Public	req_hdr

req_hdr		rb	0
req_len		db	22
req_unit	rb	1
req_cmd		rb	1
req_status	rw	1
req_rwmode	db	0		; action hint for device drivers
		rb	7
req_media	rb	1
		rb	16

req1_return	equ	byte ptr req_media+1
req1_volid	equ	word ptr req_media+2

req2_buffer	equ	word ptr req_media+1
req2_bpb	equ	word ptr req_media+5

req3_buffer	equ	word ptr req_media+1
req3_count	equ	word ptr req_media+5
req3_sector	equ	word ptr req_media+7
req3_volid	equ	word ptr req_media+9

req4_buffer	equ	word ptr req_media+1
req4_count	equ	word ptr req_media+5
req4_sector	equ	word ptr req_media+7
req4_volid	equ	dword ptr req_media+9
req4_bigsector	equ	dword ptr req_media+13

eject
BDOS_CODE	cseg

	extrn	alloc_chain:near
	extrn	bpb2ddsc:near		; converts BPB to DDSC
	extrn	buffers_check:near	; look for buffers
	extrn	delfat:near
	extrn	discard_all:near	; discard all buffers
	extrn	discard_dir:near	; discard directory buffers
	extrn	discard_dirty:near	; discard all dirty buffers
	extrn	discard_files:near	; discard open files
	extrn	fdos_error:near
	extrn	fdos_restart:near
	extrn	file_update:near
	extrn	fixfat:near
	extrn	getnblk:near		; get block value from FAT
	extrn	get_ldt:near
	extrn	get_ldt_raw:near
	extrn	hdsblk:near		; get current HDS block
	extrn	hshdscrd:near
	extrn	locate_buffer:near
	extrn	rebuild_ldt_root:near
	extrn	timestamp_dhndl:near
	extrn	update_dat:near
	extrn	update_fat:near
	extrn	share_delay:near

	public	block_device_driver
	public	clus2sec
	public	device_driver
	public	read_block
	public	select_adrive
	public	select_logical_drv
	public	select_physical_drv
	public 	write_block

eject

eject

	Public	get_ddsc

get_ddsc:
;--------
; On Entry:
;	AL = physical drive
; On Exit:
;	CY set if bad drive, else
;	ES:BX -> DDSC_
;	(All other registers preserved)
;
	cmp	al,ss:phys_drv
	 jae	get_ddsc30
	les	bx,ss:ddsc_ptr
get_ddsc10:
	cmp	bx,0FFFFh		; end of the line
	 je	get_ddsc30
	cmp	al,es:DDSC_UNIT[bx]	; does the unit match ?
	 je	get_ddsc20		; no, try the next
	les	bx,es:DDSC_LINK[bx]
	jmps	get_ddsc10
get_ddsc20:
;	clc
	ret
get_ddsc30:
	stc
	ret

eject
;	Read/Write from/to disk file

;	entry:	CURRENT_DNHDL -> file handle
;		BDRWFLG = 1 => read
;			  0 => write
;		ES:DI = buffer (32 bit: off/seg)
;		CX = requested byte count (16 bit)

;	exit:	FDOS_RET = number of bytes read/written
;		CURRENT_DHNDL incremented by FDOS_RET

	public	fdosrw			; read/write to/from disk file

fdosrw:
;------
	call	fdrw_prepare		; set up address, where we are in file
	 jc	fdrw_error		;  stop if we have a problem
	call	fdrw_size		; extend file if necessary
	 jc	fdrw_error		;  bail out if we can't
	cmp	fdrwcnt,0		; are we truncating?
	 jne	fdrw_loop		; read/write if non-zero count
	test	fdrwflg,1		; writing zero bytes?
	 jnz	fdrw_error		; (reading has no meaning)
	call	fdw_trunc		; writing truncates the file
	jmps	fdrw_nobigger
fdrw_error:
	ret

fdrw_loop:				; loop here for long reads/writes
	call	fdrw_seek		; seek to position for xfer
	 jc	fdrw_exit		;  should get error's now...
	 jnz	fdrw_buffered		; deblocking required if not aligned
	mov	cx,fdrwcnt		; CX = requested transfer size
	cmp	cx,psecsiz		; at least one sector transferred?
	 jb	fdrw_buffered		; if less, need deblocked transfer
	mov	fdrwreq,cx		; requested count for direct r/w
	call	direct_rw		; transfer straight to/from TPA
	jmps	fdrw_more
fdrw_buffered:				; perform deblocked read/write
	call	deblock_rw		; transfer via BDOS buffer
fdrw_more:
	add	fdrwoff,ax		; adjust buffer address
	add	fdos_ret,ax		; adjust return code

	add	byteoff,ax		; adjust file offset
	adc	byteoff+2,0

	sub	fdrwcnt,ax		; adjust remaining count
	 ja	fdrw_loop		; still more to do
fdrw_exit:
	les	bx,current_dhndl
	mov	ax,fdos_ret		; get total xfered and update position
	add	es:DHNDL_POSLO[bx],ax
	adc	es:DHNDL_POSHI[bx],0
	test	fdrwflg,1
	 jnz	fdrw_return		; skip if reading
	mov	ax,byteoff		; has the file grown ?
	mov	dx,byteoff+WORD
	sub	ax,es:DHNDL_SIZELO[bx]
	sbb	dx,es:DHNDL_SIZEHI[bx]
	 jb	fdrw_nobigger		; yes, update the file size
	add	es:DHNDL_SIZELO[bx],ax
	adc	es:DHNDL_SIZEHI[bx],dx
fdrw_nobigger:
	call	timestamp_dhndl		; record the current time
	test	es:DHNDL_MODE[bx],DHM_COMMIT
	 jz	fdrw_return		; is auto-commit in place ?
	call	file_update		; yes, commit the file
fdrw_return:
	ret



fdw_trunc:
;---------
; On Entry:
;	BLKIDX = block number within file
;	BLKOFFSET = block offset
; On Exit:
;	DHNDL_SIZE adjusted, any excess clusters freed
;

	les	bx,current_dhndl
	mov	cx,blkoffset		; get offset within current block
	mov	ax,blkidx		; get logical block number
	 jcxz	fdw_t10			; skip if no data in last block
	inc	ax			; else add in another cluster
fdw_t10:				; AX = # of clusters required in file
	test	ax,ax
	 jnz	fdw_t20
	xchg	ax,es:DHNDL_BLK1[bx]	; forget about chain
	jmps	fdw_t50

fdw_t20:
	xchg	ax,cx			; CX = # of blocks to keep
	mov	ax,es:DHNDL_BLK1[bx]	; get first block in file
fdw_t30:				; scan all block we want to keep
	push	cx
	push	ax
	call	getnblk			; get next block
	pop	bx
	pop	cx
	cmp	ax,lastcl		; stop on premature end of chain
	 ja	fdw_t60
	loop	fdw_t30
	push	ax			; yep, remember what
	mov	ax,dosfat
	xchg	ax,bx			; truncate chain at cluster AX
	call	fixfat			;  as thats all we need
	pop	ax
fdw_t50:
	call	delfat			; release the chain
fdw_t60:
	les	bx,current_dhndl
	mov	ax,byteoff		; now truncate the file
	mov	es:DHNDL_SIZELO[bx],ax
	mov	ax,byteoff+2
	mov	es:DHNDL_SIZEHI[bx],ax
	xor	ax,ax			; cause reads/writes to scan
	mov	es:DHNDL_BLK[bx],ax	;   block chain from start
	mov	es:DHNDL_IDX[bx],ax
	mov	fdos_ret,ax		; no logical errors
	ret



fdrw_prepare:
;------------
; Normalise the xfer address and count
; Calculate current position in the file
;
; On Entry:
;	ES:DI -> buffer
;	CX = bytes to xfer
; On Exit:
;	FDRWSEG:FDRWOFF -> normalised buffer
;	FDRWCNT = bytes to xfer
;	FDOS_RET = bytes xfer'd (0)
;	PREREAD = TRUE
;	BYTEOFF = current offset in file
;	BLKIDX = cluster containing current file position
;	BLKOFFSET = offset within cluster
;	CY set if current position theoretically impossible
;

	xor	ax,ax			; AX = 0
	mov	fdos_ret,ax		; initialize byte return count
	mov	fdrwcnt,cx		; save byte count for read/write
	mov	ax,000Fh
	and	ax,di			; get offset within paragraph
	mov	fdrwoff,ax		; save normalized offset for read/write
	add	ax,cx			; do we overflow 64k ?
	 jnc	fdrw_p10		; yes, then forget about what would
	sub	fdrwcnt,ax		;  overflow this segment
fdrw_p10:
	mov	cl,4
	shr	di,cl			; DI = paragraph offset
	mov	ax,es
	add	ax,di			; AX = effective segment
	 jnc	fdrw_p20		; if above 1 MByte base it at FFFF
	inc	ax			; AX = para's above FFFF
	shl	ax,cl			; make it bytes
	add	fdrwoff,ax		;  add to offset
	mov	ax,0ffffh		; use our magic segment
fdrw_p20:
	mov	fdrwseg,ax		; save normalized segment for read/write
	les	bx,current_dhndl
	mov	ax,es:DHNDL_POSLO[bx]
	mov	byteoff,ax		; copy position to local variables
	mov	ax,es:DHNDL_POSHI[bx]
	mov	byteoff+WORD,ax
	mov	cx,clsize
	mov	ax,lastcl
	mul	cx			; DX:AX = maximum size of disk
	sub	ax,byteoff
	sbb	dx,byteoff+WORD		; beyond this we can't go
	 jc	fdrw_p30
	mov	ax,byteoff		; DX:AX = current file size
	mov	dx,byteoff+WORD
	div	clsize
	mov	blkidx,ax		; save it for later
	mov	blkoffset,dx		; DX = offset within cluster
	clc				; theoretically possible
fdrw_p30:
	ret




fdrw_size:
;---------
; On reads check xfer starts within file, and clip size to reflect EOF.
; On writes try to extend to cluster chain so it is big enough to contain
; the data we wish to write.
;
; On Entry:
;	BYTEOFF = current position in file

⌨️ 快捷键说明

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