;;;;;;;;;;;;; ; Constants ; ;;;;;;;;;;;;; FDC_BASE EQU 3f0h FDC_DOR EQU FDC_BASE + 1 FDC_MSR EQU FDC_BASE + 4 FDC_DATA EQU FDC_BASE + 5 FDC_IRQ EQU 6 FDC_DMA EQU 2 FLOPPY_CYLINDERS EQU 80 FLOPPY_HEADS EQU 2 FLOPPY_SPT EQU 18 section .text ;;;;;;;;;;;;; ; Functions ; ;;;;;;;;;;;;; _FDCRecvByte: mov dx, FDC_MSR .loop0: in al, dx test al, 11000000b jnz .end hlt jmp .loop0 .end: mov dx, FDC_DATA in al, dx ret _FDCSendByte: push bp mov bp, sp mov dx, FDC_MSR .loop0: in al, dx test al, 10000000b jnz .end hlt jmp .loop0 .end: mov dx, FDC_DATA mov al, [bp + 4] out dx, al pop bp ret _waitFDCDone: test [cs:_fdcDone], byte 0xff jnz .end hlt jmp _waitFDCDone .end: mov [cs:_fdcDone], byte 0 ret floppy_on: ; Spin up drive ; In: ; drive number (byte, 0..3) ; Out: none push bp mov bp, sp ; Check if drive motor on mov al, 1 mov cl, [bp + 4] shl al, cl test [cs:_fdcMotors], al jnz .end mov dx, FDC_DOR mov al, 10000b mov cl, [bp + 4] shl al, cl or al, [bp + 4] or al, 1100b ; activate DMA/IRQ, no reset out dx, al ; Wait for motor to spin up push word 9 mov ax, SYSCALL_WAIT_JIFFIES int SYSCALL_INTERRUPT pop ax ; Mark motor as on mov al, 1 mov cl, [bp + 4] shl al, cl or [cs:_fdcMotors], al .end: pop bp ret floppy_seek: ; In: ; drive (word) ; track (word) ; Out: none push bp mov bp, sp push word 0fh call _FDCSendByte pop ax mov al, [bp + 4] push ax call _FDCSendByte pop ax mov al, [bp + 6] push ax call _FDCSendByte pop ax call _waitFDCDone pop bp ret floppy_read: ; Read sectors from floppy ; In: ; start (word) ; length (word) ; address (dword) ; Out: push bp mov bp, sp ; Make sure floppy is spinning push word 0 call floppy_on pop ax ; Set up DMA transfer mov ax, [bp + 10] ; length shl ax, 9 push ax mov ax, [bp + 14] ; address (MSW) push ax mov ax, [bp + 12] ; address (LSW) push ax push word 2 | (01000100b << 8) ; channel 2, to memory, single transfer call setupDMAChannel add sp, 8 ; Convert to CHS mov ax, [bp + 8] ; start (LSW) xor dx, dx mov cx, FLOPPY_SPT * FLOPPY_HEADS div cx ; ax = cylinder push ax mov ax, dx mov cl, FLOPPY_SPT div cl ; al = head, ah = sector push ax ; Seek to cylinder mov al, [bp - 3] xor ah, ah push ax push word 0 call floppy_seek add sp, 4 ; Send read command to FDC push word 01100110b call _FDCSendByte pop ax mov al, [bp - 4] shl al, 2 push ax call _FDCSendByte pop ax mov al, [bp - 2] push ax call _FDCSendByte pop ax mov al, [bp - 4] push ax call _FDCSendByte pop ax mov al, [bp - 3] inc al push ax call _FDCSendByte pop ax push word 2 call _FDCSendByte pop ax mov al, FLOPPY_SPT push ax call _FDCSendByte pop ax push word 27 call _FDCSendByte pop ax push word 0ffh call _FDCSendByte pop ax ; read status bytes mov cx, 7 readStatus: push cx call _FDCRecvByte pop cx loop readStatus mov sp, bp pop bp iret ;;;;;;;;;;;;;;;;;;;;; ; Interrupt Handler ; ;;;;;;;;;;;;;;;;;;;;; fdcIRQHandler: inc byte [cs:_fdcDone] mov al, 60h + FDC_IRQ out 20h, al iret ;;;;;;;; ; Data ; ;;;;;;;; section .data _fdcDone db 0 _fdcMotors db 0