Another attempt on disk i/o

This commit is contained in:
Nero 2020-05-02 23:57:23 +02:00
parent 404825387b
commit 36f4673c91
3 changed files with 101 additions and 129 deletions

View File

@ -3,6 +3,7 @@
jmp 0:(init+0x7C00-$$)
%include "inc/bpb.asm"
%include "inc/mbr.asm"
; Far call via interrupt vector
%macro intcall 1
@ -195,7 +196,7 @@ fputc: push ax
%include "kernel/diskio.asm"
vects: dw int20h, int21h, retf, retf
dw retf, int25h, int26h, int20h
dw retf, retf, retf, int20h
dw idle, fputc
main: ; zero out first 64kb except our code
@ -222,12 +223,7 @@ intlp: movsw
call dnconv
mov al, dl
mov cx, 1
mov dx, 0
mov bx, buffer
int 3
intcall 0x25
int 3
call select
loop: int 0x28
jmp loop
@ -250,6 +246,3 @@ init: cli
section .bss
; stack to be used during init and disk i/o
stack: resw stacks
; default int 25h/26h handler use a cache to keep geometry for
; the first 4 drives
buffer: resb 512

11
inc/mbr.asm Normal file
View File

@ -0,0 +1,11 @@
mbrtab: equ 0x1BE ; start of partition table
mbrsig: equ 0x1FE ; start of signature
mbrmn: equ 0x55AA ; signature value
pardn: equ 0x00 ; byte: partition active flag
parchs: equ 0x01 ; 3 bytes: CHS for first sector
partyp: equ 0x04 ; byte: partition type
parend: equ 0x05 ; 3 bytes: CHS for last sector
paroff: equ 0x08 ; dword: partition offset in sectors
parlen: equ 0x0C ; dword: partition length in sectors
parsiz: equ 0x10

View File

@ -1,11 +1,23 @@
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
disk_buffer:
resb 512
chstab: resw (4*chssiz)
disk_current:
resb 1
lba_supported:
resb 1
disk_chs: ; DL, DH, CL, CH for int 13h CHS functions
resb 4
disk_dap: ; disk access packet for int 13h EBIOS functions
resb 0x10
disk_tracks: ; heads * spt
resw 1
disk_spt:
resb 1
; Disk access packet for EBIOS extensions
dapps: equ 0 ; byte packet size
@ -28,121 +40,77 @@ dncl: rcl dl, 1
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
; Select a drive for I/O
; IN dl 0=A, 1=B, 2=C, 3=D
select: mov byte [disk_current], 0xFF
mov byte [lba_supported], 0
cmp dl, 0x02
jc select_floppy
; detect EBIOS/LBA extensions
call dnconv
mov byte [disk_chs], dl
mov ah, 0x41
mov bx, 0x55AA
int 0x13
test cx, 1
jz .nolba
cmp bx, 0xAA55
jnz .nolba
mov byte [lba_supported], 1
.nolba: call seek_zero
ret
.ret: mov sp, bp
select_floppy:
xor dx, dx
xor ax, ax
call seek
call read
ret
; Set absolute sector number
; IN dx:ax 32-bit sector number
seek: push ax
or ax, dx
pop ax
jz seek_zero
; dx:ax = lba
div word [disk_tracks]
xchg ax, dx
; dx = cylinder, ax = head * spt + sector
div byte [disk_spt]
; dx = cylinder, al = head, ah = sector
xchg dl, dh
ror dl, 1
ror dl, 1
or dl, ah
;inc dx
; dh bit 0-7: cylinder 0-7
; dl bit 0-5: sector number 0-5
; dl bit 6-7: cylinder 8-9
; store
mov byte [disk_chs+1], al
mov word [disk_chs+2], dx
int 3
ret
seek_zero:
mov byte [disk_chs+1], 0
mov word [disk_chs+2], 1
ret
; Read a sector into buffer
read: mov ax, 0x0201
mov dx, [disk_chs]
mov cx, [disk_chs+2]
lea bx, [disk_buffer]
push cs
pop es
pop ds
pop bp
retf
int 3
int 0x13
int 3
ret
; Write a sector into buffer
write:
ret