rdos/kernel/drive.asm

143 lines
2.7 KiB
NASM
Raw Normal View History

; 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
2020-08-15 23:15:31 +02:00
section .bss
2020-10-13 22:10:23 +02:00
; drive actually selected for I/O
2020-10-11 23:33:01 +02:00
dsknum: resb 1
; bios drive we end up using
biosnum: resb 1
2020-10-11 23:33:01 +02:00
; current sector number
; absolute, ignores partition
2020-10-11 23:33:01 +02:00
dskseek: resd 1
; bit 0 - dirty flag for dskbuf
dskflag: resb 1
; disk buffer for I/O operations
2020-10-11 23:33:01 +02:00
dskbuf: resb 512
dpt: resb DPTSIZE
2020-10-30 10:29:22 +01:00
bpb: resb BPBSIZ4
2020-08-15 23:15:31 +02:00
section .text
dskrst: call flush
mov ax, 0xFFFF
mov [dsknum], al
mov [dskseek], ax
mov [dskseek+2], ax
2020-10-30 10:29:22 +01:00
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
2020-10-30 10:29:22 +01:00
xor ax, ax
mov [bpb+BPBHS], ax
mov [bpb+BPBHS+2], ax
2020-10-30 10:29:22 +01:00
ret
2020-10-30 10:29:22 +01:00
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
2020-10-11 23:33:01 +02:00
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
2020-10-11 23:33:01 +02:00
; flush buffer if dirty
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