143 lines
2.7 KiB
NASM
143 lines
2.7 KiB
NASM
; 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
|
|
|
|
dpt: resb DPTSIZE
|
|
bpb: resb BPBSIZ4
|
|
|
|
section .text
|
|
|
|
dskrst: call flush
|
|
mov ax, 0xFFFF
|
|
mov [dsknum], al
|
|
mov [dskseek], ax
|
|
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: 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
|