drive i/o: improvements regarding reset and stack usage

- read and write now run in the same function, less branching
- implemented on-demand controller reset
- set up a function stub for int 0x13 for later stack switching
This commit is contained in:
Nero 2020-12-26 14:37:12 +00:00
parent 0a2a0e4659
commit 424e174523

View File

@ -17,7 +17,9 @@ biosnum: resb 1
; absolute, ignores partition ; absolute, ignores partition
dskseek: resd 1 dskseek: resd 1
; bit 0 - dirty flag for dskbuf ; bit 0 (1) - dirty flag for dskbuf
; bit 1 (2) - controller configured
; bit 2 (4) - EBIOS supported
dskflag: resb 1 dskflag: resb 1
; disk buffer for I/O operations ; disk buffer for I/O operations
@ -42,6 +44,13 @@ dinit: ; copy previously set DPT to our data area
mov word [4*0x1E+2], ds mov word [4*0x1E+2], ds
ret ret
; int 13 stub
; place reserved for stack switches
int13: ;int 3
int 0x13
;int 3
ret
; restore DPT to default values if possible ; restore DPT to default values if possible
; IN dl bios drive number ; IN dl bios drive number
rstdpt: mov ah, 8 rstdpt: mov ah, 8
@ -109,35 +118,6 @@ logdrv: ; dont do anything if drive already selected
mov [bpb+BPBHS+2], ax mov [bpb+BPBHS+2], ax
.ret: ret .ret: ret
calchs: ; put sectors per cylinder into bx
mov ax, [bpb+BPBSPT]
mul word [bpb+BPBNOS]
mov bx, ax
; put linear sector num into dx:ax
mov ax, [dskseek]
mov dx, [dskseek+2]
; dx:ax = linear count, bx = sectors / cylinder
div bx
xchg ax, dx
; dx = cylinder, ax = head * spt + sector
mov bl, [bpb+BPBSPT]
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 mapclu: ; counting from begin of cluster area
mov bx, [bpb+BPBRDE] mov bx, [bpb+BPBRDE]
mov cl, 4 mov cl, 4
@ -175,10 +155,66 @@ read: push ax
mov [dskseek], ax mov [dskseek], ax
mov [dskseek+2], dx mov [dskseek+2], dx
; do the actual read ; do the actual read
; TODO: error handling & retries
call calchs ; set the operation code and back it up to the stack
mov ax, 0x0201 _read: mov ch, 2
int 0x13 db 0x3D ; cmp ax, imm16: causes next instr to be skipped
_write: mov ch, 3
mov cl, 1 ; read len
; TODO: do ebios i/o
; check if we can skip controller reset
test byte [dskflag], 2
jnz .l01
; do controller reset
mov dl, [biosnum]
mov ah, 0
call int13
or byte [dskflag], 2
.l01: ; put sectors per cylinder into bx
mov ax, [bpb+BPBSPT]
mul word [bpb+BPBNOS]
mov bx, ax
; put linear sector num into dx:ax
mov ax, [dskseek]
mov dx, [dskseek+2]
; dx:ax = linear count, bx = sectors / cylinder
div bx
xchg ax, dx
; dx = cylinder, ax = head * spt + sector
mov bl, [bpb+BPBSPT]
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
; shuffle values around for bios
xchg ax, cx
xchg cx, dx
xchg dh, dl
mov dl, [biosnum]
mov bx, dskbuf
; ah: subfunction selected via cx previously
; al: 1 = reading 1 sector
; cx: sector and cylinder number
; dh: head number
; dl: drive number
; bx: offset to disk buffer
call int13
jc .err
; clear dirty flag on success
and byte [dskflag], 0xFE
clc
ret
.err: ; assume controller is misconfigured
and byte [dskflag], 0xFD
; exit with carry flag set
stc
ret ret
; mark dskbuf as containing unwritten changes ; mark dskbuf as containing unwritten changes
@ -188,11 +224,6 @@ dirty: or byte [dskflag], 1 ; dirty
; flush buffer if dirty ; flush buffer if dirty
flush: test byte [dskflag], 1 flush: test byte [dskflag], 1
jz .ret jz .ret
; do the write
; TODO: error handling & retries ; TODO: error handling & retries
call calchs jmp _write
mov ax, 0x0301
int 0x13
; remove dirty flag
and byte [dskflag], 0xFE
.ret: ret .ret: ret