Copy Link
Add to Bookmark
Report
NuKE Issue 06-005
================================================================================
Volume 1, Issue 6, May 1993
NuKE Info-Journal #6
NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE
uK E-
KE "Programming the NEC765 Floppy Disk Controller, -N
E- and the DMA Chip to bypass the Int 13h Nu
-N uK
Nu By KE
uK Dr. X E-
KE -N
E-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-Nu
% The Challenge %
~~~~~~~~~~~~~~~~~
The challenge was started by Dr. X in order to try to access the disk media
without using any DOS or Bios Interrupt 13h calls. Surely a _very_ difficult
challenge indeed, nevertheless Dr. X has succeeded in doing so, and he will
explain the theory behind his development. This scholar does deserve a
`pat on the back' for his brain teaser work. Good work Dr. X, and welcome
aboard.
NuKE Members/Supporters
% Programming the Floppy Disk Controller & DMA chip to bypass the Int 13h %
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The NEC 765 floppy disk controller chip controls floppy disk drives motors
and heads. And it manages the flow of data to and from the disk sector(s).
The FDC (Floppy Disk Controller) performs 15 operations in all, of which
only three are discussed here. They are Seek, Read and Write.
The FDC operates in three phases:
1) The command phase
2) The execution phase
3) The result phase
a) The command phase : When one or more bytes are sent to the Data Registers
b) The execution phase: When the FDC undertake the command
c) The result phase : A number of status byte(s) are read from the Data
Register(s)
% I) The Ports %
The FDC is operated through only three I/O (Input/Output) ports:
3F2 - Digital Output Port
3F4 - Status Register
3F5 - Data Register
1. Digital Output Port (3F2)
Bits Function
1-0 Drive # ; 00=A, 01=B, 10=C, 11=D
2 0=Reset the floppy disk controller (***)
3 1=Enable FDC interrupt and DMA access
7-4 1=Turn ON drive motors D to A (bit 4 = drive A)
Warning: This register is WRITE ONLY
(***) Do not set bit 2 to 0 at any time (recelebrate)
2. Data Register (3F5)
Operation Byte # Function
Seek 1 Code number (Fh)
2 Head & Drive : 00000HDD (h=head, DD=drive)
Read Sector 1 Code number (66h)
2 Head & Drive : 00000HDD (h=head, DD=drive)
3 Track number
4 Head number
5 Sector number
6 Bytes in sector (2=512)
7 End of track (09)
8 GAP Length
9 Data Length
Write Sector 1 Code number (45h)
2-9 Same as READ SECTOR (above)
Warning: You must be sure that the FDC is ready before you send or read a
a byte from the data register. Bits 7-6 of the status register
provide this information.
3. Status Register (3F4)
Bits Function
3-0 1=Disk drive D-A in Seek Mode
4 1=FDC read or write command in progress
5 1=FDC is not in DMA mode
6 1=FDC data register is ready to send data
0=FDC data register is ready to receive data
7 1=FDC ready to send or receive data
Warning: When a seek operation is complete, the FDC invokes a INT 6h
(the disk interrupt). When the interrupt occurs, the BIOS
interrupt handler sets the bit 7 of the seek status byte in
the BIOS Data Area located at 0:043E. This is the sole result of
the interrupt.
% II) Initializing %
Before initializing a channel, the program must send a code to the chip
telling it whether it is reading from or writing to the Floppy Disk
Controller. This one byte code is 46h for reading and 4Ah for writing.
The code must be sent to each of two separate port addresses: 0E & 0C.
After that, you can send the parameters to the Data Register (3F5),
following the bellow steps:
1. Turn on the floppy disk (enable interrupts with a SLI first)
a) Out the code byte to the Digital Output Register (3F2)
b) Send 46h to read or 4Ah to write to each of two separate port
addresses 0B and 0Ch
(eg: Out 0B,46h
Out 0C,46h)
2. Then you _must_ perform a seek operation to the concerned Head
and Track;
a) Out the code for Seek operation (0F) to the FDC (3F5)
b) Out head & Drive code (00000HDDxB, H=head,DD=drive)
c) Out the track number
d) Wait for Int 6h
3. After that you can perform the read or write operation(s):
a) Calculate the address of the buffer (see the program at the end
of this Article)
b) Send the address to the DMA
c) Out the value 66h for read or 45h for write to the FDC (3F5)
d) Out the Head & Drive number
e) Out the Track number
f) Out the Head number
g) Out the Sector number
h) Out the Sector Code; get this information with INT 21h
i) Out End-of-Track ; with AX=1E35h
j) Out the GAP length
k) Out the data length
l) Wait for INT 6h
m) Perform 7 INs from the Data Register (3F5) to get the status bytes.
(Refer to Part III)
4. Finally, turn off the motor(s):
a) Out the code byte to the Digital Output Register (3F2)
% III) The Status Bytes %
After a read or write operation the FDC gives you 7 status bytes:
Byte # Function
1 Status Byte 0
2 Status Byte 1
3 Status Byte 2
4 Track number
5 Head number
6 Sector number
7 Byte per sector code (0-3)
1. Status Byte 0
Bit # Function
7-6 00=normal termination
01=execution began, could not complete
10=invalid command
11=failed because disk drive went offline
5 1=seek operation in progress
4 1=disk drive fault
3 1=disk drive not ready
2 number of selected head
1-0 number of selected drive
2. Status Byte 1
Bit # Function
7 1=requested sector beyond last sector number
6 always 0
5 1=data transfer error
4 1=data overrun
3 always 0
2 1=cannot read or find sector
1 1=cannot write because of write protection tab
0 1=missing address mark in disk format
3. Status Byte 2
Bit # Function
7 always 0
6 1=encountered delete-data address mark
5 1=CRC error in data
4 1=track identification problem
3 1=scan command condition satisfied
2 1=scan command condition NOT satisfied
1 1=bad track
0 1=missing address mark
% IV) Read Procedure in ASM (for A86 assembler) %
Jmp TheCode
Buffer Db 512 dup (0) ; For the sector
StatusBuffer Db 7 Dup (7) ; For the status bytes
TheCode Proc Near
ReadSector:
; Turn ON the Motor
Sti
Mov Dx,03F2H
Mov Al,00101101xB ; Set the Bits 0 , 2 ,3 , 4
Out Dx,Al
; Wait for motor to come to speed (1/2 second)
Call Motor_Delay
Mov Cx,2000
Loop $
; Begin the initialization of DMA Chip
Mov Al,46H ; Code for Read Datas
Out 11,Al ; Send Datas
Out 12,Al
; Now , Calculate buffer address
Lea Ax,Buffer ;
Mov Bx,Ds ;
Rol Bx,4 ;
Push Bx ;
And Bl,0FH ;
Mov Dl,Bl ;
Pop Bx ;
Add Ax,Bx ;
Jnc NoCarry ;
Inc Dl ;
NoCarry: ;
Dec Al ; justify
Out 4,Al ; Send Low Byte of adress to the DMA controller
Mov Al,Ah ;
Out 4,Al ; Send High byte of the adress // // // //
Mov Al,Dl ;
Out 81h,Al ; Send Page number (Page register)
; Finish initialization
Mov Ax,511 ;
Out 5,Al ; DMA controller
Mov Al,Ah ;
Out 5,Al ;
Mov Al,2 ;
Out 10,Al ; DMA controller
; Get pointer to disk base
Mov Al,1EH ;
Mov Ah,35H ;
Int 021H ;
; Send read parameters.
Mov Ah,066H ; Code for single sector read
Call Out_Fdc ; Send It
Mov Ah,2 ; Head&Drive #
Call Out_FDC ; Send It
Mov Ah,1 ; Track Number
Call Out_FDC ; Send It
Mov Ah,0 ; Head #
Call Out_FDC ; Send It
Mov Ah,3 ; Sector #
Call Out_FDC ; Send it
Mov Ah,Es:[Bx]+3 ; Sector Size code (2=512 bytes)
Call Out_FDC ; Send it
Mov Ah,Es:[Bx]+4 ; End-of-track #
Call Out_FDC ; Send It
Mov Ah,Es:[Bx]+5 ; Gap length
Call Out_FDC ; Send it
Mov Ah,Es:[Bx]+6 ; Datas length
Call Out_FDC ; Send
Call Wait_Interrupt ; Wait Int 6
; Read the result bytes ..
Mov Cx,7
Lea Bx,StatusBuffer
Next:
Call In_FDC
Mov [BX],Al
Inc Bx
Loop Next
; Turn OFF the motor
Mov Dx,03F2H
Mov Al,00001101xB ; Turn Off the Drive B
Out Dx,Al
Ret ; Exit from the programm
Sector_REad Endp
Wait_interrupt Proc
; Monitor the int 6 in bios status Byte
Mov Ax,40H
Mov Es,Ax
Mov Bx,3EH
Again:
Mov Dl,Es:[BX]
Test Dl,080H
Jz Again
And Al,127
Mov Es:[Bx],Dl
Ret
Wait_Interrupt EndP
Out_FDC proc near
Mov Dx,03F4H
Keep_Trying:
In Al,Dx
Test Al,128
Jz Keep_Trying
Inc Dx
Mov Al,Ah
Out Dx,Al
RET
Out_FDC EndP
In_FDC Proc Near
Mov Dx,03F4H
Keep_Trying2:
In Al,Dx
Test Al,128
Jz Keep_Trying2
Inc Dx
In Al,Dx
Ret
In_FDC EndP
Motor_Delay Proc
Mov Ah,15 ; Perform Seek Operation
Call Out_FDC ; Out
Mov Ah,2 ; Head&Drive
Call Out_FDC ; Out
Mov Ah,1 ; track#
Call Out_FDC ;
Call Wait_interrupt ;
Ret
Motor_Delay endp
--------------------------------------------------------------------------------
; The bellow is yet, another example for reading the first few beginning tracks
; but this one is for the Hard Disk
; By X
; Not `fully completed', but enough to get the point.
Jmp TheCode
Buffer Db 512 dup (0) ; For the sector
StatusBuffer Db 7 Dup (7) ; For the status bytes
TheCode Proc Near
ReadSector:
; Turn ON the Motor
Sti
Mov Dx,03F2H
Mov Al,00101101xB ; Set the Bits 0 , 2 ,3 , 4
Out Dx,Al
; Wait for motor to come to speed (1/2 second)
Call Motor_Delay
Mov Cx,2000
Loop $
; Begin the initialization of DMA Chip
Mov Al,46H ; Code for Read Data
Out 11,Al ; Send Data
Out 12,Al
; Now , Calculate buffer adress
Lea Ax,Buffer ;
Mov Bx,Ds ;
Rol Bx,4 ;
Push Bx ;
And Bl,0FH ;
Mov Dl,Bl ;
Pop Bx ;
Add Ax,Bx ;
Jnc NoCarry ;
Inc Dl ;
NoCarry: ;
Dec Al ; justify
Out 4,Al ; Send Low Byte of address to the DMA controller
Mov Al,Ah ;
Out 4,Al ; Send High byte of the address // // // //
Mov Al,Dl ;
Out 81h,Al ; Send Page number (Page register)
; Finish initialization
Mov Ax,511 ;
Out 5,Al ; DMA controller
Mov Al,Ah ;
Out 5,Al ;
Mov Al,2 ;
Out 10,Al ; DMA controller
; Get pointer to disk base
Mov Al,1EH ;
Mov Ah,35H ;
Int 021H ;
; Send read parametres.
Mov Ah,066H ; Code for single sector read
Call Out_Fdc ; Send It
Mov Ah,0 ; Head&Drive #
Call Out_FDC ; Send It
Mov Ah,12 ; Track Number
Call Out_FDC ; Send It
Mov Ah,0 ; Head #
Call Out_FDC ; Send It
Mov Ah,3 ; Sector #
Call Out_FDC ; Send it
Mov Ah,Es:[Bx]+3 ; Sector Size code (2=512 bytes)
Call Out_FDC ; Send it
Mov Ah,Es:[Bx]+4 ; End-of-track #
Call Out_FDC ; Send It
Mov Ah,Es:[Bx]+5 ; Gap length
Call Out_FDC ; Send it
Mov Ah,Es:[Bx]+6 ; Datas length
Call Out_FDC ; Send
Call Wait_Interrupt ; Wait Int 6
; Read the result bytes ..
Mov Cx,7
Lea Bx,StatusBuffer
Next:
Call In_FDC
Mov [BX],Al
Inc Bx
Loop Next
; Turn OFF the motor
Mov Dx,03F2H
Mov Al,12
Out Dx,Al
Ret ; Exit from the programm
Sector_REad Endp
Wait_interrupt Proc
; Monitor the int 6 in bios status Byte
Mov Ax,40H
Mov Es,Ax
Mov Bx,3EH
Again:
Mov Dl,Es:[BX]
Test Dl,080H
Jz Again
And Al,127
Mov Es:[Bx],Dl
Ret
Wait_Interrupt EndP
Out_FDC proc near
Mov Dx,03F4H
Keep_Trying:
In Al,Dx
Test Al,128
Jz Keep_Trying
Inc Dx
Mov Al,Ah
Out Dx,Al
RET
Out_FDC EndP
In_FDC Proc Near
Mov Dx,03F4H
Keep_Trying2:
In Al,Dx
Test Al,128
Jz Keep_Trying2
Inc Dx
In Al,Dx
Ret
In_FDC EndP
Motor_Delay Proc
Mov Ah,15 ; Perform Seek Operation
Call Out_FDC ; Out
Mov Ah,0 ; Head&Drive
Call Out_FDC ; Out
Mov Ah,12 ; track#
Call Out_FDC ;
Call Wait_interrupt ;
Ret
Motor_Delay endp
================================================================================