rdos/kernel/diskio.asm

149 lines
2.5 KiB
NASM

section .bss
chsspt: equ 0 ; word sectors per track
chsnos: equ 2 ; word number of sides
chspo: equ 4 ; dword partition offset
chssiz: equ 8
chstab: resw (4*chssiz)
; Disk access packet for EBIOS extensions
dapps: equ 0 ; byte packet size
dapnum: equ 2 ; word number of sectors to transfer
dapbuf: equ 4 ; dword transfer buffer
dapsec: equ 8 ; qword absolute sector number
dapsiz: equ 16
section .text
; Convert between drive number and BIOS dl
; Bidirectional mapping
; 0 <-> 0, 1 <-> 1, 2 <-> 0x80, 3 <-> 0x81
dnconv: mov cx, 7
ror dx, 1
rol dl, 1
dncl: rcl dl, 1
rcr dh, 1
loop dncl
xchg dh, dl
ret
fndchs: ; find CHS table entry
; IN dl DOS drive number (A=0, B=1, ...)
; OUT cs:si ptr to chs table entry
push ax
mov ax, chssiz
mul dl
add ax, chstab
mov si, ax
pop ax
ret
; compare sector number in disk access packet with zero
; sets zero flag accordingly
iszero: push ax
mov ax, [bx]
or ax, [bx+2]
pop ax
ret
; calculate CHS from dap and CHS table entry
; IN ds:bx disk access packet
; cs:si chstab table entry
; OUT cx,dh chs data for int 13h
calchs: push ax
; load linear sector number
mov dx, [bx+2]
mov ax, [bx]
; if any word of it is non-zero, we need to do calculation
call iszero
jz .zero
; ax is track number (lba / spt)
; dx is sector (lba % spt) + 1
div word [cs:si+chsspt]
inc dx
; sector number
mov cl, dl
; ax is cylinder (track / heads)
; dx is head (track % heads)
xor dx, dx
div word [cs:si+chsnos]
; set up cylinder and head number
mov ch, al
mov dh, dl
pop ax
ret
; set up CHS data for int 13h for reading sector zero
.zero: mov cx, 1 ; C=0, S=1
mov dh, 0 ; H=0
pop ax
ret
; ABSOLUTE DISK READ / DISK WRITE
int25h: mov ah, 2
jmp adisk
int26h: mov ah, 3
adisk: push bp
push ds
push es
mov bp, sp
push ax
cmp cx, 0xFFFF
je .lrg
; build ebios DAP from registers supplied
; qword sector number
push cs
push cs
push cs
push dx
; dword target buffer
push ds
push bx
; word number of sectors
push cx
jmp .psz
.lrg: ; build ebios DAP from int 25h DAP
; qword sector number
push cs
push cs
mov ax, [bx+2]
push ax
mov ax, [bx]
push ax
; dword target buffer
mov ax, [bx+8]
push ax
mov ax, [bx+6]
push ax
; word number of sectors
mov ax, [bx+4]
push ax
.psz: ; word packet size
mov ax, dapsiz
push ax
; DS:SI = SS:SP (ptr to dap)
push ss
pop ds
mov si, sp
; set up int 13h subfunction number
mov ax, [si+dapsiz]
add ah, 0x40
; get BIOS drive number
mov dl, al
call dnconv
int 0x13
.ret: mov sp, bp
pop es
pop ds
pop bp
retf