1940 lines
90 KiB
HTML
1940 lines
90 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
|
<!-- saved from url=(0069)http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html -->
|
|
<HTML><HEAD><TITLE>Programming the NEC µPD765 and Intel 82072/7 Floppy Disk Controller</TITLE>
|
|
<META content="text/html; charset=iso-8859-1" http-equiv=Content-Type><!------------------------------------------------------------------------>
|
|
<META content="MSHTML 5.00.3502.5390" name=GENERATOR></HEAD>
|
|
<BODY aLink=olive bgColor=#ffffcc link=red onload=tcI1() onresize=tcI2()
|
|
onscroll=tcI2() vLink=purple onMove="tcI2()">
|
|
<DIV id=tcI19
|
|
style="LEFT: 0px; POSITION: absolute; TOP: 0px; VISIBILITY: hidden; Z-INDEX: 2147483632">
|
|
<TABLE bgColor=#eeeeee border=0 cellPadding=0 cellSpacing=0 height=62>
|
|
<TBODY>
|
|
<TR>
|
|
<TD vAlign=top><A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/"
|
|
onclick="tcI26(); return false;" title="Click here to expand banner"><IMG
|
|
border=0 height=12 src="floppy.files/left.gif" width=12></A></TD></TR>
|
|
<TR>
|
|
<TD vAlign=bottom><A href="http://www.easyspace.com/" target=_blank><IMG
|
|
border=0 src="floppy.files/littlelogo.gif"></A></TD></TR></TBODY></TABLE></DIV>
|
|
<DIV id=tcI18
|
|
style="LEFT: 0px; POSITION: absolute; TOP: 0px; VISIBILITY: hidden; Z-INDEX: 2147483647">
|
|
<TABLE border=0 cellPadding=0 cellSpacing=0 height=62>
|
|
<TBODY>
|
|
<TR>
|
|
<TD rowSpan=2 vAlign=top><A
|
|
href="http://www.easyspace.com/redirect.cgi?type=BNR-EASYSPACE-468-LOOP-4.gif&url=http://www.easyspace.com/domains/"
|
|
target=_new><IMG alt="Easyspace for your domain registration" border=0
|
|
height=60 src="floppy.files/EASYSPACE-468-LOOP-4.gif" width=468></A></TD>
|
|
<TD bgColor=#eeeeee vAlign=top><A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/"
|
|
onclick="tcI25(); return false;" title="Click here to shrink banner"><IMG
|
|
border=0 height=12 src="floppy.files/right.gif" width=12></A></TD></TR>
|
|
<TR>
|
|
<TD bgColor=#eeeeee vAlign=bottom><A href="http://www.easyspace.com/"
|
|
target=_blank><IMG border=0
|
|
src="floppy.files/littlelogo.gif"></A></TD></TR></TBODY></TABLE></DIV><BASEFONT
|
|
face=Arial>
|
|
<TABLE border=0 cellPadding=0 cellSpacing=0 width="100%">
|
|
<TBODY>
|
|
<TR>
|
|
<TD>
|
|
<H1 align=center>Programming Floppy Disk Controllers </H1><BR>
|
|
<P align=center title="">[ <A
|
|
href="http://debs.future.easyspace.com/index.html">Home </A>] [ <A
|
|
href="http://debs.future.easyspace.com/Programming/index.html"
|
|
title="Programming Home">Programming </A>] </P></TD></TR></TBODY></TABLE>
|
|
<HR color=gray SIZE=3>
|
|
<BR><BR><!---------------------------------------------------------------------------------------->
|
|
<TABLE border=0 cellPadding=10 cellSpacing=0 width="100%">
|
|
<TBODY>
|
|
<TR>
|
|
<TD vAlign=top width=10>[ <A
|
|
href="http://debs.future.easyspace.com/Index.html">Home </A>] <BR>[ <A
|
|
href="http://debs.future.easyspace.com/Programming/Index.html"
|
|
title="Programming Home">Programming </A>] </TD>
|
|
<TD>
|
|
<P>The purpose of this document is to provide information related to
|
|
programming the NEC µPD765 and the Intel 82072/7 Floppy Disk Controllers
|
|
(FDCs), by use of the registers. The document is split into several
|
|
sections: </P><BR>
|
|
<OL>
|
|
<LI><A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#Overview">Overview
|
|
</A>
|
|
<LI><A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#Configuration">Configuration
|
|
of an FDC on a PC </A>
|
|
<LI><A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#FDC Registers">FDC
|
|
Registers </A>
|
|
<LI><A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#Commands">Command
|
|
Set </A></LI></OL><BR></TD></TR></TBODY></TABLE>
|
|
<HR color=gray SIZE=3>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H2 align=center><A name=Overview>Overview </A></H2>
|
|
<P>The PC usually uses the NEC µPD765 floppy disk controller. The AT can also
|
|
incorporate an Intel 82072A controller, while the PS/2 uses an Intel 82077A. The
|
|
µPD765 and the ROM code in the controller form a microcontroller, and this
|
|
handles the majority of the work of the controller. All PC compatibles have FDCs
|
|
which are compatible with the controllers described in this document. </P>
|
|
<P>This document describes the registers used to interface with the controller,
|
|
and the commands which it recognises. </P>
|
|
<P>There are a lot of delays involved in communicating with the controller.
|
|
These delays are for a variety of reasons, including the time needed to spin up
|
|
the drive motor, and the time taken to move the head to a new position and wait
|
|
for it to settle in place. </P>
|
|
<P>When the drive motor is started up or the a seek is requested, there will be
|
|
a delay until the drive is ready for the next command. An interrupt is issued by
|
|
the hardware when it is ready for the next command, and this will tell you that
|
|
the drive is ready for your command. </P>
|
|
<P>In a single tasked environment (such as DOS), the only option is to have your
|
|
driver constantly wait for an interrupt, and then respond to it. However, in a
|
|
multi-tasked or multi-threaded environment, it is perfectly acceptable to write
|
|
a driver which allows other tasks to be executed while waiting for the
|
|
interrupt. </P>
|
|
<P>When performing a read or write operation, data may be transferred a byte at
|
|
a time by reading from or writing to the appropriate port, or a sector/track at
|
|
a time through the use of DMA channel 2. Programming the DMA controller is
|
|
beyond the scope of this document, but will be described in a future document to
|
|
be added to this site. </P>
|
|
<P>The registers, what they do and what commands can be used are all detailed in
|
|
the following sections. If there are any errors, I will gratefully accept any
|
|
feedback you might like to send to me via <A
|
|
href="mailto:debs@savah.freeserve.co.uk">e-mail </A>. </P>
|
|
<HR color=gray SIZE=3>
|
|
<BR><BR><!---------------------------------------------------------------------------------------->
|
|
<H2 align=center><A name=Configuration>Configuration of an FDC on a PC </A></H2>
|
|
<P>The Floppy Controller on a PC uses a standard configuration. On the XT there
|
|
are 3 ports available for control and data access registers. On the AT, there
|
|
are 4, and on the PS/2 there are 6. </P>
|
|
<P>The base port address used for the controller is dependant on whether the
|
|
controller is configured as the primary or secondary controller. This base
|
|
address controls the port addresses used for each of the registers on the
|
|
controller. It can additionally be noted that all floppy controllers on a PC use
|
|
DMA channel 2 for data transfer during a read or write, and they all issue a
|
|
hardware interrupt via IRQ6 to be serviced by INT 0eh by default. </P><BR>
|
|
<TABLE align=center border=1 cellPadding=0 cellSpacing=0>
|
|
<TBODY>
|
|
<TR>
|
|
<TD width=300> </TD>
|
|
<TD width=75><STRONG>Primary <BR>Address </STRONG></TD>
|
|
<TD width=75><STRONG>Secondary <BR>Address </STRONG></TD>
|
|
<TD width=75><STRONG>Write (W) <BR>Read (R) </STRONG></TD></TR>
|
|
<TR>
|
|
<TD> </TD>
|
|
<TD> </TD>
|
|
<TD> </TD>
|
|
<TD> </TD></TR>
|
|
<TR>
|
|
<TD>base address </TD>
|
|
<TD>3f0h </TD>
|
|
<TD>370h </TD>
|
|
<TD> </TD></TR>
|
|
<TR>
|
|
<TD>status register A (PS/2) </TD>
|
|
<TD>3f0h </TD>
|
|
<TD>370h </TD>
|
|
<TD>R </TD></TR>
|
|
<TR>
|
|
<TD>status register B (PS/2) </TD>
|
|
<TD>3f1h </TD>
|
|
<TD>371h </TD>
|
|
<TD>R </TD></TR>
|
|
<TR>
|
|
<TD>digital output register DOR </TD>
|
|
<TD>3f2h </TD>
|
|
<TD>372h </TD>
|
|
<TD>W </TD></TR>
|
|
<TR>
|
|
<TD>main status register </TD>
|
|
<TD>3f4h </TD>
|
|
<TD>374h </TD>
|
|
<TD>R </TD></TR>
|
|
<TR>
|
|
<TD>data rate select register (DSR)(PS/2) </TD>
|
|
<TD>3f4h </TD>
|
|
<TD>374h </TD>
|
|
<TD>W </TD></TR>
|
|
<TR>
|
|
<TD>data register </TD>
|
|
<TD>3f5h </TD>
|
|
<TD>375h </TD>
|
|
<TD>R/W </TD></TR>
|
|
<TR>
|
|
<TD>digital input register DIR (AT) </TD>
|
|
<TD>3f7h </TD>
|
|
<TD>377h </TD>
|
|
<TD>R </TD></TR>
|
|
<TR>
|
|
<TD>configuration control register (AT) </TD>
|
|
<TD>3f7h </TD>
|
|
<TD>377h </TD>
|
|
<TD>W </TD></TR>
|
|
<TR>
|
|
<TD>DMA channel </TD>
|
|
<TD>2 </TD>
|
|
<TD>2 </TD>
|
|
<TD> </TD></TR>
|
|
<TR>
|
|
<TD>IRQ </TD>
|
|
<TD>6 </TD>
|
|
<TD>6 </TD>
|
|
<TD> </TD></TR>
|
|
<TR>
|
|
<TD>INTR </TD>
|
|
<TD>0eh </TD>
|
|
<TD>0eh </TD>
|
|
<TD> </TD></TR></TBODY></TABLE><BR><BR><BR>
|
|
<P>Note that the controller can be configured differently from the defaults for
|
|
handling interrupts. </P>
|
|
<HR color=gray SIZE=3>
|
|
<BR><BR><!---------------------------------------------------------------------------------------->
|
|
<H2 align=center><A name="FDC Registers">FDC Registers </A></H2>
|
|
<P>This section gives more detailed information on the use of the registers
|
|
listed in the above table. Additionally, the first registers to be described are
|
|
those common to each system described, and these will be followed by
|
|
descriptions of AT specific registers and PS/2 specific registers. </P>
|
|
<P>Common Registers: </P>
|
|
<OL>
|
|
<LI><A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#DOR">Digital
|
|
Output Register DOR </A>
|
|
<LI><A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#MSR">Main
|
|
Status Register </A>
|
|
<LI><A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#Data">Data
|
|
Register </A></LI></OL>AT Specific Registers:
|
|
<OL>
|
|
<LI><A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#DIR">Digital
|
|
Input Register DIR </A>
|
|
<LI><A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#CCR">Configuration
|
|
Control Register </A></LI></OL>PS/2 Specific Registers:
|
|
<OL>
|
|
<LI><A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#Status">Status
|
|
Register A </A>
|
|
<LI><A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#Status">Status
|
|
Register B </A>
|
|
<LI><A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#DRSR">Data
|
|
Rate Select Register </A></LI></OL>
|
|
<HR>
|
|
|
|
<H3><A name=DOR>Digital Output Register DOR </A></H3>
|
|
<P align=center><IMG alt="image of Digital Output Register" height=136
|
|
src="floppy.files/DOR.gif" title="Digital Output Register" width=260> </P>
|
|
<TABLE cellPadding=2 width=550>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>MOTD, MOTC, MOTB, MOTA:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>Motor control for floppy drive D, C, B, A
|
|
</STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE width="100%">
|
|
<TBODY>
|
|
<TR>
|
|
<TD width="50%"><FONT size=-1>1 = Start motor</FONT> </TD>
|
|
<TD><FONT size=-1>0 = Stop motor</FONT> </TD></TR></TBODY></TABLE></TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>DMA:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>DMA and IRQ channel</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE width="100%">
|
|
<TBODY>
|
|
<TR>
|
|
<TD width="50%"><FONT size=-1>1 = Enabled</FONT> </TD>
|
|
<TD><FONT size=-1>0 = Disabled</FONT> </TD></TR></TBODY></TABLE></TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1><A style="TEXT-DECORATION: overline">REST:
|
|
</A></FONT></STRONG></TD>
|
|
<TD><STRONG><FONT size=-1>Controller reset</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE width="100%">
|
|
<TBODY>
|
|
<TR>
|
|
<TD width="50%"><FONT size=-1>1 = Controller enabled</FONT> </TD>
|
|
<TD><FONT size=-1>0 = Execute controller reset</FONT>
|
|
</TD></TR></TBODY></TABLE></TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>DR1,DR0:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Drive select</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE width="100%">
|
|
<TBODY>
|
|
<TR>
|
|
<TD width="25%"><FONT size=-1>00 = drive 0 (A)</FONT> </TD>
|
|
<TD width="25%"><FONT size=-1>01 = drive 1 (B)</FONT> </TD>
|
|
<TD width="25%"><FONT size=-1>10 = drive 2 (C)</FONT> </TD>
|
|
<TD><FONT size=-1>11 = drive 3 (D)</FONT>
|
|
</TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR><BR>
|
|
<P>This register is write only, and controls the drive motors, as well as
|
|
selecting a drive and the DMA/IRQ mode, and resetting the controller. </P>
|
|
<P>If the REST bit is set, the controller is enabled, in order to accept and
|
|
execute commands. If it is equal to 0, the controller ignores all commands and
|
|
carries out an internal reset of all internal registers (except the DOR). </P>
|
|
<P>Note that a drive cannot be selected unless its motor is on, although setting
|
|
the bits at the same time is acceptable. </P>
|
|
<P>Note also that drives 2 and 3 (floppy drives C and D) are not supported in
|
|
all systems. </P>
|
|
<P><STRONG>Example: </STRONG><BR>To start the motor on drive A and select it,
|
|
ready for another operation, you would use the following: <BR><BR></P>
|
|
<DL>
|
|
<DD>MOTA = 1 (start motor for drive A)
|
|
<DD>DMA = 1 (assuming you want to use DMA and interrupts)
|
|
<DD>REST = 1 (Controller enabled, otherwise no other commands will be
|
|
executed)
|
|
<DD>DR1,DR0 = 00 (Select drive A)
|
|
<DD>All other bits are set to 0 <BR><BR>Thus 16 + 8 + 4 + 0 = 28, or 01Ch, is
|
|
sent to port 3f2h (Drive A is usually on the primary controller). </DD></DL>
|
|
<P>In assembly language, this would be written as: </P><PRE><STRONG><FONT size=+2>
|
|
mov al,01ch
|
|
mov dx,03f2h
|
|
out dx,al</FONT></STRONG>
|
|
</PRE><BR>
|
|
<P><STRONG>Example: </STRONG><BR>To reset the controller, send 0 to port 3f2h.
|
|
This turns off all motors, selects no drives (because drive A's motor is not
|
|
active, it cannot be selected), disables the DMA and IRQ line, and resets the
|
|
controller. </P>
|
|
<P>The code for this is as follows: <BR><BR></P><PRE><STRONG><FONT size=+2>
|
|
mov al,0
|
|
mov dx,03f2h
|
|
out dx,al</FONT></STRONG>
|
|
</PRE><BR>
|
|
<HR>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H3><A name=MSR>Main Status Register </A></H3>
|
|
<P align=center><IMG alt="image of Main Status Register" height=136
|
|
src="floppy.files/MSR.gif" title="Main Status Register" width=260> </P>
|
|
<TABLE cellPadding=2 width=550>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>MRQ:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>main request</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE width="100%">
|
|
<TBODY>
|
|
<TR>
|
|
<TD width="50%"><FONT size=-1>1 = data register ready</FONT> </TD>
|
|
<TD><FONT size=-1>0 = data register not ready</FONT>
|
|
</TD></TR></TBODY></TABLE></TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>DIO:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>data input/output </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE cellPadding=2 width="100%">
|
|
<TBODY>
|
|
<TR>
|
|
<TD width="50%"><FONT size=-1>1 = controller ? CPU</FONT> </TD>
|
|
<TD><FONT size=-1>0 = CPU ? controller</FONT>
|
|
</TD></TR></TBODY></TABLE></TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>NDMA:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>non-DMA mode </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE cellPadding=2 width="100%">
|
|
<TBODY>
|
|
<TR>
|
|
<TD width="50%"><FONT size=-1>1 = controller not in DMA mode</FONT>
|
|
</TD>
|
|
<TD><FONT size=-1>0 = controller in DMA mode</FONT>
|
|
</TD></TR></TBODY></TABLE></TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>BUSY:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>instruction (device busy) </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE cellPadding=2 width="100%">
|
|
<TBODY>
|
|
<TR>
|
|
<TD width="50%"><FONT size=-1>1 = active</FONT> </TD>
|
|
<TD><FONT size=-1>0 = not active</FONT> </TD></TR></TBODY></TABLE></TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>ACTD, ACTC, ACTB, ACTA:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>drive D, C, B, A in positioning mode
|
|
</STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE cellPadding=2 width="100%">
|
|
<TBODY>
|
|
<TR>
|
|
<TD width="50%"><FONT size=-1>1 = active</FONT> </TD>
|
|
<TD><FONT size=-1>0 = not active</FONT>
|
|
</TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR><BR>
|
|
<P>The MSR is read-only, and contains the controller's status information. This
|
|
register can be read whatever else the controller is doing. </P>
|
|
<P>It should be noted that this register is different from status registers
|
|
ST0-ST3, which contain data concerning the last command executed. These
|
|
registers are accessed via the data registers. </P>
|
|
<P>Bit 7 (MRQ) indicates whether the controller is ready to receive or send data
|
|
or commands via the data register. </P>
|
|
<P>DIO is used to provide an indication of whether the controller is expecting
|
|
to receive data from the CPU, or if it wants to output data to the CPU. </P>
|
|
<P>If the controller is set up to use DMA channel 2 to transfer data to or from
|
|
main memory, the NDMA bit is not set. If this bit is set, data transfer is
|
|
carried out exclusively by means of read or write commands to the data register.
|
|
In this case, the controller issues a hardware interrupt every time that it
|
|
either expects to receive or wants to supply a data byte. </P>
|
|
<P>Bit 4 indicates whether the controller is busy or not. If the bit is set, the
|
|
controller is currently executing a command. </P>
|
|
<P>Bits 0-3 indicate which (if any) drive is currently in the process of
|
|
positioning it's read/write heads, or being recalibrated. </P>
|
|
<P>Note that the delay waiting for the controller to be ready for a read or
|
|
write can be as much as 175µs on an Intel controller, and longer on older
|
|
controllers. </P>
|
|
<P><STRONG>Example: </STRONG><BR>To test whether the controller is ready to
|
|
receive commands and data, it is necessary to test MRQ and DIO. This involves
|
|
reading the port, masking the bits, and doing a comparison on the result (to
|
|
test the values of the bits). </P>
|
|
<P>In assembly language, this is can be written as: <BR><BR></P><PRE><STRONG><FONT size=+2>
|
|
mrqloop:
|
|
mov dx,03f4h
|
|
in al,dx
|
|
and al,0c0h
|
|
cmp al,080h
|
|
jne mrqloop</FONT></STRONG>
|
|
</PRE><BR>
|
|
<P>This code will keep looping until the controller says that it is ready to
|
|
receive data. Note that if the controller is expecting to output data to the
|
|
CPU, this code will not spot that. You would need to add another couple of lines
|
|
of code if you need to check for both possibilities (In general, you would know
|
|
from previous commands whether the controller should be expecting or offering
|
|
data, and so only need to check for one condition). </P>
|
|
<HR>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H3><A name=Data>Data Register </A></H3>
|
|
<P>The data register is an 8 bit register, like each of the other registers,
|
|
which provides indirect access to a stack of registers. A command can be one to
|
|
nine bytes in length, and the first byte tells the controller how many more
|
|
bytes to expect. The controller sends the command bytes to the correct registers
|
|
in it's stack, saving the programmer from the need to use a separate index
|
|
register, as is the case in some other devices (e.g. some VGA registers). </P>
|
|
<P>Some controllers, such as the i82077A, have a buffer, with a programmable
|
|
threshold, allowing the data to be transferred several bytes at a time. This
|
|
helps to speed up the transfer of data and commands, as well as reducing the
|
|
response time seen on the µPD765. </P>
|
|
<P>Following some of the commands, the values in the status registers are
|
|
returned. The layout of the status registers follows, with the <A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#Commands">commands
|
|
</A>being listed at the end of this document. </P>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4><A name=Status0>Status Register </A>ST0 </H4>
|
|
<P align=center><IMG alt="image of Status Register 0" height=136
|
|
src="floppy.files/ST0.gif" title="Status Register 0" width=260> </P>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>IC <SUB>1 </SUB>,IC <SUB>0
|
|
</SUB>:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>interrupt code</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE cellPadding=2 width="100%">
|
|
<TBODY>
|
|
<TR>
|
|
<TD vAlign=top><FONT size=-1>00 = </FONT> </TD>
|
|
<TD><FONT size=-1>normal termination; <BR>command terminated without
|
|
any errors</FONT> </TD></TR>
|
|
<TR>
|
|
<TD vAlign=top><FONT size=-1>01 = </FONT> </TD>
|
|
<TD><FONT size=-1>abnormal termination; <BR>the controller started
|
|
execution of the command, but couldn't terminate it correctly</FONT>
|
|
</TD></TR>
|
|
<TR>
|
|
<TD vAlign=top><FONT size=-1>10 = </FONT> </TD>
|
|
<TD><FONT size=-1>invalid command; <BR>the controller could not
|
|
start command execution</FONT> </TD></TR>
|
|
<TR>
|
|
<TD vAlign=top><FONT size=-1>11 = </FONT> </TD>
|
|
<TD><FONT size=-1>abnormal termination by polling; <BR>drive became
|
|
not ready</FONT> </TD></TR></TBODY></TABLE></TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>SE:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>seek end </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>The controller has completed a seek or a calibration
|
|
command, <BR>or has correctly executed a read or write command which has
|
|
an implicit seek</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>UC:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>unit check </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>Set if the drive faults or if a recalibrate cannot find
|
|
track 0 after 79 pulses.</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>NR:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>drive not ready </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>HD:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>head currently active </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><FONT size=-1>1 = </FONT> </TD>
|
|
<TD><FONT size=-1>head 1</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><FONT size=-1>0 = </FONT> </TD>
|
|
<TD><FONT size=-1>head 0</FONT> </TD></TR></TBODY></TABLE></TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>US <SUB>1 </SUB>, US <SUB>0 </SUB></FONT>:
|
|
</STRONG></TD>
|
|
<TD><FONT size=-1><STRONG>currently selected drive (unit select)
|
|
</STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><FONT size=-1>00 = </FONT> </TD>
|
|
<TD><FONT size=-1>drive 0 (A:)</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><FONT size=-1>01 = </FONT> </TD>
|
|
<TD><FONT size=-1>drive 1 (B:)</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><FONT size=-1>10 = </FONT> </TD>
|
|
<TD><FONT size=-1>drive 2 (C:)</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><FONT size=-1>11 = </FONT> </TD>
|
|
<TD><FONT size=-1>drive 3 (D:)</FONT>
|
|
</TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4>Status Register ST1 </H4>
|
|
<P align=center><IMG alt="image of Status Register 1" height=136
|
|
src="floppy.files/ST1.gif" title="Status Register 1" width=260> </P>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>EN:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>End of Cylinder </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>Set when the sector count exceeds the number of sectors
|
|
on a track. <BR>i.e. the controller attempts to access a sector after the
|
|
last sector of a cylinder.</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>xx:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>bit unused </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>value always equal to 0</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>DE:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>data error </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>Set if the controller detected an error in the ID
|
|
address field or the data field of a sector</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>TO:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>time-out </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>Set for a data overrun; <BR>No signal received from the
|
|
DMA controller or CPU within the required time period.</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>NDAT:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>no data </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD align=right vAlign=top><STRONG><FONT
|
|
size=-1>Set if: </FONT></STRONG> </TD>
|
|
<TD><FONT size=-1>The addressed sector in a <I>read sector </I>or
|
|
<I>read deleted sector </I>cannot be found <BR>by the
|
|
controller.</FONT> </TD></TR>
|
|
<TR>
|
|
<TD align=right vAlign=top><FONT size=-1><STRONG>OR:
|
|
</STRONG> </FONT> </TD>
|
|
<TD><FONT size=-1>The controller cannot read the ID address mark in
|
|
response to a <I>read ID </I>command <BR>without error.</FONT>
|
|
</TD></TR>
|
|
<TR>
|
|
<TD align=right vAlign=top><STRONG><FONT
|
|
size=-1>OR: </FONT></STRONG> </TD>
|
|
<TD><FONT size=-1>The controller cannot correctly determine the
|
|
sequence of sectors in a <I>read track </I><BR>command</FONT>
|
|
</TD></TR></TBODY></TABLE></TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>NW:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>not writable </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>Set if the disk in the selected drive is write protected
|
|
while the controller attempts to <BR>execute a write command.</FONT>
|
|
</TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>NID:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>no address mark </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD align=right vAlign=top><STRONG><FONT
|
|
size=-1>Set if: </FONT></STRONG> </TD>
|
|
<TD><FONT size=-1>The ID address mark was not found after one
|
|
complete disk revolution</FONT> </TD></TR>
|
|
<TR>
|
|
<TD align=right vAlign=top><STRONG><FONT
|
|
size=-1>OR: </FONT></STRONG> </TD>
|
|
<TD><FONT size=-1>The controller could not find: <BR></FONT>
|
|
<DL>
|
|
<DD><FONT size=-1>a data address mark DAM</FONT>
|
|
<DD><FONT size=-1>a deleted data address mark DAM <BR>on the
|
|
specified track.</FONT>
|
|
</DD></DL></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4>Status Register ST2 </H4>
|
|
<P align=center><IMG alt="image of Status Register 2" height=136
|
|
src="floppy.files/ST2.gif" title="Status Register 2" width=260> </P>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>xx:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>bit unused </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>value always equal to 0</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>DADM:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>deleted address mark </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD align=right vAlign=top><STRONG><FONT size=-1>Set
|
|
if: </FONT></STRONG> </TD>
|
|
<TD><FONT size=-1>A deleted data address mark DAM is detected when a
|
|
<I>read sector </I>command is <BR>being executed.</FONT> </TD></TR>
|
|
<TR>
|
|
<TD align=right vAlign=top><STRONG><FONT
|
|
size=-1>OR: </FONT></STRONG> </TD>
|
|
<TD><FONT size=-1>A valid data address mark DAM is detected when a
|
|
<I>read deleted sector </I>command <BR>is being executed.</FONT>
|
|
</TD></TR></TBODY></TABLE></TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>CRCE:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>CRC error in data field </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>Set if a CRC error was detected in the data field of the
|
|
sector.</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>WCYL:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>wrong cylinder </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>Set if the track address in the controller and the track
|
|
address in the ID address mark are <BR>different.</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>SEQ:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>seek equal </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD align=right vAlign=top><STRONG><FONT
|
|
size=-1>Set if:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1>controller is a µPD765 and the condition <I>seek
|
|
equal </I>is fulfilled</FONT> </TD></TR>
|
|
<TR>
|
|
<TD align=right vAlign=top><STRONG><FONT
|
|
size=-1>else:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1>SGL is not used, this field is always equal to
|
|
0</FONT> </TD></TR></TBODY></TABLE></TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>SERR:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>seek error </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD align=right vAlign=top><STRONG><FONT
|
|
size=-1>Set if:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1>controller is a µPD765 and the controller did not
|
|
find the corresponding sector when <BR>seeking on the
|
|
cylinder.</FONT> </TD></TR>
|
|
<TR>
|
|
<TD align=right vAlign=top><STRONG><FONT
|
|
size=-1>else:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1>SERR is not used, this field is always equal to
|
|
0</FONT> </TD></TR></TBODY></TABLE></TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>BCYL:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>bad cylinder </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>This field indicates that the track address in the ID
|
|
address mark differs from the track <BR>address in the controller. <BR>The
|
|
value equals <STRONG>ffh </STRONG>, indicating a bad track with a physical
|
|
error, according to the IBM soft <BR>sector format.</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>NDAM:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>not data address mark DAM </STRONG></FONT></TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>Set if the controller cannot find a valid or deleted
|
|
data address mark DAM.</FONT> </TD></TR></TBODY></TABLE><BR><BR>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4>Status Register ST3 </H4>
|
|
<P align=center><IMG alt="image of Status Register 3" height=136
|
|
src="floppy.files/ST3.gif" title="Status Register 3" width=260> </P>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>ESIG:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>error</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD align=right vAlign=top><STRONG><FONT
|
|
size=-1>Set if:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1>controller is a µPD765 and the drives error signal
|
|
is active <BR>i.e. an error has occurred</FONT> </TD></TR>
|
|
<TR>
|
|
<TD align=right vAlign=top><STRONG><FONT
|
|
size=-1>else:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1>ESIG is not used and is always equal to 0</FONT>
|
|
</TD></TR></TBODY></TABLE></TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>WPDR:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>write protection</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>Set if the disk is write protected (indicates the
|
|
write-protection line is active).</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>RDY:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>ready</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD align=right vAlign=top><STRONG><FONT
|
|
size=-1>Set if:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1>controller is a µPD765 and the drive is ready
|
|
(indicates the ready signal of the <BR>drive is active).</FONT>
|
|
</TD></TR>
|
|
<TR>
|
|
<TD align=right vAlign=top><STRONG><FONT
|
|
size=-1>else:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1>RDY is not used and this field is always
|
|
set</FONT> </TD></TR></TBODY></TABLE></TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>TRK0:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>track 0</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>The head is above track 0 (the TRK0 signal of the drive
|
|
is active).</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>DSDR:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>double sided drive</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>The drive is double sided (indicates the DSDR signal is
|
|
active).</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>HDDR:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>head</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>This bit indicates the status of the HDSEL signal of the
|
|
drive: <BR>1 = head 1 active, <BR>0 = head 0 active</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>DS1, DS0:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>drive select</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>Both bits indicate the select signals DS1 and DS0 of the
|
|
drive: <BR>00 = drive 0 (A:) <BR>01 = drive 1 (B:) <BR>10 = drive 2 (C:)
|
|
<BR>11 = drive 3 (D:) <BR></FONT></TD></TR></TBODY></TABLE><BR><BR>
|
|
<HR>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H3><A name=DIR>Digital Input Register </A></H3>
|
|
<P align=center>DIR (AT) <BR><IMG alt="image of Digital Input Register (AT)"
|
|
height=136 src="floppy.files/DIR_(AT).gif" title="Digital Input Register (AT)"
|
|
width=260> <BR></P>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD align=middle>DIR (PS/2 except Model 30) <BR><IMG
|
|
alt="image of Digital Input Register (PS/2 except Model 30)" height=136
|
|
src="floppy.files/DIR_(PS2_except_model_30).gif"
|
|
title="Digital Input Register (PS/2 except Model 30)" width=260> </TD>
|
|
<TD align=middle>DIR (PS/2 Model 30) <BR><IMG
|
|
alt="image of Digital Input Register (PS/2 Model 30)" height=136
|
|
src="floppy.files/DIR_(PS2_model_30).gif"
|
|
title="Digital Input Register (PS/2 Model 30)" width=260>
|
|
</TD></TR></TBODY></TABLE><BR>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>CHAN:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Disk Change</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD>
|
|
<TABLE cellPadding=2 width="100%">
|
|
<TBODY>
|
|
<TR>
|
|
<TD><FONT size=-1>1 = disk changed since last command</FONT> </TD>
|
|
<TD><FONT size=-1>0 = disk not changed</FONT>
|
|
</TD></TR></TBODY></TABLE></TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>RAT1, RAT2:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Data Rate</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>00 = 500 kbits/s <BR>01 = 300 kbits/s <BR>10 = 250
|
|
kbits/s <BR>11 = 1Mbits/s</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1><A style="TEXT-DECORATION: overline">HiDe
|
|
</A></FONT></STRONG></TD>
|
|
<TD><STRONG><FONT size=-1>High-density Rate</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>1 = data rate 250kbits/s or 300 kbits/s <BR>0 = data
|
|
rate 1Mbits/s or 500 kbits/s</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>DMA:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Value of DMA bit in DOR</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>NOPR:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Value of NOPR bit in Control Configuration
|
|
Register</FONT></STRONG> </TD></TR></TBODY></TABLE><BR><BR>
|
|
<P>This register is available only in the AT and the PS/2, and is read only. The
|
|
above diagrams show that there are 3 different configurations for this register,
|
|
differing in the AT, PS/2 and PS/2 Model 30. These registers all allow you to
|
|
detect a disk change by reading bit 7, with additional information available for
|
|
the PS/2 and Model 30 variants. </P>
|
|
<P>For each of the registers, when bit 7 is set, it indicates that the disk has
|
|
been changed since the last command was executed. This can be used by a driver
|
|
to speed up access to data, by buffering of data. When buffering data, if the
|
|
disk has not been changed, required sectors can already be in memory when
|
|
requested (for example, a whole track can be read at a time and stored in a
|
|
buffer, including the possibility of storing multiple tracks when sectors are
|
|
read from different cylinders). If this happens, the data only needs reading
|
|
from disk when a new cylinder is being read from, or when the disk has been
|
|
changed. </P>
|
|
<P>In the PS/2 and Model 30, the registers also contain information about the
|
|
current data transfer rate. For Model 30, this information is read from bits 1
|
|
and 0, while in the other PS/2 models, the data is read from bits 2 and 1. This
|
|
data can be used when the rate is set through the Control Configuration Register
|
|
to check that the rate has been correctly set, or to check what rate the
|
|
controller is set to at any time. </P>
|
|
<P>In PS/2 models other than Model 30, bit 1 can be read to help determine
|
|
whether the controller is set to a high or low data transfer rate for a high
|
|
density disk. </P>
|
|
<P>In Model 30, bit 3 corresponds to bit 3 of the DOR. bit 2 corresponds to bit
|
|
2 of the CCR (only used in this model). In both these cases, the value is
|
|
read-only in the DIR, and can be written to in the corresponding register. </P>
|
|
<HR>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H3><A name=CCR>Control Configuration Register </A></H3><BR align="center">
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD align=middle>CCR (AT and PS/2) <BR><IMG
|
|
alt="image of Control Configuration Register (AT and PS/2)" height=136
|
|
src="floppy.files/CCR_(AT_PS2).gif"
|
|
title="Control Configuration Register (AT and PS/2)" width=260> </TD>
|
|
<TD align=middle>CCR (PS/2 Model 30) <BR><IMG
|
|
alt="image of Control Configuration Register (PS/2 Model 30)" height=136
|
|
src="floppy.files/CCR_(PS2_Model_30).gif"
|
|
title="Control Configuration Register (PS/2 Model 30)" width=260>
|
|
</TD></TR></TBODY></TABLE><BR>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>RAT1, RAT0:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Data Transfer Rate</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>00 = 500kbits/s <BR>01 = 300kbits/s <BR>10 = 250kbits/s
|
|
<BR>11 - 1Mbits/s</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>NOPR:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>(No) Precompensate</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = Precompensation Enabled (standard) <BR>1 = No
|
|
Precompensation</FONT> </TD></TR></TBODY></TABLE><BR><BR>
|
|
<P align=center><STRONG>Data Transfer Rates </STRONG><BR><BR></P>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>Rate</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Disk <BR>Capacity</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Size</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Drive <BR>Capacity</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD><FONT size=-1>250 kbits/s</FONT> </TD>
|
|
<TD><FONT size=-1>360 kbyte</FONT> </TD>
|
|
<TD><FONT size=-1>5?</FONT> </TD>
|
|
<TD><FONT size=-1>360 kbyte</FONT> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>720 kbyte</FONT> </TD>
|
|
<TD><FONT size=-1>3?</FONT> </TD>
|
|
<TD><FONT size=-1>1.44 Mbytes</FONT> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>720 kbyte</FONT> </TD>
|
|
<TD><FONT size=-1>3?</FONT> </TD>
|
|
<TD><FONT size=-1>720 kbyte</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><FONT size=-1>300 kbits/s</FONT> </TD>
|
|
<TD><FONT size=-1>720 kbyte</FONT> </TD>
|
|
<TD><FONT size=-1>3?</FONT> </TD>
|
|
<TD><FONT size=-1>720 kbyte</FONT> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>360 kbyte</FONT> </TD>
|
|
<TD><FONT size=-1>5?</FONT> </TD>
|
|
<TD><FONT size=-1>1.2 Mbyte</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><FONT size=-1>500 kbits/s</FONT> </TD>
|
|
<TD><FONT size=-1>1.2 Mbyte</FONT> </TD>
|
|
<TD><FONT size=-1>5?</FONT> </TD>
|
|
<TD><FONT size=-1>1.2 Mbyte</FONT> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>1.44 Mbytes</FONT> </TD>
|
|
<TD><FONT size=-1>3?</FONT> </TD>
|
|
<TD><FONT size=-1>1.44 Mbytes</FONT> </TD></TR></TBODY></TABLE><BR><BR>
|
|
<P>In the AT and all PS/2 models, the data transfer rate can be set through bits
|
|
1 and 0 of the CCR. Valid transfer rates are shown in the table immediately
|
|
above, and the table below the diagram shows what values need to be sent to
|
|
these two fields to set the appropriate rate. </P>
|
|
<P>In the Model 30 it is also possible to program the precompensation through
|
|
bit 2 of this register. The default is for precompensate to be enabled, with
|
|
this field set to 0. Setting the field to 1 turns precompensation off. </P>
|
|
<HR>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H3><A name=Status>Status Registers A and B </A></H3><BR align="center">
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD align=middle>Status Register A (PS/2) <BR><IMG
|
|
alt="image of Status Register A (PS/2)" height=136
|
|
src="floppy.files/StatusA1.gif" title="Status Register A (PS/2)"
|
|
width=260> </TD>
|
|
<TD align=middle>Status Register A (Model 30) <BR><IMG
|
|
alt="image of Status Register A (Model 30)" height=136
|
|
src="floppy.files/StatusA2.gif" title="Status Register A (Model 30)"
|
|
width=260> </TD></TR>
|
|
<TR>
|
|
<TD align=middle vAlign=top>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>INTP:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Interrupt Pending</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = interrupt signal inactive <BR>1 =
|
|
active</FONT> </TD></TR>
|
|
<TR>
|
|
<TD vAlign=top><STRONG><FONT size=-1><A
|
|
style="TEXT-DECORATION: overline">DRV2 </A>:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1>0 = 2 drives connected <BR>1 = one drive
|
|
only</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>STEP:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Stepper Pulse</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = no pulse <BR>1 = pulse is submitted</FONT>
|
|
</TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1><A style="TEXT-DECORATION: overline">TRK0
|
|
</A>:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Track 0</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = head not above track 0 <BR>1 = head above
|
|
track 0</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>HDSL:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Head Select</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = head 0 <BR>1 = head 1</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1><A style="TEXT-DECORATION: overline">INDX
|
|
</A>:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Index Mark</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = detected <BR>1 = not detected</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1><A style="TEXT-DECORATION: overline">WP
|
|
</A>:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Write Protection</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = disk write protected <BR>1 = not write
|
|
protected</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>DIR:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Direction of Head</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = outwards (to smaller cylinder numbers) <BR>1 =
|
|
inwards (to higher cylinder numbers)</FONT> </TD></TR></TBODY></TABLE></TD>
|
|
<TD align=middle vAlign=top>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>INTP:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Interrupt Pending</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = interrupt signal inactive <BR>1 =
|
|
active</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>DRQ:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>DMA Request</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = not active <BR>1 = active</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>STEP:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Step Pulse</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = pulse is submitted <BR>1 = no pulse</FONT>
|
|
</TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>TRK0:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Track 0</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = head above track 0 <BR>1 = head not above
|
|
track 0</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1><A style="TEXT-DECORATION: overline">HDSL
|
|
</A>:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Head Select</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = head 1 <BR>1 = head 0</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>INDX:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Index Mark</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = not detected <BR>1 = detected</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>WP:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Write Protection</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = disk not write protected <BR>1 = disk write
|
|
protected</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1><A style="TEXT-DECORATION: overline">DIR
|
|
</A>:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Head Direction</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = inwards (to higher cylinder numbers) <BR>1 =
|
|
outwards (to lower cylinder numbers)</FONT>
|
|
</TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR><BR><BR title=""
|
|
align="center">
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD align=middle>Status Register B (PS/2) <BR><IMG
|
|
alt="image of Status Register B (PS/2)" height=136
|
|
src="floppy.files/StatusB1.gif" title="Status Register B (PS/2)"
|
|
width=260> </TD>
|
|
<TD align=middle>Status Register B (Model 30) <BR><IMG
|
|
alt="image of Status Register B (Model 30)" height=136
|
|
src="floppy.files/StatusB2.gif" title="Status Register B (Model 30)"
|
|
width=260> </TD></TR>
|
|
<TR>
|
|
<TD align=middle vAlign=top>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>DS0:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Drive Select</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = drive other than 0 <BR>1 = drive 0</FONT>
|
|
</TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>WDAT:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Write Data</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = no data can be written to drive <BR>1 = data
|
|
can be transferred to drive</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>RDAT:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Read Data</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = no data can be read from drive <BR>1 = data
|
|
can be transferred from drive</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>WE:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Write Enabled</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = head is set to read data <BR>1 = head is
|
|
activated for data writes</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>MOT1, MOT0:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Motor of drive 1, 0</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = motor is switched off <BR>1 = motor is
|
|
switched on</FONT> </TD></TR></TBODY></TABLE></TD>
|
|
<TD align=middle vAlign=top>
|
|
<TABLE>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1><A style="TEXT-DECORATION: overline">DRV2
|
|
</A>:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1>0 = two drives connected <BR>1 = only one drive
|
|
connected</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1><A style="TEXT-DECORATION: overline">DS1
|
|
</A>:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Drive Select 1</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = drive 1 selected <BR>1 = drive not
|
|
selected</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1><A style="TEXT-DECORATION: overline">DS0
|
|
</A>:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Drive Select 0</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = drive 0 selected <BR>1 = drive not
|
|
selected</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>WDAT:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Write Data</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = no data can be written <BR>1 = data can be
|
|
transferred to the drive</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>RDAT:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Read Data</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = data cannot be read from drive <BR>1 =
|
|
data can be read from drive</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>WE:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Write Enabled</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = head enabled to read data <BR>1 = head enabled
|
|
to write data</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1><A style="TEXT-DECORATION: overline">DS3
|
|
</A>:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Drive Select 3</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = drive 3 selected <BR>1 = drive not
|
|
selected</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1><A style="TEXT-DECORATION: overline">DS2
|
|
</A>:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Drive Select 2</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD></TD>
|
|
<TD><FONT size=-1>0 = drive 2 selected <BR>1 = drive not
|
|
selected</FONT> </TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
|
|
<P>These registers are read only, and only available on the PS/2. </P>
|
|
<P>By the use of the two status registers A and B on a PS/2, it is possible to
|
|
read the status of the control lines between the floppy controller and drive.
|
|
Register bits <A style="TEXT-DECORATION: overline">DRV2 </A>, <A
|
|
style="TEXT-DECORATION: overline">TRK0 </A>, <A
|
|
style="TEXT-DECORATION: overline">INDX </A>, <A
|
|
style="TEXT-DECORATION: overline">WP </A>and RDAT indicate the status of the
|
|
corresponding data lines. Note that the bit values vary between Status Registers
|
|
A and B on Model 30 and other PS/2 models. Some of the values are also
|
|
detectable through other registers and the Status Registers readable through the
|
|
data register on the AT. </P>
|
|
<HR>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H3><A name=DRSR>Data Rate Select Register </A></H3><BR>
|
|
<P>If you know of any source of information on this register (available only on
|
|
the PS/2), please <A href="mailto:debs@savah.freeserve.co.uk">e-mail </A>me with
|
|
details. As soon as I am able to find the information, it will be added to this
|
|
page. </P>
|
|
<HR color=gray SIZE=3>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H2 align=center><A name=Commands>Command Set </A></H2>
|
|
<P>There are a total of 13 commands available on the µPD765 and compatible FDCs.
|
|
A further 4 commands are available on the 8207x controllers. </P>
|
|
<P>The <I>sector identification </I>consists of the cylinder, head, sector
|
|
number and sector size. This tells the controller the position and number of
|
|
sectors to perform this command on. </P>
|
|
<P>All commands and status bytes are transferred via the data register, at port
|
|
37fh or 377h. Before the command can be written or the status byte read, it is
|
|
necessary to read the MRQ bit in the main status register. This determines
|
|
whether the data register is ready to supply or receive a byte. It is also
|
|
necessary to fix the drive format prior to any read, write or format operation.
|
|
</P>
|
|
<P>For most data transfers, DMA is used. Although the programming of the DMA is
|
|
beyond the scope of this document, I have provided some <A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#DMA_Prog">example
|
|
code </A>showing how to set up the DMA for writing a single sector from a floppy
|
|
disk drive to main memory. All data transfers concern all sectors from the start
|
|
sector to the end of the track. The operation can be stopped earlier by either
|
|
setting the command byte <I>track length/max. sector number </I>to a value which
|
|
indicates the last sector to be operated on, or setting the count value of the
|
|
DMA controller so that it issues a TC (Terminal Count) signal after the required
|
|
number of sectors are transfered (the latter method is demonstrated in the <A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#DMA_Prog">example
|
|
DMA code </A>below). </P>
|
|
<P>If you want a command to be executed on both heads, you need to set the
|
|
Multiple Track Bit. This tells the controller to operate on the programmed head
|
|
first, then to carry out the same command from the start of the other head. </P>
|
|
<P>Once the command has been completed, the status registers ST0-3 return
|
|
information which can help you either confirm correct execution of the command,
|
|
or determine the cause of an error. </P>
|
|
<P>The commands fall into 3 categories. Data transfer commands and control
|
|
commands are available on all controllers. The extended commands are only
|
|
available on the AT or PS/2. </P>
|
|
<HR>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H3>List of Valid Commands </H3><!---------------------------------------------------------------------------------------->
|
|
<H4><A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#datacom">Data
|
|
Transfer Commands </A></H4><PRE>Command Name | Function
|
|
-----------------------------------------
|
|
read complete track | x2h
|
|
write sector | x5h
|
|
read sector | x6h
|
|
write deleted sector | x9h
|
|
read deleted sector | xch
|
|
format track | xdh
|
|
</PRE><!---------------------------------------------------------------------------------------->
|
|
<H4><A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#ctrlcom">Control
|
|
Commands </A></H4><PRE>Command Name | Function
|
|
-----------------------------------------
|
|
fix drive data | x3h
|
|
check drive status | x4h
|
|
calibrate drive | x7h
|
|
check interrupt status | x8h
|
|
read sector ID | xah
|
|
seek/park head | xfh
|
|
invalid command | all invalid opcodes
|
|
</PRE><!---------------------------------------------------------------------------------------->
|
|
<H4><A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#extcom">Extended
|
|
Commands </A></H4><PRE>Command Name | Function
|
|
-----------------------------------------------
|
|
register summary | 0fh
|
|
determine controller version | x10h
|
|
verify | x16h
|
|
seek relative | 1xfh
|
|
</PRE>
|
|
<P>In each of the above, 'x' refers to bits 7-5 of byte 0 of the command. Note
|
|
that in the <I>seek relative </I>command, x refers to just bits 6 and 5, as bit
|
|
7 is always set to 1. The remainder of the function number refers to bits 4-0.
|
|
Bit 4 is only used on the AT and PS/2, in 2 of the extended commands. </P>
|
|
<P>The function number given is the first byte of the command it applies to. The
|
|
commands vary in size from 1 to 9 bytes, and the controller knows from the
|
|
function number how many more bytes to expect. For example, if the first byte
|
|
received by the data register is <B>66h </B>, in which the upper 5 bits are 06h,
|
|
the controller knows that you are sending a <I>read sector </I>command, and it
|
|
expects 8 more bytes from the CPU. Additionally, you do nto need to worry about
|
|
which of the internal registers each byte of any command has to be directed to,
|
|
as the controller does that for you. </P>
|
|
<P>Fields common to many of the commands include the following: </P>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD vAlign=top><STRONG><FONT size=-1>M:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>Multi-track operation </STRONG><BR>1 = carry out
|
|
operation on both tracks of programmed cylinder. <BR>0 = carry out
|
|
operation on single track.</FONT> </TD></TR>
|
|
<TR>
|
|
<TD vAlign=top><STRONG><FONT size=-1>F:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>FM/MFM mode </STRONG><BR>1 = operate in MFM
|
|
(double density) mode (default) <BR>0 = operate in FM (single density)
|
|
mode</FONT> </TD></TR>
|
|
<TR>
|
|
<TD vAlign=top><STRONG><FONT size=-1>S:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>Skip mode </STRONG><BR>1 = skip deleted data
|
|
address marks, 0 = do not skip</FONT> </TD></TR>
|
|
<TR>
|
|
<TD vAlign=top><STRONG><FONT size=-1>HD:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>head number </STRONG><BR>(always equal to head
|
|
address in byte 3 of all commands using a sector ID)</FONT> </TD></TR>
|
|
<TR>
|
|
<TD vAlign=top><STRONG><FONT size=-1>DR1,DR0:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>Drive: </STRONG><BR>00 = drive 0 (A); 01 = drive
|
|
1 (B); 10 = drive 2 (C); 11 = drive 3 (D)</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>Cylinder, Head, Sector Number:</FONT></STRONG>
|
|
</TD>
|
|
<TD><STRONG><FONT size=-1>Address of first sector to read.</FONT></STRONG>
|
|
</TD></TR>
|
|
<TR>
|
|
<TD vAlign=top><STRONG><FONT size=-1>Sector size code:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>Sector size </STRONG>= 128 * 2^x where x is the
|
|
value in this field. <BR>eg If this field is 2 (the default), sector size
|
|
= 128 * 2^2 = 512 bytes</FONT> </TD></TR>
|
|
<TR>
|
|
<TD vAlign=top><STRONG><FONT size=-1>Track length/Max sector
|
|
number:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>Number of sectors per track or max. sector
|
|
number </STRONG>to operate command on.</FONT> </TD></TR>
|
|
<TR>
|
|
<TD vAlign=top><STRONG><FONT size=-1>Length of GAP 3:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1>Standard value = 42, minimal value = 32 (5?)
|
|
<BR>standard value = 27 (3?)</FONT> </TD></TR>
|
|
<TR>
|
|
<TD vAlign=top><STRONG><FONT size=-1>Data length:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>length of data to read </STRONG><BR>in bytes
|
|
(only valid if sector size = 0, else equal 0ffh)</FONT>
|
|
</TD></TR></TBODY></TABLE>
|
|
<HR>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H3><A name=datacom>Data Transfer Commands </A></H3>
|
|
<P>These are the commands used to transfer data between a disk and main memory,
|
|
or to format a track. </P>
|
|
<P>Each of these commands returns its' <A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#Results1">results
|
|
</A>in the same format, which is only described for the <I>read track
|
|
</I>command. </P>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4>Read Track (x2h) </H4>
|
|
<P align=center><IMG alt="Image of Read Track Command" height=240
|
|
src="floppy.files/rdtrk.gif" title="Read Track Command" width=300> </P>
|
|
<P>When a <I>read track </I>command is issued, the data of a single complete
|
|
track is read. The sector specification in the command phase is ignored for this
|
|
command, and the reading starts with the first sector after the index address
|
|
mark <STRONG>IDAM </STRONG>, reading sector by sector (paying no attention to
|
|
the logical sector number given in the ID address mark), until the end of the
|
|
track is reached. </P>
|
|
<P>The track is treated as a contigusous data block, and the read buffer in main
|
|
memory should be large enough to store this amount of data. Also, multi-track
|
|
operations are not allowed with this command. If you want to read the same track
|
|
on both heads, you have to send the command twice, unlike other read commands
|
|
which allow for multi-track operations with a single command. </P>
|
|
<H4><A name=Results1>Results Phase </A></H4>
|
|
<P align=center><IMG alt="image of Data Transfer Command Results Phase"
|
|
height=175 src="floppy.files/Result1.gif"
|
|
title="Data Transfer Command Results Phase" width=290> </P>
|
|
<TABLE>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>ST0, ST1, ST2:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#Status0">Status
|
|
Registers </A>0 to 2</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>Cylinder, head, sector number, sector
|
|
size:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1>Sector ID. (see table below)</FONT>
|
|
</TD></TR></TBODY></TABLE><BR><STRONG>Sector ID in the Result Phase
|
|
</STRONG><BR>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR vAlign=top>
|
|
<TD><STRONG><FONT size=-1>M </FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>HD <SUB>prog </SUB> </FONT></STRONG>
|
|
</TD>
|
|
<TD><STRONG><FONT size=-1>Last sector affected <BR>by
|
|
command</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Cylinder </FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Head </FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Sector </FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>Sector Size</FONT></STRONG> </TD></TR>
|
|
<TR>
|
|
<TD><FONT size=-1>0</FONT> </TD>
|
|
<TD><FONT size=-1>0</FONT> </TD>
|
|
<TD><FONT size=-1>before end of track</FONT> </TD>
|
|
<TD><FONT size=-1>cyl <SUB>prog </SUB></FONT></TD>
|
|
<TD><FONT size=-1>HD <SUB>prog </SUB></FONT></TD>
|
|
<TD><FONT size=-1>sec <SUB>prog </SUB></FONT></TD>
|
|
<TD><FONT size=-1>siz <SUB>prog </SUB></FONT></TD></TR>
|
|
<TR>
|
|
<TD><FONT size=-1>0</FONT> </TD>
|
|
<TD><FONT size=-1>0</FONT> </TD>
|
|
<TD><FONT size=-1>end of track</FONT> </TD>
|
|
<TD><FONT size=-1>cyl <SUB>prog+1 </SUB></FONT></TD>
|
|
<TD><FONT size=-1>HD <SUB>prog </SUB></FONT></TD>
|
|
<TD><FONT size=-1>1</FONT> </TD>
|
|
<TD><FONT size=-1>siz <SUB>prog </SUB></FONT></TD></TR>
|
|
<TR>
|
|
<TD><FONT size=-1>0</FONT> </TD>
|
|
<TD><FONT size=-1>1</FONT> </TD>
|
|
<TD><FONT size=-1>before end of track</FONT> </TD>
|
|
<TD><FONT size=-1>cyl <SUB>prog </SUB></FONT></TD>
|
|
<TD><FONT size=-1>HD <SUB>prog </SUB></FONT></TD>
|
|
<TD><FONT size=-1>sec <SUB>prog </SUB></FONT></TD>
|
|
<TD><FONT size=-1>siz <SUB>prog </SUB></FONT></TD></TR>
|
|
<TR>
|
|
<TD><FONT size=-1>0</FONT> </TD>
|
|
<TD><FONT size=-1>1</FONT> </TD>
|
|
<TD><FONT size=-1>end of track</FONT> </TD>
|
|
<TD><FONT size=-1>cyl <SUB>prog+1 </SUB></FONT></TD>
|
|
<TD><FONT size=-1>HD <SUB>prog </SUB></FONT></TD>
|
|
<TD><FONT size=-1>1</FONT> </TD>
|
|
<TD><FONT size=-1>siz <SUB>prog </SUB></FONT></TD></TR>
|
|
<TR>
|
|
<TD><FONT size=-1>1</FONT> </TD>
|
|
<TD><FONT size=-1>0</FONT> </TD>
|
|
<TD><FONT size=-1>before end of track</FONT> </TD>
|
|
<TD><FONT size=-1>cyl <SUB>prog </SUB></FONT></TD>
|
|
<TD><FONT size=-1>HD <SUB>prog </SUB></FONT></TD>
|
|
<TD><FONT size=-1>sec <SUB>prog </SUB></FONT></TD>
|
|
<TD><FONT size=-1>siz <SUB>prog </SUB></FONT></TD></TR>
|
|
<TR>
|
|
<TD><FONT size=-1>1</FONT> </TD>
|
|
<TD><FONT size=-1>0</FONT> </TD>
|
|
<TD><FONT size=-1>end of track</FONT> </TD>
|
|
<TD><FONT size=-1>cyl <SUB>prog </SUB></FONT></TD>
|
|
<TD><FONT size=-1>HD <SUB>prog </SUB></FONT></TD>
|
|
<TD><FONT size=-1>1</FONT> </TD>
|
|
<TD><FONT size=-1>siz <SUB>prog </SUB></FONT></TD></TR>
|
|
<TR>
|
|
<TD><FONT size=-1>1</FONT> </TD>
|
|
<TD><FONT size=-1>1</FONT> </TD>
|
|
<TD><FONT size=-1>before end of track</FONT> </TD>
|
|
<TD><FONT size=-1>cyl <SUB>prog </SUB></FONT></TD>
|
|
<TD><FONT size=-1>(inverse of) HD <SUB>prog </SUB></FONT></TD>
|
|
<TD><FONT size=-1>sec <SUB>prog </SUB></FONT></TD>
|
|
<TD><FONT size=-1>siz <SUB>prog </SUB></FONT></TD></TR>
|
|
<TR>
|
|
<TD><FONT size=-1>1</FONT> </TD>
|
|
<TD><FONT size=-1>1</FONT> </TD>
|
|
<TD><FONT size=-1>end of track</FONT> </TD>
|
|
<TD><FONT size=-1>cyl <SUB>prog+1 </SUB></FONT></TD>
|
|
<TD><FONT size=-1>(inverse of) HD <SUB>prog </SUB></FONT></TD>
|
|
<TD><FONT size=-1>1</FONT> </TD>
|
|
<TD><FONT size=-1>siz <SUB>prog </SUB></FONT></TD></TR></TBODY></TABLE><BR>
|
|
<TABLE>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><FONT size=-1>HD <SUB>prog </SUB>:</FONT> </TD>
|
|
<TD><FONT size=-1>programmed head </FONT> </TD>
|
|
<TD><FONT size=-1>sec <SUB>prog </SUB>:</FONT> </TD>
|
|
<TD><FONT size=-1>programmed sector</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><FONT size=-1>cyl <SUB>prog </SUB>:</FONT> </TD>
|
|
<TD><FONT size=-1>programmed cylinder </FONT> </TD>
|
|
<TD><FONT size=-1>siz <SUB>prog </SUB>:</FONT> </TD>
|
|
<TD><FONT size=-1>programmed sector size</FONT>
|
|
</TD></TR></TBODY></TABLE><BR><BR>
|
|
<P>The Sector ID consists of Cylinder, Head, Sector and Sector Size. Given the
|
|
values programmed for M (multi-track) and HD (head number), the values for the
|
|
sector ID in the results phase indicate whether the last sector affected was the
|
|
last sector of the command or not. </P>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4>Write Sector (x5h) </H4>
|
|
<P align=center><IMG alt="Image of Write Sector Command" height=240
|
|
src="floppy.files/wrsec.gif" title="Write Sector Command" width=300> </P>
|
|
<P>The <I>write sector </I>command transfers one or more sectors from main
|
|
memory to the controller, from where it is transferred to the disk. As the
|
|
controller writes each sector, it also writes a valid <I>data address mark
|
|
</I>to the disk. This command can operate on both heads, starting from the first
|
|
sector of the second head after reaching the end of the first head. </P>
|
|
<P>The <A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#Results1">results
|
|
phase </A>is the same as for the read track command. </P>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4>Read Sector (x6h) </H4>
|
|
<P align=center><IMG alt="Image of Read Sector Command" height=240
|
|
src="floppy.files/rdsec.gif" title="Read Sector Command" width=300> </P>
|
|
<P>The <I>read sector </I>command reads one or more sectors with a valid data
|
|
address mark from the disk, and transfers the data into main memory. This
|
|
command can operate on both heads. </P>
|
|
<P>The <A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#Results1">results
|
|
phase </A>is the same as for the read track command. </P>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4>Write Deleted Sector (x9h) </H4>
|
|
<P align=center><IMG alt="Image of Write Deleted Sector Command" height=240
|
|
src="floppy.files/wrdelsec.gif" title="Write Deleted Sector Command" width=300>
|
|
</P>
|
|
<P>The <I>write deleted sector </I>command is the same as the <I>write sector
|
|
</I>command, except that for each sector written a <I>deleted data address mark
|
|
</I>is written instead of the normal data address mark. </P>
|
|
<P>The <A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#Results1">results
|
|
phase </A>is the same as for the read track command. </P>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4>Read Deleted Sector (xch) </H4>
|
|
<P align=center><IMG alt="Image of Read Deleted Sector Command" height=240
|
|
src="floppy.files/rddelsec.gif" title="Read Deleted Sector Command" width=300>
|
|
</P>
|
|
<P>The <I>read deleted sector </I>command is the same as the <I>read sector
|
|
</I>command, except that only sectors with a deleted data address mark can be
|
|
read. All sectors with valid data address marks will be ignored. </P>
|
|
<P>The <A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#Results1">results
|
|
phase </A>is the same as for the read track command. </P>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4>Format Track (xdh) </H4>
|
|
<P align=center><IMG alt="Image of Format Track Command" height=180
|
|
src="floppy.files/fmttrk.gif" title="Format Track Command" width=300> </P>
|
|
<P>This command formats a single track. A 4 byte format buffer must be provided
|
|
for each sector of the track. The buffer holds the sector ID of the
|
|
corresponding sector. The format buffer should be large enough to hold the data
|
|
required for all sectors of the track. The <A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#fmtbuf">buffer
|
|
format </A>is shown below. </P>
|
|
<P>For ease of use, the DMA controller should be programmed to enable the
|
|
controller to read the format buffer via DMA channel 2. Alternatively, the
|
|
format data can be transferred by the use of interrupt-driven data exchange. The
|
|
controller issues a hardware interrupt before fromatting each sector. The
|
|
handler can then transfer the 4 byte format information for the next sector to
|
|
be formatted. </P>
|
|
<P>The formatting begins once the drive has provided a signal on the IDX line,
|
|
indicating the beginning of the track. Sectors are formatted continuously until
|
|
the drive passes the same signal again, this time indicating the end of the
|
|
track (note that the start and end of the track are at the same point, marked by
|
|
an index hole on the disk). </P>
|
|
<P>For the format command, the length of the GAP field is larger than when
|
|
reading or writing data. Unless i find any further information on the GAP
|
|
length, I can only include the default GAP length in this document. </P>
|
|
<P>The <A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#Results1">results
|
|
phase </A>is the same as for the read track command. </P>
|
|
<H4><A name=fmtbuf>Format buffer for one sector </A></H4>
|
|
<P align=center><IMG alt="Image of Format Buffer" height=120
|
|
src="floppy.files/fmtbuf.gif" title="Format Buffer" width=170> </P>
|
|
<P>In the above table, <I>Sector Size </I>uses the same codes as for each of the
|
|
commands described above. </P>
|
|
<HR>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H3><A name=ctrlcom>Control Commands </A></H3>
|
|
<P>This set of commands includes various miscellaneous commands relating to the
|
|
status of a disk or drive, including seeking to a new cylinder and responding to
|
|
invalid commands. </P>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4>Fix Drive Data (x3h) </H4>
|
|
<P align=center><IMG alt="image of Fix Drive Data Command" height=120
|
|
src="floppy.files/FixData.gif" title="Fix Drive Data Command" width=300> </P>
|
|
<TABLE>
|
|
<TBODY>
|
|
<TR>
|
|
<TD vAlign=top><STRONG><FONT size=-1>NDM:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>Non-DMA Mode </STRONG><BR>0 = Data Transfer via
|
|
DMA <BR>1 = Data Transfer not via DMA</FONT>
|
|
</TD></TR></TBODY></TABLE><BR><BR><BR align="center">
|
|
<TABLE>
|
|
<TBODY>
|
|
<TR>
|
|
<TD align=middle>Step Rate [ms] <BR><IMG alt="image of Step Rate"
|
|
height=190 src="floppy.files/StepRate.gif" title="Step Rate" width=220>
|
|
</TD>
|
|
<TD align=middle>Head Unload Time [ms] <BR><IMG
|
|
alt="image of Head Unload Time" height=190 src="floppy.files/HdUnload.gif"
|
|
title="Head Unload Time" width=220> </TD>
|
|
<TD align=middle>Head Load Time [ms]<IMG alt="image of Head Load Time"
|
|
height=190 src="floppy.files/HeadLoad.gif" title="Head Load Time"
|
|
width=220> </TD></TR></TBODY></TABLE><BR><BR>
|
|
<P>This command is used to pass mechanical control data to the controller for
|
|
the connected drives. It should be noted, as shown in the bottom 3 diagrams,
|
|
that the values are also dependent on the data transfer rate, which in the AT
|
|
and PS/2 is set in the <A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#CCR">control
|
|
configuration register </A>. </P>
|
|
<P>This command doesn't have a result phase. </P>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4>Check Drive Status (x4h) </H4>
|
|
<P align=center><IMG alt="image of Check Drive Status Command" height=100
|
|
src="floppy.files/ChkDrvStatus.gif" title="Check Drive Status Command"
|
|
width=300> </P>
|
|
<P>This command provides status information relating to the state of the
|
|
connected drives. </P>
|
|
<H4>Result Phase </H4>
|
|
<P align=center><IMG alt="image of Check Drive Status Command Result Phase"
|
|
height=50 src="floppy.files/Result2.gif"
|
|
title="Check Drive Status Command Result Phase" width=290> </P>
|
|
<P>Status Register 3 contains drive information. </P>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4>Calibrate Drive (x7h) </H4>
|
|
<P align=center><IMG alt="image of Calibrate Drive Command" height=100
|
|
src="floppy.files/Calibrate.gif" title="Calibrate Drive Command" width=300> </P>
|
|
<P>This command is used to position the read/write head to cylinder 0. If a seek
|
|
error occurs in the course of a sector access, the head can be moved to an
|
|
absolute cylinder to recalibrate the drive. </P>
|
|
<P>This command doesn't return a result phase, but after cmopletion an interrupt
|
|
is issued. To check the status information of this command, you should issue a
|
|
<I>check interrupt status </I>cmomand to determine the commands status
|
|
information. </P>
|
|
<P>When the controller sees this command, it sets the DIR signal to 0, and
|
|
passes the drive up to 79 step pulses. After each of these pulses, the
|
|
controller checks the TRK0 signal. If it is active (htat is, the head is on
|
|
track 0), the controller sets the SE bit in Status Register 0, and aborts the
|
|
command. If TRK0 is not active after 79 step pulses, the controller sets bits SE
|
|
and EC in Status Register 0, and terminates the command. </P>
|
|
<P>To calibrate the drive, you may have to issue several calibration commands,
|
|
especially if the drive being calibrated has more than 80 tracks. After
|
|
completion of the command, you should always check whether the head is correctly
|
|
positioned over track 0, using the <I>check interrupt status </I>command. A
|
|
calibration is always necessary after a power up, to initialise the head
|
|
position correctly. </P>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4><A name=chkint>Check Interrupt Status </A>(x8h) </H4>
|
|
<P align=center><IMG alt="image of Check Interrupt Status Command" height=80
|
|
src="floppy.files/ChkInts.gif" title="Check Interrupt Status Command" width=300>
|
|
</P>
|
|
<P>This command is used to check status infromation about the state of the
|
|
controller in the result phase when the controller has returned an interrupt.
|
|
</P>
|
|
<P>The interrupt signal is reset by this command, which also determines the
|
|
source of the interrupt via status register ST0. If the command is issued with
|
|
no interrupts pending, a value of 80h is returned in ST0, corresponding to the
|
|
message <I>invalid command </I>. </P>
|
|
<P>Interrupts are issued in the following cases: </P><PRE>At the beginning of the result phase of the commands:
|
|
read sector
|
|
read deleted sector
|
|
write sector
|
|
write deleted sector
|
|
read track
|
|
format track
|
|
read sector ID
|
|
verify
|
|
|
|
After completion of the following commands without a result phase:
|
|
calibrate drive
|
|
seek
|
|
seek relative
|
|
|
|
For data exchange between main memory and controller when interrupt-driven data exchange
|
|
is active and the controller is not using DMA.
|
|
</PRE>
|
|
<H4>Result Phase </H4>
|
|
<P align=center><IMG alt="Image of Check Interrupt Status Command Return Phase"
|
|
height=70 src="floppy.files/Result3.gif"
|
|
title="Check Interrupt Status Command Return Phase" width=290> </P>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4>Read Sector ID (xah) </H4>
|
|
<P align=center><IMG alt="#image of Read Sector ID Command" height=100
|
|
src="floppy.files/RdSecID.gif" title="Read Sector ID Command" width=300> </P>
|
|
<P>This command is used to read the Sector ID of the first ID address mark the
|
|
controller is able to detect. Using this command, it is possible to determine
|
|
the current position of the read/write head. If no ID address mark can be read
|
|
in one complete disk revolution, the controller issues an error message,
|
|
detected from the values returned in ST0-2. </P>
|
|
<H4>Result Phase </H4>
|
|
<P align=center><IMG alt="image of Read Sector ID Command Result Phase"
|
|
height=175 src="floppy.files/Result1.gif"
|
|
title="Read Sector ID Command Result Phase" width=290> </P>
|
|
<P>The values in the sector ID are calculated in the same way as for the <A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#Results1">result
|
|
phase </A>of the read track command. </P>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4>Seek/Park Head (xfh) </H4>
|
|
<P align=center><IMG alt="image of Park Head Command" height=120
|
|
src="floppy.files/ParkHead.gif" title="Park Head Command" width=300> </P>
|
|
<P>The Seek Head command, sometimes called the Park Head command, moves the
|
|
read/write head to the specified cylinder. When the controller receives this
|
|
command, it compares the programmed cylinder number and the current cylinder
|
|
number. The direction signal (DIR) is set, and step pulses are issued until the
|
|
two cylinder numbers match. </P>
|
|
<P>This command has no result phase. To verify successful completion of the
|
|
command, it is necessary to check the head position immediately after completion
|
|
of the command, using the <A
|
|
href="http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html#chkint">check
|
|
interrupt status </A>command. </P>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4>invalid command (all invalid opcodes) </H4>
|
|
<P align=center><IMG alt="image of Invalid Opcode Command" height=80
|
|
src="floppy.files/Invalid.gif" title="Invalid Opcode Command" width=300> </P>
|
|
<P>Whenever an invalid opcode is detected, the controller switches to a standby
|
|
state, and bit 7 of ST0 is set. The same happens if <I>check interrupt status
|
|
</I>is issued with no interrupts pending. </P>
|
|
<H4>Result Phase </H4>
|
|
<P align=center><IMG alt="image of Invalid Opcode Command Result Phase"
|
|
height=50 src="floppy.files/Result4.gif"
|
|
title="Invalid Opcode Command Result Phase" width=290> </P>
|
|
<HR>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H3><A name=extcom>Extended Commands </A></H3>
|
|
<P>These commands are not available on all controllers, being introduced in the
|
|
AT and PS/2. If the controller does not support any of these commands, it will
|
|
treat them as invalid commands. </P>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4>Register Summary (0fh) </H4>
|
|
<P align=center><IMG alt="image of Register Summary" height=80
|
|
src="floppy.files/RegDump.gif" title="Register Summary" width=300> </P>
|
|
<P>This command returns the values read from the internal controller registers.
|
|
</P>
|
|
<H4>Result Phase </H4>
|
|
<P align=center><IMG alt="image of Register Summary Command Result Phase"
|
|
height=175 src="floppy.files/Result5.gif"
|
|
title="Register Summary Command Result Phase" width=290> </P>
|
|
<TABLE>
|
|
<TBODY>
|
|
<TR>
|
|
<TD vAlign=top><STRONG><FONT
|
|
size=-1>Current Cylinder DR0, DR1, DR2 DR3:</FONT></STRONG>
|
|
</TD>
|
|
<TD><FONT size=-1>Cylinder on drive 0, 1, 2, 3 where read/write head is
|
|
currently positioned.</FONT> </TD></TR>
|
|
<TR>
|
|
<TD vAlign=top><STRONG><FONT size=-1>step time,
|
|
head unload time, head load time:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1>mechanical characteristics set by the <I>fix drive data
|
|
</I>command</FONT> </TD></TR>
|
|
<TR>
|
|
<TD vAlign=top><STRONG><FONT size=-1>NDM:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>non-DMA mode </STRONG><BR>1 = DMA disabled <BR>0
|
|
= DMA enabled</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>number of sectors/track length</FONT></STRONG>
|
|
</TD>
|
|
<TD><FONT size=-1><STRONG>number of sectors per track
|
|
</STRONG></FONT></TD></TR></TBODY></TABLE><BR><BR>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4>Determine Controller Version (10h) </H4>
|
|
<P align=center><IMG alt="image of Get Controller Version Command" height=80
|
|
src="floppy.files/CtrVer.gif" title="Get Controller Version Command" width=300>
|
|
</P>
|
|
<P>This command determines whether there is a controller present which supports
|
|
the extended commands. If the controller does not support the extended commands,
|
|
this command is treated as an invalid opcode, and an error message is returned.
|
|
</P>
|
|
<H4>Result Phase </H4>
|
|
<P align=center><IMG
|
|
alt="image of Determine Controller Version Command Result Phase" height=50
|
|
src="floppy.files/Result6.gif"
|
|
title="Determine Controller Version Command Result Phase" width=290> </P>
|
|
<P>This result is only returned if an extended controller is installed. </P>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4>Verify (x16h) </H4>
|
|
<P align=center><IMG alt="image of Verify Command" height=240
|
|
src="floppy.files/Verify.gif" title="Verify Command" width=300> </P>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD vAlign=top><STRONG><FONT size=-1>EC:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>enable count value </STRONG><BR>1 = command byte
|
|
8 specifies the number of sectors to verify <BR>0 = command byte 8
|
|
specifies the data length, if sector size = 0</FONT> </TD></TR>
|
|
<TR>
|
|
<TD vAlign=top><STRONG><FONT
|
|
size=-1>data length/verify sectors: </FONT></STRONG>
|
|
</TD>
|
|
<TD><FONT size=-1><STRONG>If EC = 0 and sector size = 0:
|
|
</STRONG><BR> length of data to verify, in bytes.
|
|
<BR><STRONG>Else: </STRONG><BR> number of sectors
|
|
to verify.</FONT> </TD></TR></TBODY></TABLE><BR><BR>
|
|
<P>This command is similar to the read command, except that it doesn't transfer
|
|
data to main memory. One or more sectros with valid DAMs are read from the disk,
|
|
and their CRC is calculated. This value is compared to the read CRC, inorder to
|
|
check the internal consistency of the data. As no data is transferred, the
|
|
command cannot be aborted by a TC signal from the DMA controller. However, if
|
|
youset the EC bit to 1, the controller issues an implicit TC signal when the
|
|
count value in <I>data length/verify sectors </I>is decremented to 0. In that
|
|
case, <I>data length/verify sectors </I>indicates the number of sectors to be
|
|
verified. A value of 0 in this byte tells the controller to check 256 sectors.
|
|
When EC is set to 0, <I>data length/verify data </I>should be set to ffh. </P>
|
|
<H4>Result Phase </H4>
|
|
<P align=center><IMG alt="image of Verify Command Result Phase" height=175
|
|
src="floppy.files/Result1.gif" title="Verify Command Result Phase" width=290>
|
|
</P>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4>Seek Relative (1xfh) </H4>
|
|
<P align=center><IMG alt="image of Seek Relative Command" height=120
|
|
src="floppy.files/SeekRel.gif" title="Seek Relative Command" width=300> </P>
|
|
<TABLE cellPadding=2>
|
|
<TBODY>
|
|
<TR>
|
|
<TD vAlign=top><STRONG><FONT size=-1>DIR:</FONT></STRONG> </TD>
|
|
<TD><FONT size=-1><STRONG>Step Direction </STRONG><BR>1 = inward (to
|
|
larger cylinder numbers) <BR>0 = outward (to smaller cylinder
|
|
numbers)</FONT> </TD></TR>
|
|
<TR>
|
|
<TD><STRONG><FONT size=-1>cylinder step:</FONT></STRONG> </TD>
|
|
<TD><STRONG><FONT size=-1>number of cylinders to step</FONT></STRONG>
|
|
</TD></TR></TBODY></TABLE><BR><BR>
|
|
<P>This command is sued to move the read/write head relative to the current
|
|
cylinder. There is no result phase for this command, but its' result can be
|
|
checked through the use of either the <I>read sector ID </I>or the <I>register
|
|
dump </I>command. </P>
|
|
<HR color=gray SIZE=3>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H2 align=center>Sample code </H2>
|
|
<HR SIZE=1>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<H4><A name=DMA_Prog>Initialise DMA for writing a single sector from FDC to main
|
|
memory </A></H4><!---------------------------------------------------------------------------------------->
|
|
<P>Please note that this code was added in a hurry and has not yet been tested.
|
|
I wanted to publish this page with DMA initialisation code before going on
|
|
holiday. The code will be tested and, if necessary, adjusted, late in June
|
|
(1999), when I get back from my vacation. </P><PRE><STRONG>
|
|
;*******************************************************************************
|
|
; This code expects to receive the data buffer address in ES:BX
|
|
;
|
|
; ES: Buffer segment
|
|
; BX: Buffer offset
|
|
;
|
|
; The address is a 20 bit segmented address, calculated from Segment*16 + Offset
|
|
;
|
|
; Bits 19-16 of the address form the entry for the DMA page entry
|
|
; Bits 15-8 of the address form the high-order byte for the DMA address register
|
|
; Bits 7-0 of the address form the low-order byte for the DMA address register
|
|
;
|
|
; For more information on this, it will be necessary to read other literature
|
|
; specifically targetting the DMA controller.
|
|
;*******************************************************************************
|
|
|
|
disable_dma1: ; disable DMA 1
|
|
|
|
mov al, 14h ; output 14h to the command register to disable and
|
|
out 08h, al ; initialise the DMA controller
|
|
|
|
mode: ; set up DMA transfer mode for channel 2
|
|
mov al, 56h ; set up for a single write transfer to main memory
|
|
out 0bh, al ; using DMA channel 2
|
|
; for a read, output 5ah
|
|
|
|
get_address: ; get the buffer address, and split into component parts
|
|
; as required by the DMA controller.
|
|
mov ax, es ; load buffer segment into AX
|
|
mov cl, 04h ;
|
|
shl ax, cl ; shift value in ax left 4 times
|
|
add ax, bx ; add offest + buffer. AX now contains high and low
|
|
; for the DMA address register.
|
|
jc carry ; if carry is set, jump to carry
|
|
|
|
no_carry:
|
|
mov bx, es ; load segment of buffer into BX
|
|
mov cl, 04h ;
|
|
shr bh, cl ; shift right BH 4 times. BH now contains the value
|
|
; for the DMA page segment
|
|
jmp buffer_address; output the buffer address
|
|
|
|
carry:
|
|
mov bx, es ; load segment of buffer into BX
|
|
mov cl, 04h ;
|
|
shr bh, cl ; shift right BH 4 times. BH now contains the high
|
|
; bits of the segment
|
|
adc bh, 00h
|
|
|
|
buffer_address: ; output the address to the DMA controller
|
|
out 0ch, al ; reset flip-flop. I am not sure what this does,
|
|
; but my reference shows this as necessary.
|
|
out 04h, al ; output low order address byte to address register
|
|
mov al, ah ;
|
|
out 04h, al ; output high-order address byte to address register
|
|
mov al, bh ;
|
|
out 81h, al ; load page register with page value
|
|
|
|
count: ; set up count register
|
|
out 0ch, al ; reset flip-flop
|
|
mov al, 0ffh ;
|
|
out 05h, al ;
|
|
mov al, 01h ;
|
|
out 05h, al ; load 511 into count register (to read one sector)
|
|
; it should be noted that for multiple transfers, the
|
|
; second value output to port 05h is equivalent to
|
|
; (2*number of sectors)-1
|
|
|
|
release_channel:
|
|
mov al, 02h
|
|
out 0ah, al ; release channel 2
|
|
|
|
enable_dma1: ; enable DMA 1
|
|
mov al, 10h
|
|
out 08h, al ; this is the value for enabling the DMA for the mode required
|
|
</STRONG>
|
|
</PRE>
|
|
<HR>
|
|
<!---------------------------------------------------------------------------------------->
|
|
<P>Once I have written my own floppy disk drivers for the operating system I am
|
|
working on, I'll add a link to that. Until then, I'm happy to continue replying
|
|
to any questions I receive by email. Please note that I am a programmer, not a
|
|
hardware expert, and as such may not be able to answer questions that relate to
|
|
how to produce hardware using a FDC. </P>
|
|
<P>If you have any comments on the content of this page, including errors and
|
|
typos, please contact me:</P>
|
|
<P align=center>
|
|
<SCRIPT language=javascript><!--
|
|
var contact = "<img src=../../../mail-me.jpg>"
|
|
var localhost = "Webmistress"
|
|
var emailHost = "dwiles"
|
|
var domain = "demon.co.uk"
|
|
var subject = "FDC"
|
|
document.write("<a href=" + "mail" + "to:" + localhost + "@" + emailHost + "." + domain +
|
|
"?" + "Subject" + "=" + subject + ">" + contact + "</a>" + ".")
|
|
//-->
|
|
</SCRIPT>
|
|
</P></BASEFONT></BODY></HTML>
|