📄 disk.asm
字号:
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 + -