Implement map-like sector access for floppy drives
This commit is contained in:
parent
8c3d61e68d
commit
e096745c13
@ -31,8 +31,17 @@ print_banner: mov si, banner
|
||||
|
||||
call dskrst
|
||||
|
||||
mov bx, testfcb
|
||||
call fcbfst
|
||||
mov dl, [defdrv]
|
||||
call logdrv
|
||||
|
||||
xor ax, ax
|
||||
xor dx, dx
|
||||
call maprd
|
||||
|
||||
inc word [dskbuf+0x82]
|
||||
|
||||
call dirty
|
||||
call flush
|
||||
|
||||
hlt: hlt
|
||||
jmp hlt
|
||||
|
183
kernel/drive.asm
183
kernel/drive.asm
@ -1,10 +1,25 @@
|
||||
; code for disk i/o
|
||||
; from outside, only the following methods are meant to be called:
|
||||
; - logdrv: select drive DL to operate on
|
||||
; - map*: map sector DX:AX into dskbuf
|
||||
; - dirty: inform that dskbuf has been written to
|
||||
; access is done by accessing dskbuf directly
|
||||
|
||||
section .bss
|
||||
|
||||
; drive actually selected for I/O
|
||||
dsknum: resb 1
|
||||
|
||||
; bios drive we end up using
|
||||
biosnum: resb 1
|
||||
|
||||
; current sector number
|
||||
; absolute, ignores partition
|
||||
dskseek: resd 1
|
||||
|
||||
; bit 0 - dirty flag for dskbuf
|
||||
dskflag: resb 1
|
||||
|
||||
; disk buffer for I/O operations
|
||||
dskbuf: resb 512
|
||||
|
||||
@ -13,69 +28,6 @@ bpb: resb BPBSIZ4
|
||||
|
||||
section .text
|
||||
|
||||
ret: ret
|
||||
|
||||
; Convert drive number into DL for int 13h
|
||||
; A=0, B=1, C=0x80
|
||||
; IN dl dos drive number
|
||||
; OUT dl bios drive number
|
||||
getdl: cmp dl, 2
|
||||
jc ret
|
||||
mov dl, 0x80
|
||||
ret
|
||||
|
||||
; Ask BIOS for drive parameters
|
||||
; IN dl dos drive number
|
||||
; OUT CX,DH chs data
|
||||
; ES:DI DPT if floppy
|
||||
qrychs: mov ah, 8
|
||||
les di, [0x1E*4]
|
||||
int 0x13
|
||||
jc .defs
|
||||
test cl, cl
|
||||
jz .defs
|
||||
ret
|
||||
|
||||
.defs: mov cx, 0x2709 ; max track = 39, max sec = 9
|
||||
mov dh, 1 ; 2 heads
|
||||
ret
|
||||
|
||||
; select drive
|
||||
; IN dl drive number
|
||||
dsksel: cmp dl, byte [dsknum]
|
||||
je ret
|
||||
|
||||
call dskrst
|
||||
|
||||
call getdl
|
||||
push dx
|
||||
call qrychs
|
||||
|
||||
; store CHS data in BPB
|
||||
xor ax, ax
|
||||
mov al, cl
|
||||
mov [bpb+BPBSPT], ax
|
||||
mov al, dh
|
||||
inc ax
|
||||
mov [bpb+BPBNOS], ax
|
||||
|
||||
; get dpt from bios if not hdd
|
||||
pop dx
|
||||
test dl, 0x80
|
||||
jnz .nodpt
|
||||
push dx
|
||||
mov dx, dpt
|
||||
mov bx, di
|
||||
mov cx, DPTSIZE
|
||||
call lod
|
||||
mov ax, [bpb+BPBSPT]
|
||||
mov [dpt+DPTSPT], al
|
||||
pop dx
|
||||
.nodpt:
|
||||
|
||||
|
||||
ret
|
||||
|
||||
dskrst: call flush
|
||||
mov ax, 0xFFFF
|
||||
mov [dsknum], al
|
||||
@ -83,5 +35,108 @@ dskrst: call flush
|
||||
mov [dskseek+2], ax
|
||||
ret
|
||||
|
||||
; log in drive
|
||||
; currently only supports 18 sectors 2 heads floppies
|
||||
; IN dl drive number
|
||||
logdrv: mov [biosnum], dl
|
||||
xor ax, ax
|
||||
xor dx, dx
|
||||
call read
|
||||
|
||||
; copy bios parameter block
|
||||
lea si, [dskbuf+BPBOFF]
|
||||
mov di, bpb
|
||||
mov cx, BPBSIZ4
|
||||
rep movsb
|
||||
|
||||
; make sure partition offset is force zero
|
||||
xor ax, ax
|
||||
mov [bpb+BPBHS], ax
|
||||
mov [bpb+BPBHS+2], ax
|
||||
|
||||
ret
|
||||
|
||||
calchs: mov bx, (18*2)
|
||||
; dx:ax = linear count, bx = sectors / cylinder
|
||||
div bx
|
||||
xchg ax, dx
|
||||
; dx = cylinder, ax = head * spt + sector
|
||||
mov bl, 18
|
||||
div byte bl
|
||||
; dx = cylinder, al = head, ah = sector
|
||||
xchg dl, dh
|
||||
ror dl, 1
|
||||
ror dl, 1
|
||||
or dl, ah
|
||||
inc dx
|
||||
; al: head number
|
||||
; dh bit 0-7: cylinder bits 0-7
|
||||
; dl bit 0-5: sector bits 0-5
|
||||
; dl bit 6-7: cylinder bits 8-9
|
||||
mov cx, dx
|
||||
mov dh, al
|
||||
mov dl, [biosnum]
|
||||
mov bx, dskbuf
|
||||
ret
|
||||
|
||||
mapclu: ; counting from begin of cluster area
|
||||
mov bx, [bpb+BPBRDE]
|
||||
mov cl, 4
|
||||
shr bx, cl ; 32 bytes per entry
|
||||
add ax, bx
|
||||
adc dx, 0
|
||||
maprd: ; counting from beginning of dir
|
||||
; add fat table sizes
|
||||
xor ch, ch
|
||||
mov cl, byte [bpb+BPBFN]
|
||||
.loop: add ax, [bpb+BPBFS]
|
||||
adc dx, 0
|
||||
loop .loop
|
||||
mapfat: ; counting from beginning of FAT
|
||||
; add reserved sector count
|
||||
add ax, [bpb+BPBRSC]
|
||||
adc dx, 0
|
||||
map: ; count from partition start
|
||||
;add ax, [BPBHS]
|
||||
;add dx, [BPBHS+2]
|
||||
; absolute sector count
|
||||
mapabs: call read
|
||||
ret
|
||||
|
||||
; hard read, absolute disk offset
|
||||
; TODO: retries on error
|
||||
; IN dx:ax
|
||||
read: ; flush previous data if necessary
|
||||
push ax
|
||||
push dx
|
||||
call flush
|
||||
pop dx
|
||||
pop ax
|
||||
; store the sector number
|
||||
mov [dskseek], ax
|
||||
mov [dskseek+2], dx
|
||||
; do the actual read
|
||||
; TODO: error handling & retries
|
||||
call calchs
|
||||
mov ax, 0x0201
|
||||
int 0x13
|
||||
ret
|
||||
|
||||
; mark dskbuf as containing unwritten changes
|
||||
dirty: or byte [dskflag], 1 ; dirty
|
||||
ret
|
||||
|
||||
; flush buffer if dirty
|
||||
flush: ret
|
||||
flush: test byte [dskflag], 1
|
||||
jz .ret
|
||||
; load sector number
|
||||
mov ax, [dskseek]
|
||||
mov dx, [dskseek+2]
|
||||
; do the write
|
||||
; TODO: error handling & retries
|
||||
call calchs
|
||||
mov ax, 0x0301
|
||||
int 0x13
|
||||
; remove dirty flag
|
||||
and byte [dskflag], 0xFE
|
||||
.ret: ret
|
||||
|
@ -17,7 +17,7 @@ setdrv: mov dl, [es:bx+fcb.drive] ; A=1
|
||||
mov [es:bx+fcb.drive], dl ; A=1
|
||||
; now set as current i/o drive
|
||||
.nofix: dec dl ; A=0 for dsksel
|
||||
jmp dsksel
|
||||
jmp logdrv
|
||||
|
||||
; FCB open
|
||||
fcbopn: ; call fcbfst
|
||||
|
Loading…
Reference in New Issue
Block a user