Implement map-like sector access for floppy drives

This commit is contained in:
Nero 2020-12-15 23:29:35 +00:00
parent 8c3d61e68d
commit e096745c13
3 changed files with 131 additions and 67 deletions

View File

@ -31,8 +31,17 @@ print_banner: mov si, banner
call dskrst call dskrst
mov bx, testfcb mov dl, [defdrv]
call fcbfst call logdrv
xor ax, ax
xor dx, dx
call maprd
inc word [dskbuf+0x82]
call dirty
call flush
hlt: hlt hlt: hlt
jmp hlt jmp hlt

View File

@ -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 section .bss
; drive actually selected for I/O ; drive actually selected for I/O
dsknum: resb 1 dsknum: resb 1
; bios drive we end up using
biosnum: resb 1
; current sector number ; current sector number
; absolute, ignores partition
dskseek: resd 1 dskseek: resd 1
; bit 0 - dirty flag for dskbuf
dskflag: resb 1
; disk buffer for I/O operations ; disk buffer for I/O operations
dskbuf: resb 512 dskbuf: resb 512
@ -13,69 +28,6 @@ bpb: resb BPBSIZ4
section .text 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 dskrst: call flush
mov ax, 0xFFFF mov ax, 0xFFFF
mov [dsknum], al mov [dsknum], al
@ -83,5 +35,108 @@ dskrst: call flush
mov [dskseek+2], ax mov [dskseek+2], ax
ret 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 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

View File

@ -17,7 +17,7 @@ setdrv: mov dl, [es:bx+fcb.drive] ; A=1
mov [es:bx+fcb.drive], dl ; A=1 mov [es:bx+fcb.drive], dl ; A=1
; now set as current i/o drive ; now set as current i/o drive
.nofix: dec dl ; A=0 for dsksel .nofix: dec dl ; A=0 for dsksel
jmp dsksel jmp logdrv
; FCB open ; FCB open
fcbopn: ; call fcbfst fcbopn: ; call fcbfst