3634 lines
100 KiB
HTML
3634 lines
100 KiB
HTML
|
||
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||
<html>
|
||
<head>
|
||
<title>
|
||
Programming the NEC µPD765 and Intel 82072/7 Floppy Disk
|
||
Controller
|
||
</title>
|
||
</head>
|
||
<!---------------------------------------------------------------------------------------->
|
||
<body onResize='vPQ2()' onLoad='vPQ1()' onScroll='vPQ2()' onMove='vPQ2()' bgcolor="#ffffcc" link="red" vlink="purple" alink="olive">
|
||
<SCRIPT>
|
||
<!--
|
||
var vPQ3=0;
|
||
var vPQ4=62;
|
||
var vPQ5=470;
|
||
var vPQ6=12;
|
||
var vPQ7=200;
|
||
var vPQ8=0;
|
||
var vPQ9=0;
|
||
var vPQ0,vPQ10;
|
||
var vPQ11,vPQ12,vPQ13,vPQ8,vPQ14;
|
||
var vPQ15,vPQ16,vPQ17=500;
|
||
function vPQ1()
|
||
{
|
||
if(vPQ8==1)
|
||
return true;
|
||
if(document.all)
|
||
{
|
||
vPQ11=document.all("vPQ18").style;
|
||
vPQ12=document.all("vPQ19").style;
|
||
vPQ20=vPQ4+vPQ3+0;
|
||
vPQ21=vPQ5+vPQ6+vPQ3;
|
||
vPQ22='visible';
|
||
vPQ23='hidden';
|
||
}
|
||
else
|
||
{
|
||
vPQ22='show';
|
||
vPQ23='hide';
|
||
vPQ11=document.vPQ18;
|
||
vPQ12=document.vPQ19;
|
||
vPQ20=vPQ4+vPQ3+15;
|
||
vPQ21=vPQ5+vPQ6+vPQ3+15;
|
||
}
|
||
if(vPQ0=="00880204")
|
||
{
|
||
if(document.all)
|
||
{
|
||
vPQ12.display='none';
|
||
vPQ11.display='none';
|
||
}
|
||
return true;
|
||
}
|
||
if(document.all)
|
||
{
|
||
if(document.body.clientHeight<vPQ7||document.body.clientWidth<vPQ7)
|
||
return true;
|
||
}
|
||
else if(document.layers)
|
||
{
|
||
if(window.innerHeight<vPQ7||window.innerWidth<vPQ7)
|
||
return true;
|
||
}
|
||
vPQ8=1;
|
||
vPQ2();
|
||
vPQ11.visibility=vPQ22;
|
||
if(document.layers)
|
||
vPQ24();
|
||
}
|
||
function vPQ24()
|
||
{
|
||
if(pageXOffset!=vPQ15||pageYOffset!=vPQ16)
|
||
{
|
||
vPQ15=pageXOffset;
|
||
vPQ16=pageYOffset;
|
||
vPQ2();
|
||
if(vPQ17>=500)
|
||
{
|
||
vPQ17=20;
|
||
setTimeout("checkTime=500",1000);
|
||
}
|
||
}
|
||
vPQ10=setTimeout("vPQ24()",vPQ17);
|
||
}
|
||
function vPQ2()
|
||
{
|
||
if(!vPQ8)
|
||
return true;
|
||
if(document.all)
|
||
{
|
||
if(document.body.scrollHeight<document.body.clientHeight
|
||
||document.body.scrollTop<((document.body.scrollHeight-document.body.clientHeight)/2))
|
||
{
|
||
vPQ11.top=document.body.scrollTop+document.body.clientHeight-vPQ20;
|
||
vPQ12.top=document.body.scrollTop+document.body.clientHeight-vPQ20;
|
||
}
|
||
else
|
||
{
|
||
vPQ11.top=document.body.scrollTop+vPQ3;
|
||
vPQ12.top=document.body.scrollTop+vPQ3;
|
||
}
|
||
vPQ11.left=document.body.scrollLeft+document.body.clientWidth-vPQ21;
|
||
vPQ12.left=document.body.scrollLeft+document.body.clientWidth-vPQ21+vPQ5;
|
||
}
|
||
else if(document.layers)
|
||
{
|
||
if(window.pageYOffset<((window.outerHeight-window.innerHeight)/2))
|
||
{
|
||
vPQ11.top=window.pageYOffset+window.innerHeight-vPQ20;
|
||
vPQ12.top=window.pageYOffset+window.innerHeight-vPQ20;
|
||
}
|
||
else
|
||
{
|
||
vPQ11.top=window.pageYOffset+vPQ3;
|
||
vPQ12.top=window.pageYOffset+vPQ3;
|
||
}
|
||
vPQ11.left=window.pageXOffset+window.innerWidth-vPQ21;
|
||
vPQ12.left=window.pageXOffset+window.innerWidth-vPQ21+vPQ5;
|
||
}
|
||
}
|
||
function vPQ25()
|
||
{
|
||
vPQ9=1;
|
||
vPQ12.visibility=vPQ22;
|
||
vPQ11.visibility=vPQ23;
|
||
clearTimeout(vPQ14);
|
||
}
|
||
function vPQ26()
|
||
{
|
||
vPQ9=0;
|
||
vPQ12.visibility=vPQ23;
|
||
vPQ11.visibility=vPQ22;
|
||
}
|
||
//-->
|
||
</SCRIPT>
|
||
|
||
<DIV ID="vPQ19" STYLE="position: absolute; top: 0; left: 0; visibility: hidden; z-index: 2147483632;">
|
||
<table border=0 cellspacing=0 cellpadding=0 height=62 bgcolor="#EEEEEE">
|
||
<tr>
|
||
<td valign="top"><a href="" title="Click here to expand banner" onClick="vPQ26(); return false;"><img src="http://banner.easyspace.com/left.gif" width=12 height=12 border=0></a></td>
|
||
</tr>
|
||
<tr>
|
||
<td valign="bottom"><a href="http://www.easyspace.com/" target="_blank"><img src="http://banner.easyspace.com/littlelogo.gif" border=0></a></td>
|
||
</tr>
|
||
</table>
|
||
</DIV>
|
||
<DIV ID="vPQ18" STYLE="position: absolute; top: 0; left: 0; z-index: 2147483647; visibility: hidden">
|
||
<table border=0 cellspacing=0 cellpadding=0 height=62>
|
||
<tr>
|
||
<td rowspan=2 valign="top"><A TARGET="_new" HREF="http://www.easyspace.com/redirect.cgi?type=BNR-ESBIZ-468-2.gif&url=http://www.easyspace.com/domains/dotbiz.html"><IMG SRC="http://banner.easyspace.com/ESBIZ-468-2.gif?r=0.0294060870073736" width=468 height=60 border=0 ALT="Nothing personal. Just business."></A></td>
|
||
<td bgcolor="#EEEEEE" valign="top"><a href="" title="Click here to shrink banner" onClick="vPQ25(); return false;"><img src="http://banner.easyspace.com/right.gif" width=12 height=12 border=0></a></td>
|
||
</tr>
|
||
<tr>
|
||
<td bgcolor="#EEEEEE" valign="bottom"><a href="http://www.easyspace.com/" target="_blank"><img src="http://banner.easyspace.com/littlelogo.gif" border=0></a></td>
|
||
</tr>
|
||
</table>
|
||
</DIV>
|
||
|
||
<basefont face="Arial">
|
||
<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
||
<tr>
|
||
<td>
|
||
<h1 align="center">
|
||
Programming Floppy Disk Controllers
|
||
</h1>
|
||
<br>
|
||
<p title="" align="center">
|
||
[
|
||
<a href="../../../index.html">Home
|
||
</a>]
|
||
[
|
||
<a title="Programming Home" href="../../index.html">Programming
|
||
</a>]
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
<hr size="3" color="gray">
|
||
<br>
|
||
<br>
|
||
<!---------------------------------------------------------------------------------------->
|
||
<table width="100%" border="0" cellspacing="0" cellpadding="10">
|
||
<tr>
|
||
<td width="10" valign="top">[
|
||
<a href="../../../Index.html">Home
|
||
</a>]
|
||
<br>
|
||
[
|
||
<a title="Programming Home" href="../../Index.html">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="#Overview">Overview
|
||
</a></li>
|
||
<li>
|
||
<a href="#Configuration">Configuration of an FDC on a
|
||
PC
|
||
</a></li>
|
||
<li>
|
||
<a href="#FDC Registers">FDC Registers
|
||
</a></li>
|
||
<li>
|
||
<a href="#Commands">Command Set
|
||
</a></li>
|
||
</ol>
|
||
<br>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
<hr size="3" color="gray"><!---------------------------------------------------------------------------------------->
|
||
<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 size="3" color="gray">
|
||
<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 border="1" cellspacing="0" cellpadding="0" align="center">
|
||
<tr>
|
||
<td width="300"><EFBFBD>
|
||
</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><EFBFBD>
|
||
</td>
|
||
<td><EFBFBD>
|
||
</td>
|
||
<td><EFBFBD>
|
||
</td>
|
||
<td><EFBFBD>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>base address
|
||
</td>
|
||
<td>3f0h
|
||
</td>
|
||
<td>370h
|
||
</td>
|
||
<td><EFBFBD>
|
||
</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><EFBFBD>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>IRQ
|
||
</td>
|
||
<td>6
|
||
</td>
|
||
<td>6
|
||
</td>
|
||
<td><EFBFBD>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>INTR
|
||
</td>
|
||
<td>0eh
|
||
</td>
|
||
<td>0eh
|
||
</td>
|
||
<td><EFBFBD>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
<br>
|
||
<br>
|
||
<br>
|
||
<p>
|
||
Note that the controller can be configured differently from the
|
||
defaults for handling interrupts.
|
||
</p>
|
||
<hr size="3" color="gray">
|
||
<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="#DOR">Digital Output Register DOR
|
||
</a></li>
|
||
<li>
|
||
<a href="#MSR">Main Status Register
|
||
</a></li>
|
||
<li>
|
||
<a href="#Data">Data Register
|
||
</a></li>
|
||
</ol>AT Specific Registers:
|
||
<ol>
|
||
<li>
|
||
<a href="#DIR">Digital Input Register DIR
|
||
</a></li>
|
||
<li>
|
||
<a href="#CCR">Configuration Control Register
|
||
</a></li>
|
||
</ol>PS/2 Specific Registers:
|
||
<ol>
|
||
<li>
|
||
<a href="#Status">Status Register A
|
||
</a></li>
|
||
<li>
|
||
<a href="#Status">Status Register B
|
||
</a></li>
|
||
<li>
|
||
<a href="#DRSR">Data Rate Select Register
|
||
</a></li>
|
||
</ol>
|
||
<hr>
|
||
<h3>
|
||
<a name="DOR">Digital Output Register DOR
|
||
</a>
|
||
</h3>
|
||
<p align="center">
|
||
<img title="Digital Output Register" height="136" alt="image of Digital Output Register" src="./Gifs/DOR.gif" width="260">
|
||
</p>
|
||
<table width="550" cellpadding="2">
|
||
<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%">
|
||
<tr>
|
||
<td width="50%"><font size="-1">1 = Start motor</font>
|
||
</td>
|
||
<td><font size="-1">0 = Stop motor</font>
|
||
</td>
|
||
</tr>
|
||
</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%">
|
||
<tr>
|
||
<td width="50%"><font size="-1">1 = Enabled</font>
|
||
</td>
|
||
<td><font size="-1">0 = Disabled</font>
|
||
</td>
|
||
</tr>
|
||
</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%">
|
||
<tr>
|
||
<td width="50%"><font size="-1">1 = Controller enabled</font>
|
||
</td>
|
||
<td><font size="-1">0 = Execute controller reset</font>
|
||
</td>
|
||
</tr>
|
||
</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%">
|
||
<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>
|
||
</table>
|
||
</td>
|
||
</tr>
|
||
</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>
|
||
<dd>DMA = 1 (assuming you want to use DMA and interrupts)</dd>
|
||
<dd>REST = 1 (Controller enabled, otherwise no other commands will be
|
||
executed)</dd>
|
||
<dd>DR1,DR0 = 00 (Select drive A)</dd>
|
||
<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 title="Main Status Register" height="136" alt="image of Main Status Register" src="./Gifs/MSR.gif" width="260">
|
||
</p>
|
||
<table width="550" cellpadding="2">
|
||
<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%">
|
||
<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>
|
||
</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 width="100%" cellpadding="2">
|
||
<tr>
|
||
<td width="50%"><font size="-1">1 = controller ? CPU</font>
|
||
</td>
|
||
<td><font size="-1">0 = CPU ? controller</font>
|
||
</td>
|
||
</tr>
|
||
</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%">
|
||
<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>
|
||
</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%">
|
||
<tr>
|
||
<td width="50%"><font size="-1">1 = active</font>
|
||
</td>
|
||
<td><font size="-1">0 = not active</font>
|
||
</td>
|
||
</tr>
|
||
</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%">
|
||
<tr>
|
||
<td width="50%"><font size="-1">1 = active</font>
|
||
</td>
|
||
<td><font size="-1">0 = not active</font>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
</td>
|
||
</tr>
|
||
</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="#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 title="Status Register 0" height="136" alt="image of Status Register 0" src="./Gifs/ST0.gif" width="260">
|
||
</p>
|
||
<table cellpadding="2">
|
||
<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%">
|
||
<tr>
|
||
<td valign="top"><font size="-1">00<EFBFBD>=<3D></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<EFBFBD>=<3D></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<EFBFBD>=<3D></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<EFBFBD>=<3D></font>
|
||
</td>
|
||
<td><font size="-1">abnormal termination by polling;
|
||
<br>
|
||
drive became not ready</font>
|
||
</td>
|
||
</tr>
|
||
</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">
|
||
<tr>
|
||
<td><font size="-1">1<EFBFBD>=<3D></font>
|
||
</td>
|
||
<td><font size="-1">head 1</font>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td><font size="-1">0<EFBFBD>=<3D></font>
|
||
</td>
|
||
<td><font size="-1">head 0</font>
|
||
</td>
|
||
</tr>
|
||
</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">
|
||
<tr>
|
||
<td><font size="-1">00<EFBFBD>=<3D></font>
|
||
</td>
|
||
<td><font size="-1">drive 0 (A:)</font>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td><font size="-1">01<EFBFBD>=<3D></font>
|
||
</td>
|
||
<td><font size="-1">drive 1 (B:)</font>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td><font size="-1">10<EFBFBD>=<3D></font>
|
||
</td>
|
||
<td><font size="-1">drive 2 (C:)</font>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td><font size="-1">11<EFBFBD>=<3D></font>
|
||
</td>
|
||
<td><font size="-1">drive 3 (D:)</font>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
<br>
|
||
<br>
|
||
<hr size="1"><!---------------------------------------------------------------------------------------->
|
||
<h4>Status Register ST1
|
||
</h4>
|
||
<p align="center">
|
||
<img title="Status Register 1" height="136" alt="image of Status Register 1" src="./Gifs/ST1.gif" 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">
|
||
<tr>
|
||
<td valign="top" align="right"><strong><font size="-1">Set<EFBFBD>if:<3A></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 valign="top" align="right"><font size="-1"><strong> OR:
|
||
</strong> <20></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 valign="top" align="right"><strong><font size="-1">OR:<3A></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>
|
||
</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 valign="top" align="right"><strong><font size="-1">Set<EFBFBD>if:<3A></font></strong>
|
||
</td>
|
||
<td><font size="-1">The ID address mark was not
|
||
found after one complete disk revolution</font>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td valign="top" align="right"><strong><font size="-1">OR:<3A></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>
|
||
<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 title="Status Register 2" height="136" alt="image of Status Register 2" src="./Gifs/ST2.gif" width="260">
|
||
</p>
|
||
<table cellpadding="2">
|
||
<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">
|
||
<tr>
|
||
<td valign="top" align="right"><strong><font size="-1">Set if:<3A></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 valign="top" align="right"><strong><font size="-1">OR:<3A></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>
|
||
</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">
|
||
<tr>
|
||
<td valign="top" align="right"><strong><font size="-1">Set<EFBFBD>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 valign="top" align="right"><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>
|
||
</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">
|
||
<tr>
|
||
<td valign="top" align="right"><strong><font size="-1">Set<EFBFBD>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 valign="top" align="right"><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>
|
||
</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>
|
||
</table>
|
||
<br>
|
||
<br>
|
||
<hr size="1"><!---------------------------------------------------------------------------------------->
|
||
<h4>Status Register ST3
|
||
</h4>
|
||
<p align="center">
|
||
<img title="Status Register 3" height="136" alt="image of Status Register 3" src="./Gifs/ST3.gif" width="260">
|
||
</p>
|
||
<table cellpadding="2">
|
||
<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">
|
||
<tr>
|
||
<td valign="top" align="right"><strong><font size="-1">Set<EFBFBD>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 valign="top" align="right"><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>
|
||
</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">
|
||
<tr>
|
||
<td valign="top" align="right"><strong><font size="-1">Set<EFBFBD>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 valign="top" align="right"><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>
|
||
</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,<2C>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>
|
||
</table>
|
||
<br>
|
||
<br>
|
||
<hr><!---------------------------------------------------------------------------------------->
|
||
<h3>
|
||
<a name="DIR">Digital Input Register
|
||
</a>
|
||
</h3>
|
||
<p align="center">
|
||
DIR (AT)
|
||
<br>
|
||
<img title="Digital Input Register (AT)" height="136" alt="image of Digital Input Register (AT)" src="./Gifs/DIR_(AT).gif" width="260">
|
||
<br>
|
||
</p>
|
||
<table cellpadding="2">
|
||
<tr>
|
||
<td align="middle">DIR (PS/2 except Model 30)
|
||
<br>
|
||
<img title="Digital Input Register (PS/2 except Model 30)" height="136" alt="image of Digital Input Register (PS/2 except Model 30)" src="./Gifs/DIR_(PS2_except_model_30).gif" width="260">
|
||
</td>
|
||
<td align="middle">DIR (PS/2 Model 30)
|
||
<br>
|
||
<img title="Digital Input Register (PS/2 Model 30)" height="136" alt="image of Digital Input Register (PS/2 Model 30)" src="./Gifs/DIR_(PS2_model_30).gif" width="260">
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
<br>
|
||
<table cellpadding="2">
|
||
<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%">
|
||
<tr>
|
||
<td><font size="-1">1 = disk changed since last
|
||
command</font>
|
||
</td>
|
||
<td><font size="-1">0 = disk not changed</font>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong><font size="-1">RAT1,<2C>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>
|
||
</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">
|
||
<tr>
|
||
<td align="middle">CCR (AT and PS/2)
|
||
<br>
|
||
<img title="Control Configuration Register (AT and PS/2)" height="136" alt="image of Control Configuration Register (AT and PS/2)" src="./Gifs/CCR_(AT_PS2).gif" width="260">
|
||
</td>
|
||
<td align="middle">CCR (PS/2 Model 30)
|
||
<br>
|
||
<img title="Control Configuration Register (PS/2 Model 30)" height="136" alt="image of Control Configuration Register (PS/2 Model 30)" src="./Gifs/CCR_(PS2_Model_30).gif" width="260">
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
<br>
|
||
<table cellpadding="2">
|
||
<tr>
|
||
<td><strong><font size="-1">RAT1,<2C>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>
|
||
</table>
|
||
<br>
|
||
<br>
|
||
<p align="center">
|
||
<strong> Data Transfer Rates
|
||
</strong>
|
||
<br>
|
||
<br>
|
||
</p>
|
||
<table cellpadding="2">
|
||
<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<EFBFBD>kbyte</font>
|
||
</td>
|
||
<td><font size="-1">5¼"</font>
|
||
</td>
|
||
<td><font size="-1">360<EFBFBD>kbyte</font>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
</td>
|
||
<td><font size="-1">720<EFBFBD>kbyte</font>
|
||
</td>
|
||
<td><font size="-1">3½"</font>
|
||
</td>
|
||
<td><font size="-1">1.44<EFBFBD>Mbytes</font>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
</td>
|
||
<td><font size="-1">720<EFBFBD>kbyte</font>
|
||
</td>
|
||
<td><font size="-1">3½"</font>
|
||
</td>
|
||
<td><font size="-1">720<EFBFBD>kbyte</font>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td><font size="-1">300 kbits/s</font>
|
||
</td>
|
||
<td><font size="-1">720<EFBFBD>kbyte</font>
|
||
</td>
|
||
<td><font size="-1">3½"</font>
|
||
</td>
|
||
<td><font size="-1">720<EFBFBD>kbyte</font>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
</td>
|
||
<td><font size="-1">360<EFBFBD>kbyte</font>
|
||
</td>
|
||
<td><font size="-1">5¼"</font>
|
||
</td>
|
||
<td><font size="-1">1.2<EFBFBD><EFBFBD>Mbyte</font>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td><font size="-1">500 kbits/s</font>
|
||
</td>
|
||
<td><font size="-1">1.2<EFBFBD><EFBFBD>Mbyte</font>
|
||
</td>
|
||
<td><font size="-1">5¼"</font>
|
||
</td>
|
||
<td><font size="-1">1.2<EFBFBD><EFBFBD>Mbyte</font>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
</td>
|
||
<td><font size="-1">1.44<EFBFBD>Mbytes</font>
|
||
</td>
|
||
<td><font size="-1">3½"</font>
|
||
</td>
|
||
<td><font size="-1">1.44<EFBFBD>Mbytes</font>
|
||
</td>
|
||
</tr>
|
||
</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">
|
||
<tr>
|
||
<td align="middle">Status Register A (PS/2)
|
||
<br>
|
||
<img title="Status Register A (PS/2)" height="136" alt="image of Status Register A (PS/2)" src="./Gifs/StatusA1.gif" width="260">
|
||
</td>
|
||
<td align="middle">Status Register A (Model 30)
|
||
<br>
|
||
<img title="Status Register A (Model 30)" height="136" alt="image of Status Register A (Model 30)" src="./Gifs/StatusA2.gif" width="260">
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td valign="top" align="middle">
|
||
<table cellpadding="2">
|
||
<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>
|
||
</table>
|
||
</td>
|
||
<td valign="top" align="middle">
|
||
<table cellpadding="2">
|
||
<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>
|
||
</table>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
<br>
|
||
<br>
|
||
<br>
|
||
<br title="" align="center">
|
||
<table cellpadding="2">
|
||
<tr>
|
||
<td align="middle">Status Register B (PS/2)
|
||
<br>
|
||
<img title="Status Register B (PS/2)" height="136" alt="image of Status Register B (PS/2)" src="./Gifs/StatusB1.gif" width="260">
|
||
</td>
|
||
<td align="middle">Status Register B (Model 30)
|
||
<br>
|
||
<img title="Status Register B (Model 30)" height="136" alt="image of Status Register B (Model 30)" src="./Gifs/StatusB2.gif" width="260">
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td valign="top" align="middle">
|
||
<table cellpadding="2">
|
||
<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,<2C>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>
|
||
</table>
|
||
</td>
|
||
<td valign="top" align="middle">
|
||
<table>
|
||
<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<EFBFBD>= 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>
|
||
</table>
|
||
</td>
|
||
</tr>
|
||
</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="#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="#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="#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="#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="#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">
|
||
<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>
|
||
</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="#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 title="Read Track Command" height="240" alt="Image of Read Track Command" src="./Gifs/rdtrk.gif" 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 title="Data Transfer Command Results Phase" height="175" alt="image of Data Transfer Command Results Phase" src="./Gifs/Result1.gif" width="290">
|
||
</p>
|
||
<table>
|
||
<tr>
|
||
<td><strong><font size="-1">ST0,<2C>ST1,<2C>ST2:</font></strong>
|
||
</td>
|
||
<td><font size="-1"><a href="#Status0">Status Registers
|
||
</a>0 to
|
||
2</font>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong><font size="-1">Cylinder,<2C>head, sector number,<2C>sector
|
||
size:</font></strong>
|
||
</td>
|
||
<td><font size="-1">Sector ID. (see table below)</font>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
<br>
|
||
<strong>Sector ID in the Result Phase
|
||
</strong>
|
||
<br>
|
||
<table cellpadding="2">
|
||
<tr valign="top">
|
||
<td><strong><font size="-1">M<EFBFBD><EFBFBD></font></strong>
|
||
</td>
|
||
<td><strong><font size="-1">HD
|
||
<sub> prog
|
||
</sub> <20><></font></strong>
|
||
</td>
|
||
<td><strong><font size="-1">Last sector affected<65><64>
|
||
<br>
|
||
by command</font></strong>
|
||
</td>
|
||
<td><strong><font size="-1">Cylinder<EFBFBD><EFBFBD></font></strong>
|
||
</td>
|
||
<td><strong><font size="-1">Head<EFBFBD><EFBFBD></font></strong>
|
||
</td>
|
||
<td><strong><font size="-1">Sector<EFBFBD><EFBFBD></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>
|
||
</table>
|
||
<br>
|
||
<table>
|
||
<tr>
|
||
<td><font size="-1">HD
|
||
<sub> prog
|
||
</sub> :</font>
|
||
</td>
|
||
<td><font size="-1">programmed head<61><64></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<65><72></font>
|
||
</td>
|
||
<td><font size="-1">siz
|
||
<sub> prog
|
||
</sub> :</font>
|
||
</td>
|
||
<td><font size="-1">programmed sector size</font>
|
||
</td>
|
||
</tr>
|
||
</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 title="Write Sector Command" height="240" alt="Image of Write Sector Command" src="./Gifs/wrsec.gif" 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="#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 title="Read Sector Command" height="240" alt="Image of Read Sector Command" src="./Gifs/rdsec.gif" 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="#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 title="Write Deleted Sector Command" height="240" alt="Image of Write Deleted Sector Command" src="./Gifs/wrdelsec.gif" 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="#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 title="Read Deleted Sector Command" height="240" alt="Image of Read Deleted Sector Command" src="./Gifs/rddelsec.gif" 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="#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 title="Format Track Command" height="180" alt="Image of Format Track Command" src="./Gifs/fmttrk.gif" 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="#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="#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 title="Format Buffer" height="120" alt="Image of Format Buffer" src="./Gifs/fmtbuf.gif" 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 title="Fix Drive Data Command" height="120" alt="image of Fix Drive Data Command" src="./Gifs/FixData.gif" width="300">
|
||
</p>
|
||
<table>
|
||
<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>
|
||
</table>
|
||
<br>
|
||
<br>
|
||
<br align="center">
|
||
<table>
|
||
<tr>
|
||
<td align="middle">Step Rate [ms]
|
||
<br>
|
||
<img title="Step Rate" height="190" alt="image of Step Rate" src="./Gifs/StepRate.gif" width="220">
|
||
</td>
|
||
<td align="middle">Head Unload Time [ms]
|
||
<br>
|
||
<img title="Head Unload Time" height="190" alt="image of Head Unload Time" src="./Gifs/HdUnload.gif" width="220">
|
||
</td>
|
||
<td align="middle">Head Load Time [ms]<img title="Head Load Time" height="190" alt="image of Head Load Time" src="./Gifs/HeadLoad.gif" width="220">
|
||
</td>
|
||
</tr>
|
||
</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="#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 title="Check Drive Status Command" height="100" alt="image of Check Drive Status Command" src="./Gifs/ChkDrvStatus.gif" 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 title="Check Drive Status Command Result Phase" height="50" alt="image of Check Drive Status Command Result Phase" src="./Gifs/Result2.gif" width="290">
|
||
</p>
|
||
<p>
|
||
Status Register 3 contains drive information.
|
||
</p>
|
||
<hr size="1"><!---------------------------------------------------------------------------------------->
|
||
<h4>Calibrate Drive (x7h)
|
||
</h4>
|
||
<p align="center">
|
||
<img title="Calibrate Drive Command" height="100" alt="image of Calibrate Drive Command" src="./Gifs/Calibrate.gif" 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 title="Check Interrupt Status Command" height="80" alt="image of Check Interrupt Status Command" src="./Gifs/ChkInts.gif" 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 title="Check Interrupt Status Command Return Phase" height="70" alt="Image of Check Interrupt Status Command Return Phase" src="./Gifs/Result3.gif" width="290">
|
||
</p>
|
||
<hr size="1"><!---------------------------------------------------------------------------------------->
|
||
<h4>Read Sector ID (xah)
|
||
</h4>
|
||
<p align="center">
|
||
<img title="Read Sector ID Command" height="100" alt="#image of Read Sector ID Command" src="./Gifs/RdSecID.gif" 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 title="Read Sector ID Command Result Phase" height="175" alt="image of Read Sector ID Command Result Phase" src="./Gifs/Result1.gif" width="290">
|
||
</p>
|
||
<p>
|
||
The values in the sector ID are calculated in the same way as for the
|
||
<a href="#Results1">result phase
|
||
</a>of the read track command.
|
||
</p>
|
||
<hr size="1"><!---------------------------------------------------------------------------------------->
|
||
<h4>Seek/Park Head (xfh)
|
||
</h4>
|
||
<p align="center">
|
||
<img title="Park Head Command" height="120" alt="image of Park Head Command" src="./Gifs/ParkHead.gif" 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="#chkint">check
|
||
interrupt status
|
||
</a>command.
|
||
</p>
|
||
<hr size="1"><!---------------------------------------------------------------------------------------->
|
||
<h4>invalid command (all invalid opcodes)
|
||
</h4>
|
||
<p align="center">
|
||
<img title="Invalid Opcode Command" height="80" alt="image of Invalid Opcode Command" src="./Gifs/Invalid.gif" 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 title="Invalid Opcode Command Result Phase" height="50" alt="image of Invalid Opcode Command Result Phase" src="./Gifs/Result4.gif" 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 title="Register Summary" height="80" alt="image of Register Summary" src="./Gifs/RegDump.gif" width="300">
|
||
</p>
|
||
<p>
|
||
This command returns the values read from the internal controller
|
||
registers.
|
||
</p>
|
||
<h4>Result Phase
|
||
</h4>
|
||
<p align="center">
|
||
<img title="Register Summary Command Result Phase" height="175" alt="image of Register Summary Command Result Phase" src="./Gifs/Result5.gif" width="290">
|
||
</p>
|
||
<table>
|
||
<tr>
|
||
<td valign="top"><strong><font size="-1">Current<EFBFBD>Cylinder<EFBFBD>DR0,<2C>DR1,<2C>DR2<52>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<EFBFBD>time, head<61>unload<61>time,
|
||
head<61>load<61>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>
|
||
</table>
|
||
<br>
|
||
<br>
|
||
<hr size="1"><!---------------------------------------------------------------------------------------->
|
||
<h4>Determine Controller Version (10h)
|
||
</h4>
|
||
<p align="center">
|
||
<img title="Get Controller Version Command" height="80" alt="image of Get Controller Version Command" src="./Gifs/CtrVer.gif" 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 title="Determine Controller Version Command Result Phase" height="50" alt="image of Determine Controller Version Command Result Phase" src="./Gifs/Result6.gif" 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 title="Verify Command" height="240" alt="image of Verify Command" src="./Gifs/Verify.gif" width="300">
|
||
</p>
|
||
<table cellpadding="2">
|
||
<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<EFBFBD>length/verify<66>sectors:<3A><></font></strong>
|
||
</td>
|
||
<td><font size="-1"><strong> If EC = 0 and sector size =
|
||
0:
|
||
</strong>
|
||
<br>
|
||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>length of data to verify, in bytes.
|
||
<br>
|
||
<strong> Else:
|
||
</strong>
|
||
<br>
|
||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>number of sectors to verify.</font>
|
||
</td>
|
||
</tr>
|
||
</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 title="Verify Command Result Phase" height="175" alt="image of Verify Command Result Phase" src="./Gifs/Result1.gif" width="290">
|
||
</p>
|
||
<hr size="1"><!---------------------------------------------------------------------------------------->
|
||
<h4>Seek Relative (1xfh)
|
||
</h4>
|
||
<p align="center">
|
||
<img title="Seek Relative Command" height="120" alt="image of Seek Relative Command" src="Gifs/SeekRel.gif" width="300">
|
||
</p>
|
||
<table cellpadding="2">
|
||
<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>
|
||
</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>
|
||
</body>
|
||
</html>
|