149 lines
2.5 KiB
NASM
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
|