In order to read from the floppy drive, we must first initialize the controller.
void Start();
|
Start
Start is called when an operation is to be performed on a floppy disk (read, write, etc.). It simply calls the other five functions listed above. It is possible that on your computer you will only need to call some of these functions before every operation, and the rest only when you initialize your floppy driver. For example, the code worked perfectly on my Celeron 466MHz tower if I called Reset only when my floppy driver initialized; but it would not work on my laptop. Also note that, if you add a timed delay before turning the motor off (as mentioned in Notes), Start would be where you would check if the motor is off; if it is, call the other functions, otherwise do nothing.
Reset
Reset will reset the floppy controller. You may be able to call this only when initializing your floppy driver; on my laptop, this would not work.
SetDataRate
SetDataRate sets the data rate used for the floppy drive. This can be 250Kbps, 300Kbps, 500Kbps, or 1Mbps. For 1.44MB disks, use 500Kbps. Different floppy disk densities require different speeds, so if you want to support types other than 1.44MB, you will need to determine what type of disk is in the drive before setting the data rate. Information I've found on the Internet, including at least one driver's source code, says to simply try one data rate, and if it does not work, try another data rate. When I tried to use 1Mbps (on either computer), the entire read operation would complete without any indication of an error, but the bytes copied would all be 0.
SetSpecifications
SetSpecifications will set the floppy drive's step rate, head unload time, and head load time. These rates depend on the data rate currently set, so this should always be set after setting the data rate. My header file includes two sets of specifications; however, there is a whole range that can be used, so if you want to see the settings that are possible, visit Programming Floppy Disk Controllers.
Recalibrate
Recalibrate attempts to recalibrate the drive; it is successful if it returns to cylinder 0.
StartMotor
StartMotor starts the floppy drive motor. Using a floppy drive requires that you first turn its motor on. The other operations require you to select the floppy drive, and a floppy drive cannot be selected unless its motor is on.
Code
void Floppy::Start() {
Reset();
StartMotor();
// Now get the floppy drive ready
SetDataRate(ccrDataRate500Kb);
SetSpecifications(spcStepRate3ms, spcHeadUnloadTime240ms, spcHeadLoadTime16ms);
Recalibrate();
}
void Floppy::Reset() {
// Reset the controller
PendingInterrupt = true;
WriteByteToPort(IOBase[ControllerIndex] + flpWDigitalOutputRegister, 0);
while(PendingInterrupt);
}
void Floppy::SetDataRate(CCR DataRate) {
WriteByteToPort(IOBase[ControllerIndex] + flpWConfigurationControlRegister, DataRate);
}
bool Floppy::SetSpecifications(byte StepRate, byte HeadUnloadTime, byte HeadLoadTime) {
if (!SendData(cmdSpecify)) return false;
if (!SendData((StepRate << spcStepRateShift) & HeadUnloadTime)) return false;
if (!SendData(HeadLoadTime << spcHeadLoadTimeShift)) return false;
return true;
}
bool Floppy::Recalibrate() {
unsigned int Tries = 0;
AtCylinder = 255;
while ((Tries < MaximumRecalibrateTries) && (AtCylinder != 0)) {
PendingInterrupt = true;
SendData(cmdCalibrateDrive);
SendData(DriveIndex);
while(PendingInterrupt);
ReadStatus();
Tries++;
}
return Tries < MaximumRecalibrateTries;
}
void Floppy::StartMotor() {
if (!MotorRunning) {
PendingInterrupt = true;
DigitalOutputRegister |= (1 << (DriveIndex + dorMotorShift)) | DriveIndex;
WriteByteToPort(IOBase[ControllerIndex] + flpWDigitalOutputRegister, DigitalOutputRegister);
while(PendingInterrupt);
MotorRunning = true;
}
}
|