Anonymous user
Floppy Disk Controller: Difference between revisions
Jump to navigation
Jump to search
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
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
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.
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).
{| {{wikitable}}
Line 212 ⟶ 211:
the hardware "untoggles" reset mode automatically after the proper delay.
{| {{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").
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.
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
'''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
clear the bit is with a '''successful''' Seek/Recalibrate to a '''new''' cylinder on the media. (
controller thinks the heads are already on the correct cylinder, it will eat
Change bit.
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
accessed. To
# 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
# 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
The suggested delays when turning the motor on are:
Line 386:
==== Reinitialization ====
The BIOS probably leaves the controller in its default state.
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 guess as to the proper values for the "Specify" command than your OS does (the values are specific to the particular
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 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.
==== 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
#
# If your OS/driver never
# 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!).
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
# 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 ====
|