hi
egy regi Fidonetes gyujtemenyben talaltam ezt a rovid peldaprogramot
remelem hasznat veszed
udv
Zoli
;---------------- HWREAD.ASM --------------
; Demonstration for accessing the floppy controller directly
; Reads the bootsector and displays the ID string (at ofs 3)
; Original Read_Sector from a Dutch book, converted to English
; and (re?)commented by Arne de Bruijn, 1994, PD
; Locks up if no disk is inserted in drive 0 (usually A:), until you insert
; a disk
; With HD drives, you need first to switch to the proper density
; with port 3f7h, 0 = 3"5 HD, 1 = 5"25 HD, 2 = DD (not implented, just
; start with a value, if error try another, just like the BIOS does
; (that's why floppies are so slow after you insert a new disk))
; or just do a dir or something and the BIOS does it all for you
; I've tried to detect a diskchange with a read from port 3f7h, bit 7,
; but after I detected a change, I can't reset the bit (but the BIOS does).
; Anybody?
_DATA segment word public 'DATA'
buffer db 512 dup(?) ; Buffer for the sector
status_buf db 7 dup(?) ; Buffer for the returned status registers
_DATA ends
_TEXT segment word public 'CODE'
assume ds:_DATA,es:nothing,cs:_TEXT,ss:_STACK
TestHWR proc far
mov ax,_Data
mov ds,ax
call Read_Sector
mov dx,3+offset buffer ; Address of ID string in bootsector
mov cx,8 ; 8 Chars
mov bx,1 ; To STDOUT
mov ah,40h ; Write
int 21h
mov ax,4c00h ; Terminate w/exitcode 0
int 21h
TestHWR endp
Read_Sector proc near
sti ; Enable interrupts
mov dx,3f2h ; Address of Digital Output Register
mov al,28 ;00011100 ; bit 1,0: 00 - Drive 0
; bit 2: FDC enable, bit 3: DMA/IO enable
; bit 4: Motor drive 0 enable
out dx,al ; To Digital Output Register
call Wait_Motor ; Let moter spin up for 1/2 sec.
mov ah,15 ; Command 15: Seek
call Send_FDC_Cmd ; Send to FDC
mov ah,0 ; Parameter 1: Drive no
call Send_FDC_Cmd ; Send to FDC
mov ah,0 ; Parameter 2: Track no
call Send_FDC_Cmd ; Send to FDC
call Wait_Int ; Wait for IRQ 6 from FDC (cmd completed)
mov cx,1750 ; Wait to settle head
Wait_Head: loop Wait_Head ; A bit CPU dependant, but it works :-)
mov al,46h ; Init DMA
out 12,al ; ??
out 11,al ; ??
mov ax,offset buffer ; Offset of buffer to AX
mov bx,ds ; Segment of buffer to BX
mov cl,4 ; Divide by 16
rol bx,cl ; To isolate 64K block (page) of buffer
mov dl,bl
and dl,0fh ; Page no in DL
and bl,0f0h ; Add remainder of segment (*16)
add ax,bx ; To offset
adc dl,0 ; And adjust DL if neccesary
out 4,al ; Store lo byte of offset
mov al,ah ; Hi byte to AL
out 4,al ; Store hi byte of offset
mov al,dl ; Page no to DL
out 81h,al ; Store page no of buffer
mov ax,511 ; Number of bytes to receive, less 1
out 5,al ; Store lo byte of count
mov al,ah ; Hi byte to AL
out 5,al ; Store hi byte of count
mov al,2 ; ??
out 10,al ; ??
mov ax,351eh ; Get address of INT 1Eh, a pointer to
int 21h ; a table with some information for the FDC
mov ah,66h ; Command 6: Read data
; bit 5: Skip deleted data adress mark
; bit 6: MFM mode
call Send_FDC_Cmd ; Send to FDC
mov ah,0 ; Parameter 1: bit 1,0: drive no. (00=drive 0)
; bit 2: Head (1=Head 1)
call Send_FDC_Cmd ; Send to FDC
mov ah,0 ; Parameter 2: Track no.
call Send_FDC_Cmd ; Send to FDC
mov ah,0 ; Parameter 3: Head no. (again????)
call Send_FDC_Cmd ; Send to FDC
mov ah,1 ; Parameter 4: Starting sector no.
call Send_FDC_Cmd ; Send to FDC
mov ah,es:[bx+3] ; Parameter 5: Sector size (get from table)
; (0 - User spec., 1 - 256, 2 - 512, 3 - 1024)
call Send_FDC_Cmd ; Send to FDC
mov ah,es:[bx+4] ; Parameter 6: Last sector in track (from table)
; (Actuelly I think this is the last sector to
; read, so for 1 sector starting at sec. 1
; it's 1, but I don't know for sure)
call Send_FDC_Cmd ; Send to FDC
mov ah,es:[bx+5] ; Parameter 7: Gap length (from table)
call Send_FDC_Cmd ; Send to FDC
mov ah,es:[bx+6] ; Parameter 8: Data length (if par5 is 0)
call Send_FDC_Cmd ; Send to FDC
call Wait_Int ; Wait until completed
mov cx,7 ; Command 6 has 7 status registers
lea bx,status_buf ; Read them into Status_Buf
Next: call Get_FDC_Stat ; Get one status register
mov [bx],al ; Store in buffer
inc bx ; To next position in buffer
loop Next ; Do all the 7
mov dx,3f2h ; Address of Digital Ouput Register
mov al,12 ; bit 2: FDC enable, bit 3: DMA/IO enable
; (to turn motor off)
out dx,al ; Store to Digital Ouput Register
ret ; Return to caller
Read_Sector endp
Wait_Int proc near ; Wait for command completed interrupt
mov ax,40h ; (IRQ 6), by polling a bit in the BIOS data
mov es,ax ; area, at 40h:3eh (bit 7)
; This bit is set by the BIOS IRQ 6 (INT 14)
; handler
Again: test byte ptr es:[3eh],80h ; Test for the bit
jz Again ; Not set? Try again (no timeout check!)
and byte ptr es:[3eh],7fh ; And switch off for later use
ret ; Return to caller
Wait_Int endp
Send_FDC_Cmd proc near ; Send a byte (in AH) to 3F5h
; and check for ready
mov dx,3f4h ; Address of main status register
TryAgain:
in al,dx ; Get a byte from main status register
test al,80h ; Test bit 7: Data reg ready for IO from/to CPU
jz TryAgain ; Not set? Try again (no timeout check!)
inc dx ; Set to cmd output address
mov al,ah ; Get byte to send
out dx,al ; And send to FDC
ret ; Return to caller
Send_FDC_Cmd endp
Get_FDC_Stat proc near
mov dx,3f4h ; Address of main status register
TryAg2: in al,dx ; Get a byte from main status register
test al,80h ; Test bit 7: Data reg ready for IO from/to
CPU
jz TryAg2 ; Not set? Try again (no timeout check!)
inc dx ; Set to cmd status address
in al,dx ; And get the status byte
ret ; Return to caller
Get_FDC_Stat endp
Wait_Motor proc near ; Wait a 1/2 sec to let the motor spin up
mov ax,40h ; Wait for 9 changes from day-time counter
mov es,ax ; In BIOS data area at 40h:6eh
mov cx,9 ; 18.2 times per sec incremented, 9 -> 1/2 sec
NewTick:mov dx,es:[6ch] ; Get actual tick count (only lo word)
ChkTick:cmp es:[6ch],dx ; Compare
je ChkTick ; Not changed? Try again
loop NewTick ; Wait for next tick
ret ; Return to caller
Wait_Motor endp
_TEXT ends
_STACK segment word stack 'STACK'
db 256 dup(?)
_STACK ends
end TestHWR
|