📄 disk.asm
字号:
;---------
; On Entry:
; ES:DI -> UDSC_
; On Exit:
; ES:DI preserved
; 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 set_owner40
test ax,UDF_VFLOPPY
jz set_owner40
mov al,es:UDSC_DRIVE[di]
mov ah,es:UDSC_RUNIT[di] ; get ROS unit
test ah,ah ; is it unit zero ?
jnz set_owner10
push ds
mov ds,dx ; DS -> low memory
Assume DS:IVECT
mov dual_byte,al ; set dual drive support byte
pop ds
Assume DS:CGROUP
set_owner10:
push ds
lds si,udsc_root
Assume DS:Nothing
set_owner20:
cmp ah,ds:UDSC_RUNIT[si] ; does this unit use the same drive ?
jne set_owner30
or ds:UDSC_FLAGS[si],UDF_UNSURE+UDF_OWNER
cmp al,ds:UDSC_DRIVE[di]
je set_owner30
and ds:UDSC_FLAGS[si],not UDF_OWNER
set_owner30:
lds si,ds:UDSC_NEXT[si]
cmp si,0FFFFh ; end of the line ?
jne set_owner20
pop ds
Assume DS:CGROUP
xchg ax,dx ; DL = owning drive
inc dx ; make it one based
set_owner40:
ret
ask_for_disk: ; make sure the right disk is in the floppy drive
;------------
call get_owner ; DL = owning drive
dec dx ; make DL zero based
js askfdsk30 ; stop if not a logical drive
mov dh,es:UDSC_DRIVE[di] ; DH = new drive, DL = old drive
cmp dl,dh ; do we own the drive ?
je askfdsk30 ; yes, stop now
push dx ; save for broadcast
mov dl,dh ; new owner in DL
call set_owner ; we are now the owner
push es
push di
push cs
call FullScreen
pop di
pop es
pop dx
mov ax,4A00h ; should we prompt ?
xor cx,cx
int 2Fh ; lets ask
inc cx ; CX = FFFF ?
jcxz askfdsk30 ; then skip prompt
ifdef JAPAN
mov ax,5001h ; get adaptor mode
int VIDEO_INT ; ..
cmp bx,81 ; japanese mode ?
mov si,CG:disk_msgA_jpn ; get message to print for Japanese
je askfdsk10 ; yes
endif
mov si,CG:disk_msgA ; get message to print
askfdsk10:
call WriteASCIIZ ; output the string
mov al,es:UDSC_DRIVE[di] ; get drive letter for new drive
add al,'A'
dec si ; point to NUL
call WriteNext ; output char, stop at NUL
ifdef JAPAN
mov ax,5001h ; get adaptor mode
int VIDEO_INT ; ..
cmp bx,81 ; japanese mode ?
mov si,CG:disk_msgB_jpn ; get message to print for Japanese
je askfdsk20 ; yes
endif
mov si,CG:disk_msgB ; get message to print
askfdsk20:
call WriteASCIIZ ; output the string
mov ah,0 ; wait for any key to be pressed
int KEYBOARD_INT ; read one key from keyboard
askfdsk30:
ret ; we've got the right drive
WriteNext:
int 29h ; output via fastconsole entry
WriteASCIIZ:
lods cs:byte ptr [si] ; get next char
test al,al
jnz WriteNext ; stop at NUL
ret
FullScreen:
xor di,di
mov es,di
mov ax,1684h ; get the entry point
mov bx,21 ; for DOSMGR
int 2Fh
mov bx,es
or bx,di ; anyone there ?
jz FullScreen10
mov ax,1 ; yes, go full screen please
push es ; fake a JMPF to ES:DI
push di
FullScreen10:
retf
driver endp
RCODE ends ; end of device driver code
page
ICODE segment 'ICODE' ; initialization code
Assume CS:CGROUP, DS:CGROUP, ES:Nothing, SS:Nothing
dd_init: ; 0-initialize driver
;-------
call hard_init ; setup hard disk units
call floppy_init ; setup floppy units
les bx,REQUEST[bp]
mov al,nunits ; get # of units installed
mov es:RH0_NUNITS[bx],al ; return value to the BDOS
mov NumDiskUnits,al ; also set it in device header
mov ax,endbios ; get pointer to last resident byte
mov es:RH0_RESIDENT[bx],ax ; set end of device driver
mov es:RH0_RESIDENT+2[bx],ds
mov ax,CG:bpbtbl
mov es:RH0_BPBOFF[bx],ax ; set BPB table array
mov es:RH0_BPBSEG[bx],ds
sub ax,ax ; initialization succeeded
ret ; (BIOS init always does...)
floppy_init:
;-----------
mov nunits,0 ; floppies start at drive A:
mov ah,ROS_RESET ; reset the disk system
xor dx,dx ; for NEAT hard disk boot bug
int_____DISK_INT
int EQUIPMENT_INT ; determine equipment status
mov cl,6
shr ax,cl ; shift down floppy bits
and ax,03h ; mask for floppy
inc ax ; correct 0 based code
mov nfloppy,al
cmp al,1 ; if there is only one floppy
jne equip_check_des ; then use 2 designators
inc ax ; this fakes a B: drive
equip_check_des:
mov cx,ax ; CX = # of units to set up
xor dx,dx ; DL = physical drive
equip_loop:
push cx
call new_unit ; ES:DI -> UDSC
mov es:UDSC_RUNIT[di],dl ; set physical drive (ROS code)
call floppy_type ; determine type, build default BPB
cmp nfloppy,1 ; do we only have single drive?
je equip_single ; yes, use same physical drive for all
inc dx ; else use new drive for each unit
equip_single: ; we only have one physical drive
call add_unit ; add ES:DI to list of UDSC_'s
pop cx
loop equip_loop ; repeat for all logical floppies
pushx <ds, es>
push ds ; DS -> i13_trap segment
mov di,ds
mov es,di
sub si,si
mov ds,si
lds si,78h[si]
mov di,CG:local_parms ; copy parameters to template
mov cx,11
rep movsb
pop es ; now ES -> i13_trap segment
Assume ES:CGROUP
sub ax,ax
mov ds,ax ; DS -> interrupt vectors
Assume DS:IVECT
mov ax,CG:Int2FTrap ; hook Int 2F
mov i2Foff,ax
mov i2Fseg,es
mov ax,CG:Int13Trap ; hook Int 13
xchg ax,i13off
mov es:i13off_save,ax
mov ax,es
xchg ax,i13seg
mov es:i13seg_save,ax
mov di,500h ; dual drive byte & friends live here
mov cx,20h/2 ; zero some bytes at 50h:0
sub ax,ax ; get a quick zero
mov es,ax ; ES:DI -> 0:500h
rep stosw ; setup dual drive byte & friends
Assume DS:CGROUP, ES:Nothing
popx <es, ds>
ret
floppy_type:
;-----------
; entry: DI -> unit descriptor
mov UDSC_TYPE[di],0 ; assume 360K 5.25" floppy
mov UDSC_NCYL[di],40 ; 40 tracks only
mov ah,ROS_GETTYPE ; "Read DASD type"
int_____DISK_INT ; find out if disk change line available
jc equip_no_chgline ; skip if function not supported
cmp ah,2 ; floppy with disk change line?
jne equip_no_chgline ; no, must be old 360K
or es:UDSC_FLAGS[di],UDF_CHGLINE
mov es:UDSC_TYPE[di],1 ; assume 1.2Mb floppy
mov es:UDSC_NCYL[di],80 ; 80 tracks
equip_no_chgline:
pushx <es, di, dx> ; save our registers
mov ah,ROS_PARAM ; read drive parameters
int_____DISK_INT ; find out floppy type
popx <dx, di, es>
jc equip_no_type ; skip if PC,XT,jr,AT before 10 Jan 84
dec bx ; make values 0 based
jns equip_type ; (CMOS invalid - type = 0)
xor bx,bx ; assume 360K
cmp ch,4fh ; is it 80 track ?
jne equip_no_type ; if not forget it
mov bl,1 ; BL = 1 (ie. 1.2M)
cmp cl,15 ; 15 spt ?
je equip_type
inc bx ; BL = 2 (ie. 720k)
cmp cl,9 ; 9 spt ?
je equip_type
inc bx ; BL = 3 (ie. 1.4M)
cmp cl,18 ; 18 spt ?
je equip_type
inc bx
inc bx ; BL = 5 (ie. 2.8M)
cmp cl,36 ; 36 spt ?
jne equip_no_type ; don't recognise anything
equip_type:
cmp bl,3 ; is it 1.44 Mb 3.5" type?
jb equip_type_ok ; skip if 360K, 1.2Mb, 720K (0, 1, 2)
mov bl,7 ; use reserved "Other" type
je equip_type_ok
inc bx ; else make it 2.88 Mb type 9
inc bx
equip_type_ok:
mov es:UDSC_TYPE[di],bl ; set the default drive type for format
equip_no_type:
mov al,es:UDSC_TYPE[di] ; AL = 0, 1, 2 or 7 (360/1.2/720/1.44)
cbw ; make it a word
xchg ax,si ; SI = drive type
shl si,1 ; SI = drive type * 2
mov si,bpbs[si] ; get default BPB for drive
cmp si,CG:bpb360 ; is this is a 360 K drive?
jne equip_360 ; skip if any other type
mov bpbtbl[bx],CG:bpb720 ; use larger default BPB
equip_360:
mov cx,UDSC_BPB_LENGTH ; CX = size of BPB
pushx <es, di, si, cx>
lea di,es:UDSC_BPB[di]
mov ax,ds
mov es,ax ; ES = DS
rep movsb ; make default BPB current BPB in UDSC
popx <cx, si, di, es>
pushx <es, di>
lea di,es:UDSC_DEVBPB[di]
rep movsb ; copy default BPB device BPB in UDSC
popx <di, es>
ret
page
LOG_PRIM equ 01h ; log in primary partitions
LOG_EXTD equ 02h ; log in extended partitions
log_flag dw LOG_PRIM ; scan for primary only initially
hard_init: ; setup all hard disk units
;---------
; mov log_flag,LOG_PRIM ; log in primary only initially
call hardi0 ; C: & D:
mov log_flag,LOG_EXTD ; log in extended only
; call hardi0
; ret
hardi0:
mov ah,ROS_PARAM ; get hard disk parameters
mov dl,80h
int_____DISK_INT ; get # of hard disks we have
jc hardi9 ; skip if hard disks not supported
test dl,dl ; test if any hard disks found
jz hardi9 ; skip if there weren't any
mov al,dl
cbw
xchg ax,cx ; CX = # of hard disks
mov dl,80h ; start with first hard disk
hardi1:
pushx <cx, dx> ; save drive count, physical drive
call login_hdisk ; find all partitions on hard disk
popx <dx, cx> ; restore physical drive, drive count
inc dx ; next physical hard disk
loop hardi1 ; next physical hard disk
hardi9: ; all hard disks done
ret
login_hdisk: ; find all partitions on a hard disk
;-----------
; entry: DL = 80h, 81h for 1st/2nd hard disk
push log_flag ; save state for next drive
mov p_unit,dl ; save physical drive
mov cx,0001h ; track 0, sector 1
mov dh,0 ; partition tables start on head 0
log_h1:
mov dl,p_unit ; get physical unit
call login_read_dx
jnc log_h1a
jmp log_h9 ; give up if disk error
log_h1a:
push cx
push dx
mov ah,ROS_PARAM
int_____DISK_INT ; return disk drive parameters
inc dh ; DH = number of heads
mov nhead,dh ; set # of heads on drive
and cl,3Fh ; isolate sector count
mov nsect,cl ; set sectors per track
pop dx
pop cx
;; cmp local_id,0AA55h
;; jne log_h9 ; give up if not initialized
test log_flag,LOG_PRIM ; scanning for primary?
jz log_h5 ; no, ignore all primary partitions
mov si,CG:local_pt ; point to partition table
log_h2:
;** SECURE PARTITIONS **
mov al,init_runit
test al,al ; booting from a hard disk ?
;** SECURE PARTITIONS **
mov al,4[si] ; get system ID
;** SECURE PARTITIONS **
jns log_h2a ; booting from a hard disk ?
mov ah,al ; yes, allow secure partitions
and ah,0F0h
cmp ah,SEC_ID
je log_h02
cmp ah,SEC_ID2
jne log_h2a
log_h02:
sub al,ah ; turn into a sensible partition ID
log_h2a:
;** SECURE PARTITIONS **
cmp al,DOS20_ID ; is this a DOS 2.x partition?
je log_h3 ; yes, try to log it in
cmp al,DOS30_ID ; is this a DOS 3.0/3.1/3.2 partition?
je log_h3 ; yes, try to log it in
cmp al,DOS331_ID ; is this a DOS 3.31/4.0 partition?
jne log_h4 ; skip if not a good partition
log_h3:
push si ; save partition table index
pushx <cx, dx> ; save partition table address
call login_primary ; login primary partition
popx <dx, cx> ; get partition table address
call login_read_dx ; re-read partition table
pop si ; get partition table index
jc log_h9 ; give up if error
log_h4:
add si,16 ; next partition table entry
cmp si,CG:local_id ; all partitions checked?
jb log_h2 ; loop back if more
log_h5: ; primary partitions done
test log_flag,LOG_EXTD ; scanning for extended?
jz log_h9 ; skip if no extended scan
or log_flag,LOG_PRIM ; scan for both types now
mov si,CG:local_pt ; SI -> partition table
; RG-01
log_h6:
;** SECURE PARTITIONS **
mov al,init_runit
test al,al ; booting from a hard disk ?
;** SECURE PARTITIONS **
mov al,4[si] ; get system ID
;** SECURE PARTITIONS **
jns log_h6a ; booting from a hard disk ?
mov ah,al ; yes, allow secure partitions
and ah,0F0h
cmp ah,SEC_ID
je log_sec2
cmp ah,SEC_ID2
jne log_h6a
log_sec2:
sub al,ah
log_h6a:
;** SECURE PARTITIONS **
cmp al,DOSEX_ID ; DOS 3.3 extended partition found?
jne log_h7
log_h6b:
mov dh,1[si] ; get head # for next table
mov cx,2[si] ; get cylinder, sector for next table
jmp log_h1 ; read & scan next partition table
log_h7: ; entry not an extended partition
add si,16 ; next partition table entry
cmp si,CG:local_buffer+IDOFF; all partitions checked?
jb log_h6 ; loop back if more
log_h9: ; drive login done
pop log_flag ; restore state for next drive
ret
login_primary:
;-------------
; entry: SI -> partition table entry
mov ax,12[si] ; get size of partition (low)
mov part_size,ax
mov ax,14[si] ; get size of partition (high)
mov part_size+2,ax
mov cl,2
mov bx,5[si] ; get last head/sector
and bx,1100000011000000b ; isolate cylinder bits 10..11,8..9
rol bl,cl ; bits 10..11 fr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -