160 lines
2.7 KiB
NASM
160 lines
2.7 KiB
NASM
section .bss
|
|
|
|
drives: equ 16
|
|
|
|
; 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 ax, 0x0301
|
|
mov cx, [chs_cx]
|
|
mov dx, [chs_dx]
|
|
mov bx, diskbuf
|
|
int 0x13
|
|
ret
|