Floppy Disk Controller: Difference between revisions
Jump to navigation
Jump to search
[unchecked revision] | [unchecked revision] |
Content deleted Content added
Auto motor off info, fixed a couple more errors |
Better info on "disk change" flag |
||
Line 10: | Line 10: | ||
More detailed info can be found in the [[ATA in x86 RealMode (BIOS)]] article, because accessing a floppy is identical to accessing a hard disk |
More detailed info can be found in the [[ATA in x86 RealMode (BIOS)]] article, because accessing a floppy is identical to accessing a hard disk |
||
(using CHS) in Real Mode. The rest of this article deals with creating Protected Mode drivers for the floppy subsystem. |
(using CHS) in Real Mode. The rest of this article deals with creating Protected Mode drivers for the floppy subsystem. |
||
Note: the BIOS IRQ0 handler remembers a timeout for turning the motor off, from the last BIOS floppy access. The last access may have been |
|||
attempting to load your bootloader. So, in the distant future, if the BIOS ever receives 36 more IRQ0 ticks (if you ever return to Real Mode) |
|||
it may turn off your floppy motors for you, once. |
|||
=== Accessing USB Floppy Drives === |
=== Accessing USB Floppy Drives === |
||
Line 73: | Line 77: | ||
If you are using PIO mode in a singletasking environment then the IRQ6s just waste CPU cycles, and you should be using polling instead. |
If you are using PIO mode in a singletasking environment then the IRQ6s just waste CPU cycles, and you should be using polling instead. |
||
You can usually shut the IRQs off by setting bit 3 (value = 8) of the Digital Ouptput Register (see below). |
You can usually shut the IRQs off by setting bit 3 (value = 8) of the Digital Ouptput Register (see below). If you want, you can even |
||
toggle that bit on and off for specific commands, so that you receive some types of interrupts but not others. |
|||
To do PIO data transfers: init/reset the controller if needed (see below), select the drive if needed (see below), |
To do PIO data transfers: init/reset the controller if needed (see below), select the drive if needed (see below), |
||
Line 88: | Line 93: | ||
There were several generations of floppy controller chips on several generations of 80286 (and prior) computers, before |
There were several generations of floppy controller chips on several generations of 80286 (and prior) computers, before |
||
the 82077AA chip existed. The 82077AA was built to emulate all of them, by setting various pins on the chip to 5 volts. |
the 82077AA chip existed. The 82077AA was built to emulate all of them, by setting various pins on the chip to 5 volts. |
||
The three modes are: PC-AT mode, PS/2 mode, and Model 30 mode. |
The three modes are: PC-AT mode, PS/2 mode, and Model 30 mode. The most likely mode you will see on any hardware that |
||
still runs is Model 30 mode. You may find some pre-1996 Pentium machines using PS/2 mode. Sadly, most emulator programs run in PS/2 mode! |
|||
In the documentation, you can ignore PC-AT mode. Or you can try to handle all three, by only using registers and commands that are identical |
In the documentation, you can ignore PC-AT mode. Or you can try to handle all three, by only using registers and commands that are identical |
||
in all 3 modes. |
in all 3 modes. |
||
Line 102: | Line 107: | ||
On real hardware, there are definite timing issues. Seek delays and motor delays are just what any programmer would expect. It |
On real hardware, there are definite timing issues. Seek delays and motor delays are just what any programmer would expect. It |
||
would be nice if the drive would send an IRQ when the motor was up to speed, but it does not. Two things that you may not |
would be nice if the drive would send an IRQ when the motor was up to speed, but it does not. Two things that you may not |
||
expect are that quite new hardware |
expect are that quite new hardware probably still needs artificial delays between outputting "command/parameter" bytes, and that you |
||
probably also need artificial delays between inputting "result" bytes. There is a bit in the MSR |
probably also need artificial delays between inputting "result" bytes. There is a bit in the MSR to test in order to know when the |
||
next byte can be sent/retrieved. It is not a good idea to simply hardcode specific delays between output/input bytes. |
|||
Looping 20 times, and testing the value of the |
Looping 20 times, and testing the value of the RQM bit in the MSR each time, should always be a sufficient "timeout". |
||
However, using IO Port reads to generate delays (or polling MSR) leads to poor performance in a multitasking environment, and |
|||
driver to sleep for the shortest possible period (microsleep), instead. |
you may want to put the driver to sleep for the shortest possible period (microsleep), instead. |
||
== Registers == |
== Registers == |
||
Line 146: | Line 151: | ||
=== Bitflags and Registers that you can rely on === |
=== 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 |
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. |
the mode. However, all of the important registers and bitflags remain the same between modes. |
||
They are the following: |
|||
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. |
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. |
||
But be sure to place a fairly big delay (1 microsecond) betweeen each "outb" to the FIFO. |
|||
TDR: The Tape Drive Register is identical in all modes, but it is useless (you will never find functional equipment that requires it). |
TDR: The Tape Drive Register is identical in all modes, but it is useless (you will never find functional equipment that requires it). |
||
Line 260: | Line 265: | ||
The two important bits are RQM and DIO. NDMA and BUSY are also useful in polling PIO mode. |
The two important bits are RQM and DIO. NDMA and BUSY are also useful in polling PIO mode. |
||
Most important is RQM, which is set when it is OK (or necessary!) to read/write data from/to the FIFO port. |
Most important is RQM, which is set when it is OK (or necessary!) to read/write data from/to the FIFO port. |
||
DIO and BUSY should be checked to verify proper command termination (the end of "result phase" and beginning of "command phase"). |
|||
NDMA signals the end of the "execution phase" of a command, and the beginning of "result phase". |
NDMA signals the end of the "execution phase" of a command, and the beginning of "result phase". |
||
DIO and BUSY should be checked to verify proper command termination (the end of "result phase" and beginning of "command phase"). |
|||
==== CCR and DSR ==== |
==== CCR and DSR ==== |
||
Line 275: | Line 280: | ||
use different datarates, then you need to switch the datarate when you select the other drive. It also seems to be possible |
use different datarates, then you need to switch the datarate when you select the other drive. It also seems to be possible |
||
to modify this register while the FDC is in "reset state". |
to modify this register while the FDC is in "reset state". |
||
Note2: some tutorials seem to claim that changing/setting the datarate causes an IRQ6. This is false. |
|||
Datarates used for setting either DSR or CCR: |
Datarates used for setting either DSR or CCR: |
||
Line 285: | Line 292: | ||
Note: There is also a 300Kbps (value = 1), and a 250Kbps setting (value = 2) but they are only for utterly obsolete drives/media. |
Note: There is also a 300Kbps (value = 1), and a 250Kbps setting (value = 2) but they are only for utterly obsolete drives/media. |
||
=== Important Bitflags that depend on the Mode === |
|||
==== DIR register, Disk Change bit ==== |
==== DIR register, Disk Change bit ==== |
||
This bit (bit 7, value = 0x80) |
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). |
|||
bit until you have tested the functionality on real hardware. |
Do not trust your handling of this bit until you have tested the functionality on real hardware. |
||
Note: |
Note: The datasheet is very confusing about the value of the bit, because Model 30 mode shows the bit as being inverted. But |
||
in Model 30 mode, the '''signal''' is also inverted, so it comes out the same. "False" always means the bit is cleared, and |
|||
This claim needs further testing. |
|||
"true" always means the bit is set. |
|||
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 |
|||
Basically, you want to keep a flag for whether there is media in each drive. if Disk Change is "true" and there was media, |
|||
for the motor to spin up, though). It may also be necessary to read the register twice (and discard the first value), when |
|||
the OS should get a signal that the previous media was ejected, and the driver should automatically try to recalibrate the drive |
|||
changing the selected drive -- because "selecting" sometimes takes a little time. |
|||
for the new media. The recalibration serves two purposes. The heads may have moved when the new media was inserted, and the |
|||
recalibrate will correct for this. Also, the recalibrate will clear the Disk Change flag to "false" if there is '''new''' media |
|||
in the drive. You can find out initially whether there is media in the drives by issuing Recalibrate or Seek commands to all the drives |
|||
(see the [[#Reinitialization|reinitialization]] procedure below). |
|||
Basically, you want to keep a flag for whether there is media in each drive. If Disk Change is set and there was media, |
|||
If a drive has no media in it, and the driver wants to automatically check for new media, it can periodically do a Seek command |
|||
the OS should get a signal that the previous media was ejected. |
|||
on the drive. If Disk Change remains "true", then the drive is still empty. If it goes "false", it means that a new |
|||
floppy has been inserted, and the OS should get a "media inserted" signal. On some/most hardware, it is possible to |
|||
simply toggle the drive motor bit on, off, and then on again, to achieve the same result as doing a Seek (Linux calls this a "twaddle"). |
|||
Once the Disk Change bit gets set (and you have "processed that message"), you need to try to clear the bit. The main way to |
|||
But there is a problem. As the section title says, the problem is that the '''value''' of the Disk Change bitflag depends |
|||
clear the bit is with a '''successful''' Seek to a '''new''' cylinder on the media. (Recalibrate or Reset do not work. And if the |
|||
on the mode. And there are 3 possible modes. |
|||
controller thinks the heads are already on the correct cylinder, it will eat the Seek command without clearing the Disk |
|||
And the idiots at Intel who made this chip failed utterly in giving you a definitive way of figuring out the mode. |
|||
Change bit.) If the seek fails, you can be fairly certain that there is no media in the drive anymore. It is important to note that |
|||
The three modes, again, are PC-AT mode, PS/2 mode, and Model 30 mode. It is easy to distinguish PS/2 mode from |
|||
this means you should check the value of Disk Change just prior to every Seek command that you do, because otherwise you |
|||
Model 30 mode. So how do you distinguish PC-AT mode from the other two? You can't. There isn't a bitflag anywhere |
|||
will lose any Disk Change information. This is also true for implied seeks, and relative seeks. |
|||
that will tell you whether the chip is in PC-AT mode. |
|||
Apparently a small number of floppy drives also support one additional way to clear the bit -- something that |
|||
What can you do? There are a few possibilities. The two main ones: |
|||
Linux calls a "twaddle". Simply toggle the drive motor bit on, off, and then on again. When your driver tries to clear the |
|||
# Ignore PC-AT mode. This is really a very safe assumption. |
|||
Disk Change bit the first time, it can try a twaddle, and see if it works, and keep a flag if it does. |
|||
# Do a workaround to figure out if this Disk Change bit means "true" when set, or "false" when set. |
|||
If you ignore PC-AT mode, then you can tell whether Disk Change is true or false by looking at the other bits in upper DIR. |
|||
Bits 4, 5, and 6 of DIR tell you what value of Disk Change is "false". Usually "true" = 1 on real hardware. |
|||
The workaround (to do ONCE): Read DIR. Assume that the current value of Disk Change means "true". Send a Recalibrate command. |
|||
If it works, then there is media in the drive, and Disk Change should have toggled to "false". So |
|||
read DIR again, check the Disk Change bit, and see if it flipped values. If it did, your initial guess for |
|||
the value of "true" is correct. (Otherwise, it was the opposite.) |
|||
If the Recalibrate fails, then there is no media in the drive, and Disk Change should continue to always be "true". |
|||
So your initial guess was correct. |
|||
Logic diagram: |
|||
{| {{wikitable}} |
|||
|- |
|||
! State of media |
|||
! actual DskChg flag |
|||
! guess |
|||
! Recalibrate result |
|||
! new actual DskChg flag |
|||
! guess good? |
|||
|- |
|||
| None in drive |
|||
| true |
|||
| true |
|||
| Failure |
|||
| true |
|||
| yes |
|||
|- |
|||
| Just inserted |
|||
| true |
|||
| true |
|||
| Success |
|||
| false |
|||
| yes |
|||
|- |
|||
| accessed many times |
|||
| false |
|||
| true |
|||
| Success |
|||
| false |
|||
| no |
|||
|} |
|||
==== Other bitflags in other registers ==== |
|||
If you really want to try using non-essential bitflags that are mode-dependent, you will need to look in the |
|||
datasheet linked below for their locations and meanings. Including them would add too much extraneous info to |
|||
this article. As mentioned in the case of the Disk Change bit, it is not logically possible to completely |
|||
determine what mode the controller chip is in, so it is not really possible to know the meaning of any bitflag, |
|||
if there is any ambiguity between modes. |
|||
== Programming Details == |
== Programming Details == |
||
Line 373: | Line 325: | ||
accessed. To do that, you: |
accessed. To do that, you: |
||
# Turn on the drive's motor and select the drive, using an "outb" command to the DOR IO port. |
# 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. |
# 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. |
# 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. |
# Exchange data with the drive / "seek" the drive heads (the "execution phase"), on the FIFO IO port. |
||
Line 386: | Line 338: | ||
can completely lock up some systems. This claim seems unlikely? |
can completely lock up some systems. This claim seems unlikely? |
||
When you turn a floppy drive motor on, it takes quite a few milliseconds to "spin up" -- to reach the (stabilized) speed |
|||
Note2: modern floppy drives only spin the disk for one or two seconds, and then automatically turn the motors back off by themselves. |
|||
You need to access the drive within that window, or you will get an error. The motor might not even visibly turn on until you send |
|||
a command. |
|||
When you turn a floppy drive motor on, it takes quite a few milliseconds to "spinup" -- to reach the (stabilized) speed |
|||
needed for data transfer. The controller has electronics to handle a large variation in rotation speed, but it has its limits. |
needed for data transfer. The controller has electronics to handle a large variation in rotation speed, but it has its limits. |
||
If you start reading/writing immediately after the motor is turned on, "the PLL will fail to lock on to the data signal" and you will get an error. |
If you start reading/writing immediately after the motor is turned on, "the PLL will fail to lock on to the data signal" and you will get an error. |
||
After you are done reading (or writing), you should typically wait an additional |
After you are done reading (or writing), you should typically wait an additional two seconds to turn the motor off. (It may also be smart |
||
to seek the heads back to cylinder 0 just before turning the motor off.) You could leave the motor on longer, |
to seek the heads back to cylinder 0 just before turning the motor off.) You could leave the motor on longer, |
||
but it might give the user the idea that the floppy is still transferring data and that it's taking an awfully long time |
but it might give the user the idea that the floppy is still transferring data and that it's taking an awfully long time. |
||
The reason to leave the motor on is that your driver may not know if there is a queue of sector reads or writes |
|||
and, as said above, the floppy drive may well turn its own motor off anyway. |
|||
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: |
The suggested delays when turning the motor on are: |
||
Line 461: | Line 411: | ||
## 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. |
## 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. |
## '''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. |
# Wait for the resulting IRQ6. HIHI!! only in polling mode? |
||
# Send a Sense Interrupt command (required). |
# Send a Sense Interrupt command (required). |
||
# If your OS/driver never turned off polling mode (see the Configure command), then you have to send 3 more Sense Interrupt commands. (Alternately, you can tell if you need the extra 3 by examining the top 2 bits of the st0 byte returned by the first Sense Interrupt. If both bits are set, you need to send 3 more.) |
# If your OS/driver never turned off polling mode (see the Configure command), then you have to send 3 more Sense Interrupt commands. (Alternately, you can tell if you need the extra 3 by examining the top 2 bits of the st0 byte returned by the first Sense Interrupt. If both bits are set, you need to send 3 more.) |
||
Line 488: | Line 438: | ||
command fails -- this may be the reason why. |
command fails -- this may be the reason why. |
||
# 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. |
|||
# You need to either know or assume the "true" value for the Disk Change bitflag in DIR. |
|||
# Read DIR. If the "Disk Change" bitflag is set to "true", then the floppy drive door was opened, so the driver needs to Recalibrate the drive, |
|||
then the OS needs to test if a new disk is in the drive. |
|||
==== Waiting ==== |
==== Waiting ==== |
||
Line 516: | Line 464: | ||
## Loop on reading MSR until RQM = 1, verify that DIO = 1. |
## Loop on reading MSR until RQM = 1, verify that DIO = 1. |
||
## In a loop: read the next result byte from the FIFO, loop on reading MSR until RQM = 1, verify CMD BSY = 1 and DIO = 1 ((Value & 0x50) == 0x50). |
## In a loop: read the next result byte from the FIFO, loop on reading MSR until RQM = 1, verify CMD BSY = 1 and DIO = 1 ((Value & 0x50) == 0x50). |
||
# After reading all the expected result bytes: check them for error conditions, verify that RQM = 1, CMD BSY = 0, and DIO = 0. '''If not''' retry the |
# After reading all the expected result bytes: check them for error conditions, verify that RQM = 1, CMD BSY = 0, and DIO = 0. '''If not''' retry the entire command again, several times, starting from step 2! |
||
entire command again, several times, starting from step 2! |
|||
Note: implementing a failure timeout for each loop and the IRQ is pretty much required -- it is the only way to detect many command errors. |
Note: implementing a failure timeout for each loop and the IRQ is pretty much required -- it is the only way to detect many command errors. |
||
Line 572: | Line 519: | ||
==== Status Registers ==== |
==== Status Registers ==== |
||
There are 3 registers that hold information about the last error encountered. The st0 register information |
There are 3 registers that hold information about the last error encountered. The st0 register information |
||
is passed back with the result bytes of most commands |
is passed back with the result bytes of most commands. The st1 and st2 information is returned in the result |
||
bytes of read/write commands. They can also be retrieved with a Dumpreg command. |
|||
Interrupt command. The st1 and st2 information is returned in the result bytes of read/write commands. They |
|||
can also be retrieved with a Dumpreg command. |
|||
===== st0 ===== |
===== st0 ===== |
||
The top |
The top 2 bits (value = 0xC0) are set after a reset procedure, with polling on. Either bit being set at any other |
||
time is an error indication. |
|||
Bit 6 (value = 0x40) is set for any "normal" error condition, unless the error locks up the controller completely. |
|||
Bit |
Bit 5 (value = 0x20) is set after every Recalibrate, Seek, or an implied seek. The other bits are not useful. |
||
===== st1 ===== |
===== st1 ===== |
||
The st1 register provides more detail about errors during read/write operations. |
The st1 register provides more detail about errors during read/write operations. |
||
Line 586: | Line 533: | ||
caused by '''not subtracting 1''' when setting the DMA byte count. |
caused by '''not subtracting 1''' when setting the DMA byte count. |
||
Bit 4 (value = 0x10) is set if your driver is too slow to get bytes in or out of the FIFO port in time. |
Bit 4 (value = 0x10) is set if your driver is too slow to get bytes in or out of the FIFO port in time. |
||
Bit 1 (value = 2) is set if |
Bit 1 (value = 2) is set if the media is write protected. |
||
The rest of the bits are various types of data errors |
The rest of the bits are for various types of data errors; indicating bad media, or a bad drive. |
||
===== st2 ===== |
===== st2 ===== |
||
The st2 register provides more detail about errors during read/write operations. |
The st2 register provides more (useless) detail about errors during read/write operations. |
||
The bits all indicate various types of data errors |
The bits all indicate various types of data errors for either bad media, or a bad drive. |
||
==== Configure ==== |
==== Configure ==== |
||
This command initializes controller-specific values: the data buffer "threshold" value, implied seek enable, FIFO |
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, polling off, threshold = 8, precompensation 0. |
(And "Write Precompensation".) A good setting is: implied seek on, FIFO on, polling off, threshold = 8, precompensation 0. |
||
Line 656: | Line 604: | ||
===== SRT, HLT and HUT ===== |
===== SRT, HLT and HUT ===== |
||
These parameters sent with the Specify command to the controller are meant to optimize drive performance. |
These parameters sent with the Specify command to the controller are meant to optimize drive performance, and head lifetime. |
||
The values are specific to the exact model, condition, and age of floppy drive installed on the system. The values sent by the driver to the |
|||
controller were always meant |
controller were always meant |
||
to be '''adaptive'''. That is, your driver is theoretically supposed to keep statistics of how often Seek commands fail with the current |
to be '''adaptive'''. That is, your driver is theoretically supposed to keep statistics of how often Seek commands fail with the current |
||
setting of SRT. If they always work, and your driver wants to optimize performance, then it can send a new Specify command, with the SRT |
setting of SRT. If they always work, and your driver wants to optimize performance, then it can send a new Specify command, with the SRT |
||
value reduced by 1. Then begin keeping new statistics. Similarly for HLT |
value reduced by 1. Then begin keeping new statistics. Similarly for HLT regarding Read/Write operations. As drives age and collect |
||
dirt, the driver would automatically compensate by seeing higher statistical error rates, and increase the values of SRT |
dirt, the driver would automatically compensate by seeing higher statistical error rates, and increase the values of SRT and HLT. |
||
Keeping statistics in that way only works when the drive in question is used often. Now that internal floppy drives are nearly obsolete, |
Keeping statistics in that way only works when the drive in question is used often. Now that internal floppy drives are nearly obsolete, |
||
Line 703: | Line 651: | ||
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 |
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. |
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. After a Recalibrate/Seek it should be 0x20 | drive number. |
|||
==== Recalibrate ==== |
==== Recalibrate ==== |
||
Line 742: | Line 691: | ||
A Sense Interrupt command is required after this command completes, to clear it from being BUSY. (Multiple Sense Interrupts, |
A Sense Interrupt command is required after this command completes, to clear it from being BUSY. (Multiple Sense Interrupts, |
||
if you ran multiple Seeks.) |
if you ran multiple Seeks.) |
||
Note: the controller tries to remember what cylinder each drive's heads are currently on. If you try to seek to that same |
|||
cylinder, then the controller will silently ignore the command (and return a "success" value). One of the things this means |
|||
is that you can get a "success" return value on a seek '''even if there is no media in the drive''', if you happen to seek |
|||
to the wrong cylinder number. |
|||
===== Relative seek ===== |
===== Relative seek ===== |
||
Line 752: | Line 706: | ||
==== Read/Write ==== |
==== Read/Write ==== |
||
Note: Remember that this is in CHS format, so the sector number starts at 1. |
Note: Remember that this is in CHS format, so the sector number starts at 1. |
||
Line 778: | Line 731: | ||
Note2: Floppy media and electronics are well known for being unreliable. Any read or write command that fails should be retried |
Note2: Floppy media and electronics are well known for being unreliable. Any read or write command that fails should be retried |
||
at least twice. |
at least twice, unless it was a write and failed on "write protect". |
||
=== Perpendicular Mode and 2.88M floppies === |
=== Perpendicular Mode and 2.88M floppies === |
||
If you are using an emulator and you need a floppy disk image that is bigger than 1440Kb, there is a 2880Kb image available. |
If you are using an emulator and you need a floppy disk image that is bigger than 1440Kb, there is a 2880Kb image available. |
||
In order to access it in Pmode, you need to modify your driver to handle Perpendicular Mode. Basically, it is an extra configuration |
In order to access it in Pmode, you need to modify your driver to handle Perpendicular Mode. Basically, it is an extra configuration |
||
Line 794: | Line 746: | ||
You also need to set CCR/DSR for the 1M datarate (value = 3) to access a 2.88M drive. |
You also need to set CCR/DSR for the 1M datarate (value = 3) to access a 2.88M drive. |
||
=== Additional Programming Notes === |
|||
If you are doing a transfer between 2 floppy drives (so that both motors are on), and you are toggling "selection" between the two, |
|||
there may be a short delay required. |
|||
== Code Examples == |
== Code Examples == |