Floppy Disk Controller: Difference between revisions

More polling mode info, slight reformat, some fixes
[unchecked revision][unchecked revision]
(→‎DOR bitflag definitions: motor off error)
(More polling mode info, slight reformat, some fixes)
Line 33:
 
=== How Many Drives? ===
 
It is probably wisest to always get the drive count and types from [[CMOS]], register 0x10.
 
Line 86 ⟶ 85:
if there were any errors. See below for more detail.
 
==== Bochs canCan't handleHandle Polling PIO ====
If you try to turn off the IRQs in Bochs (to use pure polling PIO mode), Bochs will panic. It may also not be able to handle
non-DMA data transfers properly, even if IRQs are turned on. It is currently mainly designed to model the floppy using DMA.
Line 98 ⟶ 97:
in all 3 modes.
 
=== Most commandsCommands runRun "silentlySilently" ===
There are only a few commands/conditions that produce interrupts: a reset (in polling mode only), Seek, Recalibrate, or one of the
read/write/verify/format commands. Several commands do not produce any result bytes, either. If you want to verify that a silent
Line 149 ⟶ 148:
access STATUS_REGISTER_B on FDC 1, you would use FDC1_BASE_ADDRESS + STATUS_REGISTER_B = 0x370 + 1 = 0x371.
 
=== Bitflags and Registers that you can rely on ===
As said above, the most common controller chip has 3 modes, and many bitflags in the registers are different (or opposite!) depending on
the mode. However, all of the important registers and bitflags remain the same between modes.
They are the following:
 
=== FIFO and Tape Drive Registers ===
FIFO: The FIFO register may not have a 16byte buffer in all modes, but this is a minor difference that does not really affect its operation.
 
TDR: The Tape Drive Register is identical in all modes, but it is useless (you will never find functional equipment that requires it).
 
==== DOR bitflag definitions ====
 
{| {{wikitable}}
Line 212 ⟶ 211:
the hardware "untoggles" reset mode automatically after the proper delay.
 
==== MSR bitflag definitions ====
 
{| {{wikitable}}
Line 267 ⟶ 266:
DIO and BUSY should be checked to verify proper command termination (the end of "result phase" and beginning of "command phase").
 
==== CCR and DSR ====
The bottom 2 bits of DSR match CCR, and setting one of them sets the other. The upper 6 bits on both DSR and CCR default to 0, and
can always be set to zero safely. So, even though they have different bit definitions, you always set them with identical values, and
Line 292 ⟶ 291:
Note: There is also a 300Kbps (value = 1), and a 250Kbps setting (value = 2) but they are only for utterly obsolete drives/media.
 
==== DIR register, Disk Change bit ====
This bit (bit 7, value = 0x80) is fairly useful. It gets set if the floppy door was opened/closed. Sadly, almost all the emulator
programs set and clear this bit completely inappropriately (especially after a reset).
Line 302 ⟶ 301:
 
Note2: You must turn on the drive motor bit before you access the DIR register for a selected drive (you do not have to wait
for the motor to spin up, though). It may also be necessary to read the register twicefive (andtimes (discard the first value4 values), when
'''changing''' the selected drive -- because "selecting" sometimes takes a little time.
 
Basically, you want to keep a flag for whether there is media in each drive. If Disk Change is set and there was media,
the OS should get a signal that the previous media was ejected.
 
Once the Disk Change bit getssignals set"true" (and you have "processed that message"event"), you need to try to clear the bit. The main way to
clear the bit is with a '''successful''' Seek/Recalibrate to a '''new''' cylinder on the media. (Recalibrate orA Resetreset dodoes not work. And ifIf the
controller thinks the heads are already on the correct cylinder, it will eat thea Seek command without clearing the Disk
Change bit.) If the seekheads fails,are youalready canon becylinder fairly certain0, thata thereRecalibrate is also a no-op.) media inIf the driveseek anymore.'''fails''', Ityou iscan importantbe to note thatfairly
certain that there is no media in the drive anymore. It is important to note that
this means you should check the value of Disk Change just prior to every Seek command that you do, because otherwise you
will lose any Disk Change information. This is also true for implied seeks, and relative seeks.
Line 321:
 
== Programming Details ==
Overall, the controller needs to be initialized and reset once (see below for the steps involved). Then a particular drivedrives can be
accessed. To doaccess that, youdrives:
# Turn on the drive's motor and select the drive, using an "outb" command to the DOR IO port.
# Wait for awhile for the motor to get up to speed, using some waiting scheme (but don't wait too long).
# Issue your command byte plus some parameter bytes (the "command phase") to the FIFO IO port.
# Exchange data with the drive / "seek" the drive heads (the "execution phase"), on the FIFO IO port.
Line 346:
The reason to leave the motor on is that your driver may not know if there is a queue of sector reads or writes
that are going to be executed next. If there are going to be more drive accesses immediately, they won't need to wait
for the motor to spin up, if the motor is still on.
 
The suggested delays when turning the motor on are:
Line 386:
==== Reinitialization ====
 
The BIOS probably leaves the controller in its default state. Polling"Drive polling mode" on, FIFO off, threshold = 1, implied seek off, lock off. This
lock off. This is a lousy state for the controller to be in, and your OS will need to fix it. The BIOS probably also does not have any better
any better guess as to the proper values for the "Specify" command than your OS does (the values are specific to the particular drive). There
drive). There is certainly no reason why you should trust the BIOS to have done any of it '''correctly.'''
 
So, when your OS is initializing:
# Send 4 Sense Interrupt commands to the controller. This may clear a problem with default "polling mode".
# Send a Version command to the controller.
# Verify that the result byte is 0x90 -- if it is not, it might be a good idea to abort and not support the floppy subsystem. Almost all of the code based on this article will work, even on the oldest chipsets -- but there are a few commands that will not.
# If you don't want to bother having to send another Configure command after every Reset procedure, then:
## Send a better Configure command to the controller. A suggestion would be: drive polling mode off, FIFO on, threshold = 8, implied seek on, precompensation 0.
## send a Lock command.
# Do a Controller Reset procedure.
# Send a Recalibrate command to each of the drives. (You can do them all at the same time, or you can use this as an opportunity to handle the "Disk Change" bit, and/or you can use this as a chance to detect which drives actually have media in them.)
 
==== Controller Reset ====
Line 410 ⟶ 409:
## Bit 2 (value = 4) in the DOR: Save the current/"original" value of the DOR, write a 0 to the DOR, wait 4 microseconds, then write the original value (bit 2 is always set) back to the DOR.
## '''or''' Bit 7 (value = 0x80) in the DSR: Precalculate a good value for the DSR (generally 0), and OR it with 0x80. Write that value to the DSR.
# Wait for the resulting IRQ6. HIHI!!(unless onlyyou have IRQs turned off in pollingthe mode?DOR)
# SendIf a(and only if) [[#Configure|drive polling mode]] is turned on, send 4 Sense Interrupt commandcommands (required).
# If your OS/driver never turnedsent offa polling mode (see the ConfigureLock command), then you haveprobably need to send 3a morenew SenseConfigure Interrupt commands.command (Alternately, you can tell if you need the extrafifo 3settings bywere examininglost the top 2 bits ofin the st0 byte returned by the first Sense Interruptreset). If both bits are set, you need to send 3 more.)
# If your OS/driver never sent a Lock command, then you need to send a new Configure command (the fifo information was lost in the reset).
# Do a Drive Select procedure for the next drive to be accessed.
 
Line 421 ⟶ 419:
Note2: Emulators will often set the Disk Change flag to "true" after a reset, '''but this does not happen on real hardware''' -- it is
a shared bug in all the emulators that do it.
 
Note3: A reset does not change the [[#Configure|drive polling mode or implied seek]] settings.
 
==== Drive Selection ====
Line 437:
command fails -- this may be the reason why.
 
# Turn the drive motor bit on.
# Read DIR. If the "Disk Change" bitflag is set to "true", then the floppy drive door was opened, so the OS needs to test if a new disk is in the drive.
 
Line 452 ⟶ 453:
# Verify that RQM = 1 and DIO = 0 ((Value & 0xc0) == 0x80) -- if not, reset the controller and start all over.
# Send your chosen command byte to the FIFO port (port 0x3F5).
# In a loop: loop on reading MSR until RQM = 1. Verify DIO = 0, then send the next parameter byte for the command to the FIFO port.
# Either Execution or Result Phase begins when all parameter bytes have been sent, depending on whether you are in PIO mode, and the command has an Execution phase. If using DMA, or the command does not perform read/write/head movement operations, skip to the Result Phase.
# (In PIO Mode Execution phase) read MSR, verify NDMA = 1 ((Value & 0x20) == 0x20) -- if it's not set, the command has no Execution phase, so skip to Result phase.
Line 543 ⟶ 544:
==== Configure ====
This command initializes controller-specific values: the data buffer "threshold" value, implied seek enable, FIFO disable, polling enable.
(And "Write Precompensation".) A good setting is: implied seek on, FIFO on, drive polling mode off, threshold = 8, precompensation 0.
 
If you enable implied seeks, then you don't have to send Seek commands (or Sense Interrupt commands for the Seek commands).
Line 551 ⟶ 552:
transfer!).
 
PollingDrive polling mode is just an annoyance that is there for backwards software compatibility. It makes you need extra Sense Interrupts
after every reset. Always turn it off, if you send a Configure command.
 
Line 562 ⟶ 563:
* Configure command = 0x13
* First parameter byte = 0
* Second parameter byte = (implied seek enable << 6) | (fifo '''DIS'''able << 5) | (drive polling mode enable << 4) | thresh_val (= threshold - 1)
* Third parameter byte = precomp_val = 0
* No result bytes.
Line 636 ⟶ 637:
bitflag in the controller. It is required in three circumstances that produce interrupts.
 
# After doing a Controller Reset procedure (youwith may[[#Configure|drive needpolling tomode]] sendturned 4 of them, then)on.
# After the completion of a Seek command (or Relative Seek).
# After the completion of a Recalibrate command.
 
These are the only times when you should send a Sense Interrupt. You should still send them even if you have IRQs turned off in
the DOR and you are using PIO polling instead. If you send Sense Interrupt commands at other times: the command will complete, return
a 0x80, and then lock up the controller until you do a Reset.
 
* Sense Interrupt command = 0x8
Line 651 ⟶ 653:
Note: if you try to read the result bytes without waiting for RQM to set, then you are likely to always get an incorrect result value
of 0. This is also likely to get your driver out of sync with the FDC for input/output. The correct value of st0 after a reset should
be 0xC0 | drive number (drive number = 0 to 3). After a Recalibrate/Seek it should be 0x20 | drive number.
 
==== Recalibrate ====
Anonymous user