kernel: implement diskio using drive table

This commit is contained in:
Nero 2020-08-27 20:52:16 +00:00
parent 4a294ee21c
commit f0a000b7d1
5 changed files with 93 additions and 259 deletions

View File

@ -39,17 +39,18 @@ intlp: movsw
stosw
loop intlp
; file descriptor 0 = CON
mov word [fd_table], con_ftab
; print banner
mov dx, banner
mov cx, 13
mov bx, 0
call fd_write
call drives_init
mov dl, 0
call drive_select
xor ax, ax
xor dx, dx
call drive_seek
call drive_read
mov ax, [diskbuf+0x1FE]
int 3
loop: int 0x28
jmp loop
@ -235,12 +236,7 @@ fputc: push ax
pop ax
iret
%include "kernel/fd.asm"
%include "kernel/con.asm"
%include "kernel/drive.asm"
%include "kernel/diskio.asm"
%include "kernel/fat.asm"
zero: dw 0

View File

@ -1,22 +0,0 @@
con_ftab: dw con_read
dw con_write
con_read: stc
ret
con_write: push si
push bx
push cx
test cx, cx
jz .end
mov si, dx
mov ah, 0x0E
xor bx, bx
.loop: lodsb
int 0x10
loop .loop
pop cx
.end: pop bx
pop si
ret

View File

@ -1,192 +0,0 @@
section .bss
disk_buffer:
resb 512
disk_current:
resb 1
lba_supported:
resb 1
; Seek state and geometry info for CHS access
disk_chs: ; DL, DH, CL, CH for int 13h CHS functions
resb 4
disk_spc: ; sectors per cylinder = heads * spt
resw 1
disk_spt:
resb 1
; Partition conf from MBR or dummy for floppies
part_offset:
resd 1
part_size:
resd 1
dap: ; Disk access packet for EBIOS extensions
resw 1
dap_sectors:
resw 1
dap_buffer:
resd 1
dap_sector:
resq 1
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
; Select a drive for I/O
; This leave the first sector of the partition in the buffer
; IN dl 0=A, 1=B, 2=C, 3=D
select: mov byte [disk_current], 0xFF
mov byte [lba_supported], 0
call dnconv
mov byte [disk_chs], dl
cmp dl, 0x80
jc select_floppy
; detect EBIOS/LBA extensions
mov ah, 0x41
mov bx, 0x55AA
int 0x13
test cx, 1
jz select_hdd
cmp bx, 0xAA55
jnz select_hdd
mov byte [lba_supported], 1
jmp select_hdd
select_floppy:
push dx
call seek_zero
call read
; load disk geometry
mov ax, [disk_buffer+0x0B+bpb_spt]
mov [disk_spt], ax
mul word [disk_buffer+0x0B+bpb_nos]
mov [disk_spc], ax
; set partition size
; we dont rely on the 'total sectors' given in the BPB
; instead, we assume maximum cylinder
; 1023 is the maximum encodable for int 13h
lea di, [part_offset]
xor ax, ax
; partition offset = 0
stosw
stosw
; partition size = 0x00010000 = 32MB
stosw
inc ax
stosw
pop dx
ret
select_hdd:
push dx
; load CHS geometry for drive
mov ah, 0x8
int 0x13
xor ah, ah
mov al, cl
mov [disk_spt], ax
mul byte dh
mov [disk_spc], ax
; load offset and size of first partition
call seek_zero
call read
mov bx, disk_buffer+0x1BE
lea si, [bx+8]
lea di, [part_offset]
mov cx, 4
rep movsw
; read bpb
mov dx, [part_offset+2]
mov ax, [part_offset]
call seek
call read
pop dx
ret
; Set absolute sector number
; IN dx:ax 32-bit sector number
seek: push ax
or ax, dx
pop ax
jz seek_zero
test byte [lba_supported], 1
jnz seek_lba
; dx:ax = lba
div word [disk_spc]
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
ret
seek_zero:
; set chs data to first sector
mov byte [disk_chs+1], 0
mov word [disk_chs+2], 1
; set lba data to first sector
xor ax, ax
xor dx, dx
seek_lba:
mov word [dap], 0x10
mov word [dap_sectors], 1
mov word [dap_buffer], disk_buffer
mov [dap_buffer+2], cs
lea di, [dap_sector]
stosw
mov ax, dx
stosw
xor ax, ax
stosw
stosw
ret
; Read a sector into buffer
read: test byte [lba_supported], 1
jnz read_lba
mov ax, 0x0201
mov dx, [disk_chs]
mov cx, [disk_chs+2]
lea bx, [disk_buffer]
push cs
pop es
int 0x13
ret
read_lba:
mov ah, 0x42
mov dl, [disk_chs]
lea si, [dap]
int 0x13
ret
; Write a sector into buffer
write: stc
ret

View File

@ -16,6 +16,13 @@ drive_ptr: resw 1
drive_table: resb (drives * drive_size)
; DX and CX for int 13 CHS access
chs_dx: resw 1
chs_cx: resw 1
; disk buffer for I/O operations
diskbuf: resb 1024
section .text
drives_init: ; CX = number of floppy drives in the system
@ -32,6 +39,7 @@ drives_init: ; CX = number of floppy drives in the system
.loop: push cx
push dx
mov [bx+drive.biosnum], dl
mov byte [bx+drive.flag], 1 ; 1 = drive letter used
; query bios for floppy format
mov ah, 8
push bx
@ -82,3 +90,79 @@ drives_init: ; CX = number of floppy drives in the system
add bx, drive_size
loop .loop
ret
; select drive
; IN dl drive number
drive_select: xor dh, dh
mov ax, drive_size
mul dx
add ax, drive_table
mov word [drive_ptr], ax
ret
; reset currently selected drive
drive_reset: mov bx, [drive_ptr]
mov dl, [bx+drive.biosnum]
; our ptr = CX:BX
lea bx, [bx+drive.dpt]
mov cx, ds
; toggle in our ptr
mov si, [0x1E*4]
xchg bx, [si]
xchg cx, [si+2]
; do the call
xor ax, ax
int 0x13
pushf
; restore original ptr
xchg bx, [si]
xchg cx, [si+2]
; pass int 13 flags
popf
ret
; query status of selected drive
; OUT ah
drive_status: mov bx, [drive_ptr]
mov dl, [bx+drive.biosnum]
mov ah, 1
int 0x13
ret
; set sector for read/write operation
; IN dx:ax 32-bit sector number
drive_seek: mov bx, [drive_ptr]
div word [bx+drive.spc]
xchg ax, dx
; dx = cylinder, ax = head * spt + sector
div byte [bx+drive.dpt+dpt.lastsector]
; 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
xchg al, ah
mov al, [bx+drive.biosnum]
; store
mov word [chs_dx], ax
mov word [chs_cx], dx
ret
drive_read: mov ax, 0x0201
mov cx, [chs_cx]
mov dx, [chs_dx]
mov bx, diskbuf
int 0x13
ret
drive_write: mov ah, 0x0301
mov cx, [chs_cx]
mov dx, [chs_dx]
mov bx, diskbuf
int 0x13
ret

View File

@ -1,32 +0,0 @@
%define fd_num 32
section .bss
fd_table: resb (0x10 * fd_num)
section .text
fd_to_ptr: push cx
mov cl, 4
sal bx, cl
add bx, fd_table
pop cx
ret
fd_read: cmp bx, fd_num
jnc fd_inv_hnd
call fd_to_ptr
; read ptr to ftab
mov bx, [bx]
; jmp to addr in ftab[0]
jmp [bx]
fd_write: cmp bx, fd_num
jnc fd_inv_hnd
call fd_to_ptr
mov bx, [bx]
jmp [bx+2]
fd_inv_hnd: mov ax, 6
stc
ret