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

📄 disk.asm

📁 DOS源码
💻 ASM
📖 第 1 页 / 共 5 页
字号:
	iret

i2F_driver_check:
;
; Installation check
;
	mov	al,0ffh			; say we are installed
	iret

i2F_driver_add:
;
; Add new block device DS:DI
;
	push	ds
	push	es
	push	ds
	pop	es			; ES:DI -> unit
	mov	ds,cs:DataSegment
	call	add_unit
	pop	es
	pop	ds
	iret

i2F_driver_point:
;
; return DS:DI -> first UDSC_
;
	mov	ds,cs:DataSegment	; DS -> our data
	lds	di,ds:udsc_root
	iret
;
; Execute DRIVER.SYS request ES:BX
;
i2F_driver_req:
	push	ds
	mov	ds,cs:DataSegment
			Assume DS:CGROUP
	mov	ds:req_off,bx			; fill in request pointer
	mov	ds:req_seg,es			;  as if it was local
	pop	ds
			Assume DS:Nothing
	push	cs:driverTable			; fiddle the table address
	jmp	DriverFunction			;  then go to normal handler

	extrn	DriverFunction:near
	extrn	IntDiskTable:word		; = DiskTable

driverTable	dw	CG:IntDiskTable		; push address of table on
						; stack as DriverFunction
						; examines it

Int2FHandler	endp

	Assume	DS:CGROUP, SS:Nothing, ES:Nothing

	Public	DiskTable

DiskTable label word
	db	24			; Last supported function
	dw	CG:dd_init		; 0-initialize driver
	dw	CG:dd_medchk		; 1-media change check
	dw	CG:dd_build_bpb		; 2-build BIOS Parameter Block
	dw	CG:dd_error		; 3-IOCTL string input
	dw	CG:dd_input		; 4-input
	dw	CG:dd_error		; 5-nondestructive input (char only)
	dw	CG:dd_error		; 6-input status (char only)
	dw	CG:dd_error		; 7-input flush
	dw	CG:dd_output		; 8-output
	dw	CG:dd_output_vfy	; 9-output with verify
	dw	CG:dd_error		; 10-output status (char only)
	dw	CG:dd_error		; 11-output flush (char only)
	dw	CG:dd_error		; 12-IOCTL string output
	dw	CG:dd_open		; 13-device open
	dw	CG:dd_close		; 14-device close
	dw	CG:dd_remchk		; 15-removable media check
	dw	CG:dd_error		; 16-n/a
	dw	CG:dd_error		; 17-n/a
	dw	CG:dd_error		; 18-n/a
	dw	CG:dd_genioctl		; 19-generic IOCTL
	dw	CG:dd_error		; 20-n/a
	dw	CG:dd_error		; 21-n/a
	dw	CG:dd_error		; 22-n/a
	dw	CG:dd_getdev		; 23-get logical drive
	dw	CG:dd_setdev		; 24-set logical drive

driver	proc	near

point_unit:	; get unit descriptor for work drive
;----------
; On Entry:
;	ES:BX -> Request Header
; On Exit:
;	AL = logical drive
;	ES:DI -> es:UDSC_
;	(All other registers preserved)
;
	mov	al,es:RH_UNIT[bx]	; get the unit number (0=A:, 1=B:, etc)
	les	di,udsc_root		; ES:DI -> 1st es:UDSC_
point_unit10:
	cmp	al,es:UDSC_DRIVE[di]	; stop if the logical drive matches
	 je	point_unit20	
	les	di,es:UDSC_NEXT[di]
	cmp	di,0FFFFh		; else try the next es:UDSC_
	 jne	point_unit10
	pop	ax			; don't return to the caller
	mov	ax,RHS_ERROR+1		; return "invalid unit" error
point_unit20:
	ret

add_unit:	; add a new unit to the list
;--------
; On Entry:
;	ES:DI -> UDSC to add
; On Exit:
;	ES:DI preserved
;
	mov	al,es:UDSC_DRIVE[di]	; get the logical unit
	cmp	al,MAXPART		; is it too many ?
	 jae	add_unit40
	push	ds
	mov	es:word ptr UDSC_NEXT[di],0FFFFh
					; make sure it's terminated
	and	es:UDSC_FLAGS[di],UDF_HARD+UDF_CHGLINE
	lea	si,udsc_root		; DS:SI -> [first UDSC_]
add_unit10:
	cmp	ds:word ptr UDSC_NEXT[si],0FFFFh
	 je	add_unit30
	lds	si,ds:UDSC_NEXT[si]	; DS:SI -> UDSC_ we already have
	mov	al,es:UDSC_RUNIT[di]
	cmp	al,ds:UDSC_RUNIT[si]	; do the logical units match ?
	 jne	add_unit10
	mov	ax,ds:UDSC_FLAGS[si]	; inherit some flags
	push	ax
	and	ax,UDF_HARD+UDF_CHGLINE
	mov	es:UDSC_FLAGS[di],ax	; hard disk/changeline inherited
	pop	ax
	test	ax,UDF_HARD
	 jnz	add_unit10		; skip owner stuff on hard drive
	test	ax,UDF_VFLOPPY		; is this a multiple drive anyway ?
	 jnz	add_unit20
	or	ax,UDF_OWNER+UDF_VFLOPPY
	mov	ds:UDSC_FLAGS[si],ax	; no, 1st person becomes owner
add_unit20:
	or	es:UDSC_FLAGS[di],UDF_VFLOPPY
	jmps	add_unit10		; go and try the next
add_unit30:
	mov	ds:word ptr UDSC_NEXT[si],di
	mov	ds:word ptr UDSC_NEXT+2[si],es
	pop	ds
add_unit40:
	ret

dd_error:	; 3-IOCTL string input
;--------
	mov	ax,RHS_ERROR+3		; "invalid command" error
	ret

dd_medchk:	; 1-media change check
;---------
;	entry:	ES:BX -> request header
;	exit:	RH1_RETURN = 0, 1 or FF
;		  00 = media may have changed
;		  01 = media hasn't changed
;		  FF = media has been changed

	call	point_unit		; get unit descriptor
	test	es:UDSC_FLAGS[di],UDF_HARD
	 jnz	medchk2			; "hasn't changed" if hard disk
	call	ask_for_disk		; make sure we've got correct floppy
	mov	ax,es:UDSC_FLAGS[di]	; get flags
	test	ax,UDF_UNSURE		; has format/diskcopy occurred?
	 jnz	medchk6			; may have changed to different format
	test	ax,UDF_CHGLINE
	 jz	medchk3			; skip ROS call if no change line
	mov	dl,es:UDSC_RUNIT[di]
	mov	al,dl			; don't trust changeline if we are
	xchg	al,activeRosUnit	;  changing floppies
	cmp	al,dl			; return may have changed
	 jne	medchk3
	mov	ah,ROS_DSKCHG		; get disk change status function
	int_____DISK_INT		; AH=0: DC low, AH=6: DC active
	 jc	medchk5			; disk change not active?
medchk2:
	mov	al,01h			; disk hasn't changed
	jmps	medchk_ret


medchk3:				; no changeline support, use timer
	call	read_system_ticks	; get system tick count in CX/DX
	mov	ax,dx
	xchg	ax,es:UDSC_TIMER[di]	; get previous time and update
	sub	dx,ax
	mov	ax,cx
	xchg	ax,es:UDSC_TIMER+2[di]
	sbb	cx,ax			; CX/DX = # ticks since last access
	 jne	medchk5			; media could have changed if > 64k
	cmp	dx,18*3			; more than three seconds expired?
	 jb	medchk2			; "not changed" if access too recent
medchk5:
	mov	cx,1			; read track 0, sector 1 (boot sector)
	call	login_read		; to check the builtin BPB
	 jc	medchk6			; may have changed if read error
	mov	al,local_buffer+11+BPB_FATID
	cmp	al,0F0h			; check if we find a BPB
	 jb	medchk6			; may have changed if not good BPB
	cmp	al,es:UDSC_BPB+BPB_FATID[di]
	 jne	medchk8			; has media byte changed ?
	mov	si,offset CGROUP:local_buffer+UDSC_BPB_LENGTH+11+2
	lodsb				; get extended boot
	sub	al,29h			; do we have an extended boot ?
	 je	medchk7			; no, test against our dummy value
	push	cs
	pop	ds			; DS:SI -> our dummy value
	mov	si,offset CGROUP:dummyMediaID
medchk7:
	push	di
	lea	di,UDSC_SERIAL[di]
	mov	cx,2
	repe	cmpsw			; is serial number unchanged ?
	pop	di
	 je	medchk6			; then return may have changed
medchk8:
	lea	ax,UDSC_LABEL[di]	; ES:AX -> ASCII label
	lds	bx,REQUEST[bp]
	mov	ds:word ptr RH1_VOLID[bx],ax
	mov	ds:word ptr RH1_VOLID+2[bx],es
	mov	al,0FFH			; return disk changed
	jmps	medchk_ret

medchk6:
	mov	al,00h			; disk may have changed

medchk_ret:
	and	es:UDSC_FLAGS[di],not UDF_UNSURE
	les	bx,REQUEST[bp]
	mov	es:RH1_RETURN[bx],al	; set return value
	sub	ax,ax
	ret


	page
dd_build_bpb:	; 2-build BIOS Parameter Block
;------------
	call	point_unit		; get unit descriptor
	test	es:UDSC_FLAGS[di],UDF_HARD
	 jnz	bldbpb1			; BPB doesn't change for hard disks
	call	login_media		; try to determine media type (BPB)
	 jc	bldbpb_err
bldbpb1:
	mov	es:UDSC_OPNCNT[di],0	; no files open at this time
	and	es:UDSC_FLAGS[di],not UDF_UNSURE
					; media is sure
	lea	si,UDSC_BPB[di]
	mov	ax,es
	les	bx,REQUEST[bp]
	mov	es:RH2_BPBOFF[bx],si	; return the current BPB
	mov	es:RH2_BPBSEG[bx],ax

	xor	ax,ax
	ret

bldbpb_err:
	jmp	xlat_error		; return error code
;	ret



login_media:		; determine BPB for new floppy disk
;-----------
	push	ds
	mov	cx,1			; read track 0, sector 1 (boot)
	call	login_read		; to determine media type
	 jc	login_media_err		; abort if physical error
	cmp	local_buffer+11+BPB_FATID,0F0h
	 jb	login_media10		; fail unless FATID sensible
	lodsw				; get JMP instruction from boot sector
	xchg	ax,bx			; save in BX
	lodsb				; get next 3rd byte in AX
	add	si,8			; skip JMP, OEM name, SI -> BPB
	cmp	bl,0E9h			; does it start with a JMP ?
	 je	login_media40
	cmp	bl,069h
	 je	login_media40
	cmp	bl,0EBh			; how about a JMPS ?
	 jne	login_media10
	cmp	al,090h			; then we need a NOP
	 je	login_media40
login_media10:
	mov	cx,2			; read track 0, sector 2 (FAT)
	call	login_read		; try to read the sector
	 jc	login_media_err		; abort if physical error
	cmp	word ptr 1[si],-1	; bytes 1, 2 must be 0FFh, 0FFh
	 jne	login_media30		; default media if bad FAT
	lodsb				; else get FAT ID byte
	mov	si,CG:bpb160		; look through builtin BPB table
	mov	cx,NBPBS		; # of builtin BPBs
login_media20:
	cmp	al,BPB_FATID[si]	; does it match one we know?
	 je	login_media40		; yes, use builtin BPB
	add	si,BPB_LENGTH		; else move to next BPB
	loop	login_media20		; repeat for all BPBs
login_media30:				; can't find that FAT ID
	lea	si,UDSC_DEVBPB[di]	; use the default type
	push	es
	pop	ds			; use BPB at DS:SI ->
login_media40:
	push	di
	lea	di,UDSC_BPB[di]		; ES:DI -> unit descriptor (UDSC)
	mov	cx,UDSC_BPB_LENGTH	; size of a BPB (less reserved stuff)
	rep	movsb			; copy into unit descriptor
	pop	di
	mov	es:UDSC_BPB+BPB_SECSIZ[di],SECSIZE
;	mov	cx,0
	mov	es:word ptr (UDSC_BPB+BPB_HIDDEN)[di],cx
	mov	es:word ptr (UDSC_BPB+BPB_HIDDEN+2)[di],cx
	cmp	si,offset CGROUP:local_buffer+UDSC_BPB_LENGTH+11
	 jne	login_media50		; is the BPB from the boot sector ?
;	mov	ax,ds			; if so then check for media id
;	cmp	ax,cs:DataSegment	; seg check redundant as UDSC_DEVBPB
;	 jne	login_media50		;  is followed by 7 bytes of zero
	lodsw				; skip 2 bytes
	lodsb				; now get possible boot signature
	cmp	al,29h			; is it an extended boot sector ?
	 je	login_media60		; yes, use it
login_media50:
	push	cs
	pop	ds			; DS:SI -> our dummy value
	mov	si,offset CGROUP:dummyMediaID
login_media60:
	call	UpdateMediaID		; update UDSC_ with media info
	clc
login_media_err:
	pop	ds
	ret

dummyMediaID	dd	0	; serial number 0
		db	'NO NAME    '
		db	'FAT12   '

UpdateMediaID:
;-------------
; On Entry:
;	DS:SI -> extended boot record info
;	ES:DI -> UDSC_ to update
; On Exit:
;	ES:DI preserved
;
	push	di
	xor	ax,ax			; AX = a handy zero	
	lea	di,UDSC_SERIAL[di]
	movsw
	movsw				; copy serial number
	pop	di
	push	di
	lea	di,UDSC_LABEL[di]
	mov	cx,11
	rep	movsb			; copy the volume label
	stosb				; zero terminate it
	pop	di
	push	di
	lea	di,UDSC_FSTYPE[di]
	movsw
	movsw
	movsw
	movsw				; copy the file system type
	stosb				; zero terminate it
	pop	di
	ret


login_read:
;	entry:	CH, CL = cylinder/sector to read
;	exit:	CY = 1, AH = status if error
;		else local_buffer filled in

	mov	dl,es:UDSC_RUNIT[di]	; DL = ROS drive
	mov	dh,0			; DH = head number

login_read_dx:				; read on drive DL, head DH
;-------------				; (entry for hard disk login)
	mov	P_RETRY[bp],RETRY_MAX	; initialize retry count
logrd1:
	push	es
	mov	ax,ROS_READ*256 + 1	; read one sector from ROS
	push	ds
	pop	es			; ES = DS = local segment
	mov	bx,CG:local_buffer
	int_____DISK_INT		; call the ROM BIOS
	pop	es
	 jnc	logrd3			; skip if no disk error
	push	ax
;	mov	ah,ROS_RESET
	xor	ax,ax
	int_____DISK_INT		; reset the drive
	pop	ax
	dec	P_RETRY[bp]
	 jnz	logrd1			; loop back if more retries
logrd2:
	stc
logrd3:
	mov	si,CG:local_buffer
	ret

	page
dd_output:	; 8-output
;---------
	mov	P_ROSCMD[bp],ROS_WRITE	; write to floppy/hard disk
	jmps	io_common

dd_output_vfy:	; 9-output with verify
;-------------
	mov	P_ROSCMD[bp],ROS_VERIFY	; write & verify floppy/hard disk
	jmps	io_common

dd_input:	; 4-input
;--------
	mov	P_ROSCMD[bp],ROS_READ	; read from floppy/hard disk
;	jmps	io_common

io_common:				; common code for the above three
	call	point_unit		; get unit descriptor
	call	ask_for_disk		; make sure we've got correct floppy
	call	setup_rw		; setup for read/write operation
	 jc	io_ret			; return if bad parameters
io_loop:
	call	track_rw		; read as much as possible on track
	 jc	xlat_error		; return if physical disk error
	cmp	P_COUNT[bp],0		; test if any more stuff to read
	 jne	io_loop			; yes, loop back for more

	mov	al,es:UDSC_RUNIT[di]	; remember the drive that is active
	mov	activeRosUnit,al
	test	es:UDSC_FLAGS[di],UDF_HARD+UDF_CHGLINE
	 jnz	io_exit			; skip timer read for hard/changeline

	call	read_system_ticks	; get system tick count in CX/DX
	mov	es:UDSC_TIMER[di],dx
	mov	es:UDSC_TIMER+2[di],cx	; save time of successful access
io_exit:
	xor	ax,ax			; all done, no error encountered
io_ret:
	ret

xlat_error:	;  translate ROS error to DOS error
;----------
;	entry:	AH = ROS disk error code, CY = 1
;	exit:	AX = status to be returned to BDOS

	pushx	<es, di>		; save some registers
	mov	al,ah			; AL = ROS error code
	push	cs
	pop	es
	mov	di,CG:ros_errors	; ES:DI -> ROS error code table
	mov	cx,NUMROSERR
	repne	scasb			; scan for match
	mov	ax,RHS_ERROR		; get basic error indication
	or	al,cs:(CG:dos_errors-CG:ros_errors-1)[di]
					; combine with type of error
	popx	<di, es>
	stc
	ret



setup_rw:	; prepare for INPUT, OUTPUT or OUTPUT_VFY
;--------
; On Entry:
;	ES:DI -> UDSC

⌨️ 快捷键说明

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