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

📄 disk.asm

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

set2:					; now set track layout
	lea	si,BPB_LENGTH+7[bx]	; DS:SI -> new user layout
	mov	es,cs:DataSegment
	mov	di,CG:layout_table	; ES:DI -> BIOS layout table
	lodsw				; get sector count
	test	ax,ax			; make sure this is good value
     jz set6            
	cmp	ax,MAX_SPT		; make sure this is good value
	 ja	set6			;   so we don't overflow table
	xchg	ax,cx			; CX = sector count
set3:					; loop here for every sector
	inc	di
	inc	di
	lodsw				; get sector number
	stosb				; write sector number
	lodsw				; get sector size (0080, 0100, 0200, 0400)
	shl	ax,1			; double it (0100, 0200, 0400, 0800)
set4:
	shr	ah,1			; halve the sector size until = 128
	 jc	set5			; we've shifted out bottom bit
	inc	al			; count the # of bits
	 jnz	set4			; (this should always jump)
set5:
	stosb				; store LOG2 (sector size/128)
	loop	set3			; repeat for all sectors
set6:
	pop	es
	pop	ds
	xor	ax,ax
	ret

ioctl_read:
;----------

	mov	P_ROSCMD[bp],ROS_READ	; read physical track
	jmps	ioctl_rw_common		; use common code

ioctl_write:
;-----------

	mov	P_ROSCMD[bp],ROS_WRITE	; write physical track
;	jmps	ioctl_rw_common		; use common code

ioctl_rw_common:
	call	ask_for_disk		; make sure we've got correct floppy
	push	ds
	call	point_ioctl_packet	; DS:BX -> ioctl packet
	mov	al,ds:5[bx]		; get logical sector (0..SPT-1)
	mov	P_SECTOR[bp],al
	mov	ax,ds:7[bx]		; get sector count
	mov	P_COUNT[bp],ax
	mov	ax,ds:9[bx]		; get transfer address
	mov	P_DMAOFF[bp],ax
	mov	ax,ds:11[bx]
	mov	P_DMASEG[bp],ax
	mov	ax,ds:1[bx]		; get head number
	mov	P_HEAD[bp],al
	mov	ax,ds:3[bx]		; get cylinder number
	mov	P_CYL[bp],ax
	pop	ds
rw_loop:
	call	track_rw		; read as much as possible on track
	 jc	rw_err			; return if physical disk error
	cmp	P_COUNT[bp],0		; test if any more stuff to read
	 jne	rw_loop			; yes, loop back for more
	sub	ax,ax			; all done, no error encountered
	ret				; return O.K. code
rw_err:
	jmp	xlat_error		; translate ROS code to DOS error
;	ret

ioctl_verify:
;------------
ioctl_format:
;------------
	call	ask_for_disk		; make sure we've got correct floppy
	mov	P_RETRY[bp],RETRY_MAX	; perform up to three retries
format_retry:
	call	set_format		; attempt data rate setup
	push	ds
	call	point_ioctl_packet	; DS:BX -> ioctl packet
	test	ds:byte ptr [bx],1	; are we testing parameters only ?
	 jz	format10
	mov	ds:[bx],al		; return AL
	pop	ds
	xor	ax,ax			; we succeeded
	ret

format10:
	mov	ax,es:UDSC_BPB+BPB_SPT[di]
	test	ds:byte ptr [bx],2	; is it undocumented "do 2 tracks" bit?
	 jz	format20
	add	ax,ax			; yes, double the count
format20:
	mov	P_COUNT[bp],ax		; save it locally for later
	mov	dh,ds:1[bx]		; get head #
	mov	cx,ds:3[bx]		; get cylinder #
	ror	ch,1
	ror	ch,1
	xchg	cl,ch
	or	cl,1			; start with sector 1
	mov	dl,es:UDSC_RUNIT[di]	; get ROS drive #
	lds	bx,REQUEST[bp]		; DS:BX -> Request Header
	mov	bx,ds:RH19_CATEGORY[bx]	; get major & minor function
	pop	ds

	push	es
	xor	ax,ax
	mov	es,ax
	mov	ax,new_int1e_off	; point floppy paramters at local
	xchg	ax,es:[4*1Eh]
	mov	orig_int1e_off,ax	; save old value
	mov	ax,new_int1e_seg
	xchg	ax,es:[4*1Eh+2]
	mov	orig_int1e_seg,ax
	pop	es

format30:
	cmp	bh,RQ19_FORMAT		; skip if verify only
	 jne	format40
	test	es:UDSC_FLAGS[di],UDF_HARD
	 jnz	format40		; hard disks are always verify

	mov	ax,P_COUNT[bp]
	mov	ah,ROS_FORMAT
	push	es
	push	bx
	push	ds
	pop	es
	mov	bx,CG:layout_table	; ES:BX -> parameter table
	int_____DISK_INT
	pop	bx
	pop	es
	 jc	format50
format40:				; no error on format, try verify
	mov	ax,P_COUNT[bp]
	mov	ah,ROS_VERIFY
	push	es
	push	bx
	xor	bx,bx
	mov	es,bx
	int_____DISK_INT
	pop	bx
	pop	es
	 jc	format50
	xor	ax,ax			; return success
format50:
	push	es
	push	di
	push	ax
	mov	ax,0
	mov	es,ax
	mov	di,78h
	mov	ax,orig_int1e_off
	stosw
	mov	ax,orig_int1e_seg
	stosw
	pop	ax
	pop	di
	pop	es
	 jnc	format60		; if no error's just exit
	call	xlat_error		; translate to DOS error
	dec	P_RETRY[bp]		; any more retries ?
	 jz	format60		; no, just exit with error
;	mov	ah,ROS_RESET
	xor	ax,ax
	int_____DISK_INT		; reset the drive
	jmp	format_retry		; now give it another go
format60:
	ret


;	The following table indicates which combinations of drive
;	types, sectors per track and tracks per disk are O.K. and
;	which value in AL is required for those combinations  for
;	INT 13h, AH = 17h ("set DASD type for format").

;			+----------------------	0 = 360Kb, 1 = 1.2Mb, 2 = 720Kb
;			|   +------------------	# of sectors/track (9, 15, 18)
;			|   |  +---------------	# of tracks per disk (40 or 80)
;			|   |  |   +-----------	1 = 360 Kb in 360 Kb
;			|   |  |   |		2 = 360 Kb in 1.2 Mb
;			|   |  |   |		3 = 1.2 Mb in 1.2 Mb
;			|   |  |   |  		4 = 720 Kb in 720 Kb
;			|   |  |   |  +--------	gap length for format
;			|   |  |   |  |
;			V   V  V   V  V

ok_fmt_table	db	0,  9, 40, 1, 50h	; 360 Kb
		db	1,  9, 40, 2, 50h	; 360 Kb in 1.2 Mb
		db	1, 15, 80, 3, 54h	; 1.2 Mb in 1.2 Mb
		db	2,  9, 80, 4, 50h	; 720 Kb in 720 Kb
		db	-1			; end of table

set_format:
;----------
; On Entry:
;	ES:DI -> UDSC_
; On Exit:
;	AL = 0 on success, else value to return in parameter block
;	ES:DI preserved
;
	push	ds
	call	point_ioctl_packet	; DS:BX -> ioctl packet
	mov	dh,ds:1[bx]		; get the head number
	mov	cx,ds:3[bx]		; get the cylinder number
	pop	ds

	mov	si,CG:layout_table	; SI -> track layout table
	mov	ax,MAX_SPT		; AX = # of sectors per track
set_format10:
	mov	0[si],cl		; set cylinder number
	mov	1[si],dh		; set head number
	add	si,4			; next sector entry
	dec	ax			; count down # of sectors
	 jnz	set_format10		; repeat until all done

	call	get_ncyl		; return # of tracks
	dec	ax			; AX = max. cylinder #
	ror	ah,1
	ror	ah,1			; move bits 8,9 into 6,7
	xchg	al,ah
	mov	cx,es:UDSC_BPB+BPB_SPT[di]
					; get desired sectors/track
	or	cx,ax			; CL, CH = max. cylinder/max. sector #
	cmp	cx,2708h		; check for 40 track, 8 sectors/track
	 jne	set_format20		; we convert 160, 320 to 180, 360
	inc	cx			; make it 9 sectors per track
set_format20:
	mov	dl,es:UDSC_RUNIT[di]	; get ROS unit number
	pushx	<es, di>
	mov	ah,ROS_SETMEDIA		; set type for format
	int_____DISK_INT		; check if combination is legal
	mov	new_int1e_off,di
	mov	new_int1e_seg,es	; ES:DI -> new parameters if legal
	popx	<di, es>
	 jc	set_format40		; did we succeed ?
set_format30:
	xor	ax,ax			; success, return no errors
	ret

set_format40:
; ROM BIOS has given an error, if the function isn't supported drop
; thru' and try the older method's
;
	mov	al,2			; assume ROS doesn't support it
	cmp	ah,0Ch			; media combination not supported ?
	 je	set_format80		; return AL=2
	inc	ax			; AL = 3
	cmp	ah,80h			; drive not ready ?
	 je	set_format80		; return AL=3

; Lets look for a match in our tables

	call	get_ncyl		; AX = number of cylinders
	mov	cx,es:UDSC_BPB+BPB_SPT[di]
					; CL = sectors per track
	mov	ch,al			; CH = tracks per disk
	cmp	cx,2808h		; 40 tracks, 8 sectors?
     jne    set_format50        
	inc	cx			; force it to 9 sectors/track
set_format50:
	mov	si,CG:ok_fmt_table-4
set_format60:
	add	si,4			; next table entry
	lods	cs:byte ptr [si]	; get drive type
	cmp	al,0FFh			; end of device/media list?
	 je	set_format70		; yes, can't handle this combination
	cmp	al,es:UDSC_TYPE[di]	; does the drive type match?
	 jne	set_format60		; try next one if wrong drive
	cmp	cx,cs:[si]		; do tracks/sectors match?
	 jne	set_format60		; no, try next one

	mov	parms_spt,cl		; set sectors/track
	mov	al,cs:3[si]		; get required gap length from table
	mov	parms_gpl,al		; set gap length for format
	mov	ax,CG:local_parms
	mov	new_int1e_off,ax	; use local parameters for formatting
	mov	new_int1e_seg,ds	; set new interrupt vector address
	mov	dl,es:UDSC_RUNIT[di]
	mov	al,cs:2[si]		; get media/drive combination
	mov	ah,ROS_SETTYPE		; set the drive type
	int_____DISK_INT
	 jnc	set_format30		; return if no errors
	cmp	es:UDSC_TYPE[di],0	; is this a 360 K drive?
	 je	set_format30		; go ahead, might be old ROS
	cmp	es:UDSC_TYPE[di],2	; is this a 720 K drive?
	 je	set_format30		; go ahead, might be old ROS
set_format70:
	mov	al,1			; return not supported
set_format80:
	ret


get_ncyl:
;--------
	mov	ax,es:UDSC_BPB+BPB_TOTSEC[di]
	xor	dx,dx			; get sectors on disk
	test	ax,ax			; zero means we use 32 bit value
	 jnz	get_ncyl10
	mov	ax,es:word ptr (UDSC_BPB+BPB_SIZE)[di]
	mov	dx,es:word ptr (UDSC_BPB+BPB_SIZE+2)[di]
get_ncyl10:
	div	es:UDSC_BPB+BPB_SPT[di]	; AX = # of cylinders * heads
	call	get_ncyl20		; round up
	div	es:UDSC_BPB+BPB_HEADS[di]; AX = # of cylinders
get_ncyl20:
	test	dx,dx			; do we have overflow ?
	 jz	get_ncyl30
	inc	ax			; round up
	xor	dx,dx			; make it a 32 bit value
get_ncyl30:
	ret


ioctl_getmedia:
;--------------
	mov	P_ROSCMD[bp],ROS_READ	; read from floppy/hard disk
	call	rw_media		; read the boot sector
	 jc	getmedia10
	push	es
	push	di
	push	ds
	call	point_ioctl_packet	; DS:BX -> ioctl packet
	push	ds
	pop	es
	lea	di,2[bx]		; ES:DI -> skip info word
	pop	ds			; DS:SI -> boot sector media id
	mov	cx,4+11+8
	rep	movsb			; copy the boot sector image
	pop	di
	pop	es
	xor	ax,ax
getmedia10:
	ret


ioctl_setmedia:
;--------------
	mov	P_ROSCMD[bp],ROS_READ	; read from floppy/hard disk
	call	rw_media		; read the boot sector
	 jc	setmedia10
	push	ds
	push	si
	push	es
	push	di
	push	ds
	push	si
	call	point_ioctl_packet	; DS:BX -> ioctl packet
	lea	si,2[bx]		; DS:SI -> skip info word
	pop	di
	pop	es			; ES:DI -> boot sector image
	mov	cx,4+11+8
	rep	movsb			; update the boot sector image
	pop	di
	pop	es
	pop	si
	pop	ds
	mov	P_ROSCMD[bp],ROS_WRITE	; write to floppy/hard disk
	jmp	rw_media		; write the boot sector
setmedia10:
	ret

rw_media:
;--------
; On Entry:
;	ES:DI -> UDSC
; On Exit:
;	ES:DI preserved
;	CY clear, SI -> boot record info
;	CY set on error, AX = error code
;
; setup parameters to read/write boot sector to/from local buffer
;
	call	ask_for_disk		; make sure we've got correct floppy
	mov	P_DMAOFF[bp],CG:local_buffer
	mov	P_DMASEG[bp],ds		; set transfer address
	mov	P_COUNT[bp],1		; read 1 sector
	mov	ax,es:UDSC_BPB+BPB_SPT[di]
	mul	es:UDSC_BPB+BPB_HEADS[di]; get sectors per track * heads
	xchg	ax,cx			; CX = sectors per cylinder
	mov	ax,es:word ptr (UDSC_BPB+BPB_HIDDEN)[di]
	mov	dx,es:word ptr (UDSC_BPB+BPB_HIDDEN+2)[di]
	div	cx			; AX = cylinder #, DX = head/sec offset
	mov	P_CYL[bp],ax		; save physical cylinder number
	xor	ax,ax			; make remainder 32 bit so
	xchg	ax,dx			; DX:AX = (head # * SPT) + sector #
	div	es:UDSC_BPB+BPB_SPT[di]	; divide by sectors per track
	mov	P_SECTOR[bp],dl		; DX = sector #, AX = head #
	mov	P_HEAD[bp],al		; save physical sector/head for later
	call	rw_loop			; read the boot sector
	 jc	rw_media20
	cmp	local_buffer+11+BPB_FATID,0F0h
	 jb	rw_media10
	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	rw_media20		; no, well we can't write a new one
rw_media10:
	mov	ax,RHS_ERROR+3		; "unknown command"
rw_media20:
	ret


dd_getdev:	; 23-get logical drive
;---------
;	get logical drive that corresponds to the physical drive
	call	point_unit		; get unit descriptor
	call	get_owner		; DL = owning drive (zero not owned)
	jmps	dd_setdev10		; return the owner


dd_setdev:	; 24-set logical drive
;---------
;	set logical drive that corresponds to the physical drive
;
	call	point_unit		; get unit descriptor
	call	set_owner		; set new owner
dd_setdev10:
	les	bx,REQUEST[bp]
	mov	es:RH_UNIT[bx],dl	; return current logical drive
	xor	ax,ax
	ret

get_owner:
;---------
; On Entry:
;	ES:DI -> UDSC_
; On Exit:
;	DL = owning drive (zero = no owner)
;
	xor	dx,dx			; assume one unit per physical drive
	mov	ax,es:UDSC_FLAGS[di]
	test	ax,UDF_HARD
	 jnz	get_owner40
	test	ax,UDF_VFLOPPY
	 jz	get_owner40
	push	ds
	mov	ds,dx			; DS -> low memory
		Assume	DS:IVECT
    mov dl,dual_byte        
	pop	ds
		Assume	DS:CGROUP
	mov	al,es:UDSC_RUNIT[di]	; lets look for this ROS drive
	test	al,al			; is it physical unit zero ?
	 jz	get_owner30		; yes, return dual_byte
	push	ds			; no, search our internal info
	lds	si,udsc_root
		Assume	DS:Nothing
get_owner10:
	cmp	al,ds:UDSC_RUNIT[si]	; do we use the same drive ?
	 jne	get_owner20
	test	ds:UDSC_FLAGS[si],UDF_OWNER
	 jz	get_owner20		; do we own it ?
	mov	dl,ds:UDSC_DRIVE[si]	; get the logical drive owner
get_owner20:
	lds	si,ds:UDSC_NEXT[si]
	cmp	si,0FFFFh		; try the next drive
	 jne	get_owner10
	pop	ds
		Assume	DS:CGROUP
get_owner30:
	inc	dx			; make drive one based
get_owner40:
	ret

set_owner:

⌨️ 快捷键说明

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