Workstate on disk I/O rework

This commit is contained in:
Nero 2021-12-16 12:27:23 +00:00
parent 79a86bad49
commit e26adff688
2 changed files with 88 additions and 82 deletions

View File

@ -1,6 +1,7 @@
cpu 8086 cpu 8086
%define seg 0x060 %define seg 0
%define off 0x700
org 0x7C00 - (seg << 4) org 0x7C00 - (seg << 4)
@ -16,24 +17,12 @@ init: cli
.retry: mov ax, 0x0208 .retry: mov ax, 0x0208
mov cx, 2 mov cx, 2
mov dh, 0 mov dh, 0
mov bx, 0x100 mov bx, off
int 0x13 int 0x13
jc .retry jc .retry
xor di, di jmp seg:off
mov ax, 0x18CD
stosw
int 0x12
mov cl, 6
shl ax, cl
stosw
mov al, 2
stosb
mov ax, 0x18CD
stosw
jmp seg:0x100
times (0x1BE - ($-$$)) db 0 times (0x1BE - ($-$$)) db 0

View File

@ -1,15 +1,15 @@
org 0x700
cseg equ 0x0
jmp init jmp init
%include "bpb.inc" %include "bpb.inc"
%include "farptr.inc" %include "farptr.inc"
; drive actually selected for I/O ; dflags bitfields
dsknum db 0xFF DRVLOG equ 0x01 ; bit 0 (1) - drive logged in (see drvnum)
DRVRST equ 0x02 ; bit 1 (2) - controller configured
dap db 0x10, 0 DRVEXT equ 0x04 ; bit 2 (4) - EBIOS supported
dw 1 DIRTY equ 0x08 ; bit 3 (8) - dskbuf dirty
dapbuf dw dskbuf, 0
dskseek dw 0,0,0,0
; initial setup for disk i/o ; initial setup for disk i/o
; copy previously set DPT to our data area ; copy previously set DPT to our data area
@ -23,8 +23,6 @@ dinit xor ax, ax
mov es, cx mov es, cx
mov word [es:4*0x1E], dpt mov word [es:4*0x1E], dpt
mov word [es:4*0x1E+2], ds mov word [es:4*0x1E+2], ds
; set segment addr in DAP
mov [dapbuf+2], cs
ret ret
align 16 align 16
@ -36,6 +34,8 @@ i13isp jmp short int13i
iret iret
align 16 align 16
; Entry point when user program calls int13h
; TODO: flush buffer and log out drive
int13i call int13 int13i call int13
iret iret
@ -86,7 +86,7 @@ getprm test byte [dskflag], 4
; select a drive for io ; select a drive for io
; IN dl drive number ; IN dl drive number
; dont do anything if drive already selected ; dont do anything if drive already selected
select cmp dl, [dsknum] select cmp dl, [drvnum]
je logfdd.ret je logfdd.ret
; clear out current contents ; clear out current contents
push dx push dx
@ -140,7 +140,7 @@ loghdd sub dl, 2
sbb bx, 0xAA55 sbb bx, 0xAA55
jnz .chs jnz .chs
; enable ebios and assume controller is configured ; enable ebios and assume controller is configured
or byte [dskflag], (2+4) or byte [dflags], DRVCTL | DRVEXT
; get chs data (needed or we cant load vbr) ; get chs data (needed or we cant load vbr)
.chs call getprm .chs call getprm
; read mbr ; read mbr
@ -181,74 +181,68 @@ logerr stc
ret ret
; map sector into dskbuf ; map sector into dskbuf
; sector number from partition start
; IN dx:ax sector number
map add ax, [bpb+BPBHS]
add dx, [bpb+BPBHS+2]
; absolute sector count
; skip doing a read if sector number matches ; skip doing a read if sector number matches
; IN dx:ax sector number ; IN dx:ax absolute sector number
mapabs cmp ax, [dskseek] map cmp ax, [drvseek]
jne l003 jne .do
cmp dx, [dskseek+2] cmp dx, [drvseek+2]
je l002 jne .do
; flush and read other sector ret
l003 push ax ; flush previous contents
.do push ax
push dx push dx
call flush call flush
pop dx pop dx
pop ax pop ax
; store the sector number ; set sector number
mov [dskseek], ax mov [drvseek], ax
mov [dskseek+2], dx mov [drvseek+2], dx
jmp _read ; issue read cmd
mov ch, 2
jmp diskio
; mark dskbuf as containing unwritten changes ; mark dskbuf as containing unwritten changes
dirty or byte [cs:dskflag], 1 ; dirty dirty or word [cs:dflags], DIRTY
l002 ret l002 ret
; flush buffer if dirty ; flush buffer if dirty
flush test byte [cs:dskflag], 1 flush test word [cs:dflags], DIRTY
jz l002 jz l002
; low level read and write ; issue write cmd
; call again to retry, no input registers mov ch, 3
; read or write is configured in cx
_write mov ch, 3 ; Do disk I/O
db 0x3D ; cmp ax, imm16: causes next 2 bytes to be skipped ; IN ch 2 = read
_read mov ch, 2 ; 3 = write
mov cl, 1 ; read len ; Sector number is read from [drvseek]
diskio mov cl, 1 ; read len
; DS := ES := CS ; DS := ES := CS
mov ax, cs call rstseg
mov ds, ax
mov es, ax
; check if ebios supported ; check if ebios supported
test byte [dskflag], 4 test word [dflags], DRVEXT
jz .l00 jz .noext
; set up regs for ebios call
mov ax, cx mov ax, cx
or ah, 0x40 or ah, 0x40
mov si, dap mov si, dap
jmp .do jmp .do
; check if we can skip controller reset ; check if we can skip controller reset
.l00 test byte [dskflag], 2 .noext test word [dflags], DRVRST
jnz .l01 jnz .norst
; do controller reset ; do controller reset
mov dl, [biosnum] mov dl, [biosnum]
mov ah, 0 mov ah, 0
call int13 call int13
or byte [dskflag], 2 or word [dflags], DRVRST
; put sectors per cylinder into bx
.l01 mov ax, [bpb+BPBSPT]
mul word [bpb+BPBNOS]
mov bx, ax
; put linear sector num into dx:ax ; put linear sector num into dx:ax
mov ax, [dskseek] .norst mov ax, [drvseek]
mov dx, [dskseek+2] mov dx, [drvseek+2]
; dx:ax = linear count, bx = sectors / cylinder ; dx:ax = linear count
div bx div word [drvspc]
; TODO: is it possible to get an overflow here?
xchg ax, dx xchg ax, dx
; dx = cylinder, ax = head * spt + sector ; dx = cylinder, ax = head * spt + sector
mov bl, [bpb+BPBSPT] div byte [drvspt]
div byte bl
; dx = cylinder, al = head, ah = sector ; dx = cylinder, al = head, ah = sector
xchg dl, dh xchg dl, dh
ror dl, 1 ror dl, 1
@ -274,34 +268,57 @@ _read mov ch, 2
call int13 call int13
jc .err jc .err
; clear dirty flag on success ; clear dirty flag on success
and byte [dskflag], 0xFE and word [dflags], ~DIRTY
clc clc
ret ret
; assume controller is misconfigured ; assume controller is misconfigured
.err and byte [dskflag], 0xFD .err and word [dflags], ~DRVRST
; exit with carry flag set ; exit with carry flag set
stc stc
ret ret
init mov ax, 0x0e38 init mov ax, cs
int 0x10 ; boot failure if loaded wrong
cmp ax, cseg
je $+4
int 0x18
halt hlt halt hlt
jmp halt jmp halt
section .bss dap db 0x10, 0
dw 1
dw dskbuf, cseg
drvseek dw 0,0,0,0
; bios drive we end up using ; bit 0 (1) - drive logged in (see drvnum)
biosnum resb 1
; bit 0 (1) - dirty flag for dskbuf
; bit 1 (2) - controller configured ; bit 1 (2) - controller configured
; bit 2 (4) - EBIOS supported ; bit 2 (4) - EBIOS supported
dskflag resb 1 ; bit 3 (8) - dskbuf dirty
dflags dw 0
dpt resb 11 section .bss
bpb resb BPBSIZ ; drive currently logged in
drvnum resb 1
; number, just for bios
biosnum resb 1
; DPT tables for 4 floppy drives
dpt resb 4*14
; Information for logged in drive
drvss resb 1 ; sector size, 2^(7+n) bytes
drvcs resb 1 ; cluster size, 2^(7+n) bytes
alignb 4
drvspt resb 2 ; sectors per track
drvspc resb 2 ; sectors per cylinder
drvoff resb 4 ; partition offset
drvend resb 4 ; first sector after the partition
drvfat resb 4 ; offset to fat table
drvrd resb 4 ; offset of root directory
drvcla resb 4 ; offset to cluster area
drvfn resb 2 ; sectors per fat table
; disk buffer for I/O operations ; disk buffer for I/O operations
alignb 2 alignb 2
dskbuf resb 512 dskbuf resb 1024