section .bss drives: equ 16 ; drive table entry struc drive .biosnum: resb 1 .flag: resb 1 .spc: resw 1 .cylinders: resw 1 .dpt: resb dpt_size endstruc ; ptr into currently selected drive 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 int 0x11 mov cl, 6 shr ax, cl inc ax and ax, 3 mov cx, ax mov bx, drive_table xor dx, dx .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 int 0x13 pop bx ; set up defaults if invalid data or fail jc .defs test cx, cx jnz .load .defs: ; use defaults: 360k, 40 cyl, 9 sects les di, [0x1e * 4] mov cx, 0x270 mov dh, 1 .load: ; copy dpt push es push ds pop es pop ds push cx mov si, di lea di, [bx+drive.dpt] mov cx, 11 rep movsb pop cx ; restore ds push cs pop ds ; get and save number of cylinders mov ax, cx xchg al, ah rol ah, 1 rol ah, 1 and ax, 0x03FF inc ax mov [bx+drive.cylinders], ax ; save spt mov ax, cx and al, 0x3F mov [bx+drive.dpt+dpt.lastsector], al ; multiply with heads and save sectors per cylinder inc dh mul dh ; ax = al * dh mov [bx+drive.spc], ax ; advance loop pop dx pop cx inc dl 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