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