rdos/kernel/ramdisk.inc

86 lines
1.7 KiB
PHP

; Spanning whole conventional memory
; Sector size 0x200 (512 bytes)
; Start address 0x00600, 3 hidden sectors for IVT and BDA
; Kernel .data may be in reserved sectors
; Ramdisk I/O, similar invocation to BIOS int 13h
; in AH 42=read, 43=write
; in DS:SI location of disk address packet
; out AH error code or 00 (also in CF)
ramdisk_io:
; backup original values
push cx
push dx
push si
push di
push ds
push es
; 3 most significant addr bytes must be all zero
test WORD [ds:si+0x0E], 0xFFFF
jnz .invaddr
test WORD [ds:si+0x0C], 0xFFFF
jnz .invaddr
test WORD [ds:si+0x0A], 0xFFFF
jnz .invaddr
; calculate segment register for ramdisk access
mov dx, [ds:si+0x08]
cmp dx, 0x07fd ; 0x800 sectors in adress space, 3 hidden
jge .invaddr
mov cl, 0x05 ; 2^5 = 32 paragraphs per sector
sal dx, cl
add dx, 0x0060 ; 3 hidden sectors
xor cx, cx
push cx ; offset = 0
push dx ; segment
; store addresses for buffer access
mov dx, [ds:si+0x04]
push dx ; offset
mov dx, [ds:si+0x06]
push dx ; segment
; setup transfer length (in words) in CX
mov dx, [ds:si+0x02] ; sector count
mov cx, 0x0008 ; 2^8 = 256 words per sector
sal dx, cl
xchg dx, cx
cmp ah, 0x42
je .read
cmp ah, 0x43
je .write
sub sp, 8 ; remove src & dst pointers from stack
.invval:
mov ah, 0x01
stc
jmp .ret
.invaddr: ; out of bounds
mov ah, 0x04
stc
jmp .ret
.read:
pop es ; ES:DI buffer
pop di
pop ds ; DS:SI ramdisk data
pop si
rep movsw
clc
jmp .ret
.write:
pop ds ; DS:SI buffer
pop si
pop es ; ES:DI ramdisk data
pop di
rep movsw
clc
.ret:
; restore backupped values
pop es
pop ds
pop di
pop si
pop dx
pop cx
ret