diff --git a/kernel/disk.asm b/kernel/disk.asm new file mode 100644 index 0000000..86e3195 --- /dev/null +++ b/kernel/disk.asm @@ -0,0 +1,168 @@ +disk_num: equ 0x40 ; BYTE drive number (A=0) +disk_heads: equ 0x41 ; BYTE number of heads/sides +disk_parm: equ 0x42 ; 11 BYTES for int 0x1E +disk_spt: equ 0x46 ; - BYTE + +disk_parm_init: + push ax + push si + push di + push ds + + ; invalidate existing data + mov byte [disk_num], 0xFF + + xor ax, ax + mov ds, ax + + ; if int 0x1E is already pointing to us, + ; we have nothing to copy + mov di, disk_parm + lds si, [0x1E*4] + cmp si, di + je .correctparm + + ; copy bios table into our location + mov cx, 11 + rep movsb + + ; make the interrupt vector point to our address + xor ax, ax + mov ds, ax + mov [0x1E*4], di + mov ax, cs + mov [0x1E*4+2], ax + +.correctparm: + pop ds + pop di + pop si + pop ax + ret + +disk_load_bpb: + mov ax, 0x0201 + mov cx, 0x0001 + xor dh, dh + mov bx, diskbuf + stc + + int 0x13 + jnc .end + + ; try a second time + mov ax, 0x0201 + int 0x13 + jnc .end + + ; try a third time + mov ax, 0x0201 + int 0x13 +.end: + ret + +disk_select: + push ax + push cx + push dx + push bx + + cmp byte [disk_num], dl + je .end + mov byte [disk_num], dl + call disk_load_bpb + jc .end + + ; Validate and apply sector size + mov ax, [diskbuf+fdc_ss] +; test ax, 0xF87F +; jnz .nobpd + call log2 + sub al, 7 + mov [disk_parm+3], al + + ; fetch sectors per track + mov al, [diskbuf+fdc_spt] + mov [disk_parm+4], al + + ; fetch number of sides/heads + mov ax, [diskbuf+fdc_nos] + mov [disk_heads], al + + xor ah, ah + int 0x13 +.end: + pop bx + pop dx + pop cx + pop ax + ret + +; Setup CX, DX and BX for int 13h transfer +; IN BX ptr to 32-bit number +; OUT CL Sector number +; CH Cylinder number +; DL Drive number +; DH Head number +; BX Sector buffer +disk_prepare_chs: + mov ax, word [bx] + mov dx, word [bx+2] + + xor bh, bh + mov bl, byte [disk_spt] + + div word bx ; ax:temp = (lba / spt) + inc dx ; dx:sector = (lba % spt) + 1 + mov cl, dl ; sector number + + xor bx, bx + mov bl, byte [disk_heads] + + xor dx, dx + div word bx ; ax:cylinder = (temp / nos) + ; dx:head = (temp % nos) + mov ch, al ; cylinder number + mov dh, dl ; head number + + mov dl, byte [disk_num] + mov bx, diskbuf + ret + +; Read a sector into diskbuf +; IN BX ptr to DWORD giving sector number +disk_read: + push ax + push cx + push dx + push bx + + call disk_prepare_chs + + mov ax, 0x0201 + int 0x13 + + pop bx + pop dx + pop cx + pop ax + ret + +; Write a sector from diskbuf +; IN BX ptr to DWORD giving sector number +disk_write: + push ax + push cx + push dx + push bx + + call disk_prepare_chs + + mov ax, 0x0301 + int 0x13 + + pop bx + pop dx + pop cx + pop ax + ret diff --git a/kernel/drive.asm b/kernel/drive.asm deleted file mode 100644 index 447fb3a..0000000 --- a/kernel/drive.asm +++ /dev/null @@ -1,70 +0,0 @@ -; Load a sector from drive. -; IN DX:AX sector number (lba) -; BX ptr to FCB -; OUT CL Sector number -; CH Cylinder number -; DH Head number -drive_chs_calc: - push bx ; backup fcb ptr - mov bx, [bx+fcb_spt] ; nos is in BH now - push bx ; backup nos - xor bh, bh ; zero out nos so spt is left - div word bx ; ax:temp = (lba / spt) - inc dx ; dx:sector = (lba % spt) + 1 - mov cl, dl ; sector number - - pop bx ; restore nos - xchg bl, bh ; put nos into bl - xor bh, bh ; zero out spt - div word bx ; ax:cylinder = (temp / nos) - ; dx:head = (temp % nos) - mov ch, al ; cylinder number - mov dh, dl ; head number - - pop bx ; restore fcb ptr - ret - -; Load a sector from drive. -; IN DX:AX sector number -; BX ptr to FCB -drive_read: - push ax - push cx - push dx - push bx - push si - - mov cx, dx - or cx, ax - jz .fast - - call drive_chs_calc - - mov si, 5 ; retry count -.try: - mov dl, [bx+fcb_drv] ; drive number - and dl, 0x7F - dec dl - mov ax, 0x0201 - mov bx, diskbuf - ; try read - int 0x13 - jnc .end - ; reset disk - mov ah, 0x00 - int 0x13 - ; loop with si - dec si - test si, si - jnz .try - stc -.end: - pop si - pop bx - pop dx - pop cx - pop ax - ret -.fast: ; fast lane for boot sector - inc cl - jmp .try diff --git a/kernel/exec.asm b/kernel/exec.asm index 9ab3744..faf2d23 100644 --- a/kernel/exec.asm +++ b/kernel/exec.asm @@ -7,7 +7,6 @@ exec: mov bx, sp call fcb_parse - call fcb_open_rootdir add sp, 0x20 pop bx diff --git a/kernel/fcb.asm b/kernel/fcb.asm index 85d0e60..06f3ffe 100644 --- a/kernel/fcb.asm +++ b/kernel/fcb.asm @@ -5,67 +5,4 @@ fcb_drv: equ 0 ; 1 byte, 1=A: 2=B: 3=C: fcb_fn: equ 1 ; 8 bytes fcb_ext: equ 9 ; 3 bytes -; Drive & FS data (6 bytes) -fcb_spt: equ 12 ; byte sectors per track -fcb_nos: equ 13 ; byte number of sides/heads -fcb_ss: equ 14 ; byte sector size: 0=128, 1=256, 2=512, ... -fcb_cs: equ 15 ; byte cluster size: 0=128, 1=256, 2=512, ... -fcb_co: equ 16 ; word start sector for theoretical cluster 0 - -; Read/Write pointer (6 bytes) -fcb_left: equ 18 ; word number of bytes left to read in current sector -fcb_off: equ 20 ; dword offset in disk (not in file) - -; Link to directory item (4 bytes) -fcb_ds: equ 24 ; dword offset of directory item - -fcb_end: equ 32 - -fcb_open_rootdir: - mov dl, 0x01 - or dl, 0x80 - mov [bx], dl - dec dl - - ; Setup default data - ; Default 2 heads, 9 sectors - mov word [bx+fcb_spt], 0x0209 - xor ax, ax - xor dx, dx - lea di, [bx+fcb_ss] - ; Sector & Cluster size 128 bytes - mov cx, (fcb_end - fcb_ss) - rep stosb - - ; load first sector - call drive_read - - ; copy sector size - mov ax, [diskbuf + fdc_ss] - call log2 - sub ax, 7 - ; ... save as sector size - mov byte [bx+fcb_ss], al - - ; copy cluster size - xor ah, ah - mov al, [diskbuf + 0x0D] - call log2 - add al, [bx+fcb_ss] - mov byte [bx+fcb_cs], al - - ; copy sectors per track - mov al, [diskbuf + fdc_spt] - mov byte [bx+fcb_spt], al - - ; copy number of heads/sides - mov al, [diskbuf + 0x1A] - mov byte [bx+fcb_nos], al - - xor dx, dx - mov ax, [diskbuf + fdc_sf] - mul byte [diskbuf + fdc_fn] - add ax, [diskbuf + fdc_rsc] - int3 - - ret +fcb_type: equ 12 ; BYTE type identifier diff --git a/kernel/main.asm b/kernel/main.asm index 793b237..0abe31e 100644 --- a/kernel/main.asm +++ b/kernel/main.asm @@ -22,7 +22,10 @@ init: mov dx, banner call print_string - call exec_chain + call disk_parm_init + + mov dl, 0x00 + call disk_select cli .halt: @@ -52,6 +55,6 @@ cpm_syscall: %include "fdc.asm" %include "fcb.asm" %include "fcbparse.asm" -%include "drive.asm" +%include "disk.asm" %include "log2.asm" %include "dump.asm"