Help on a Floppy disk controller
Posted: Thu Jan 18, 2007 11:02 am
/***************************************************************************
** HELP ** HELP ** HELP ** HELP ** HELP ** HELP ** HELP ** HELP ** HELP **
This is My Floppy driver, This driver works fine on Bochs, and On
Microsoft PC Emulator, and on Qemu, But on my real PC the Read/Write
doesn't work (It claims 'No DATA' or 'didn't find address mark' in the ST1 return value),
so it seems that the error is something with the Hardware detection of the sectors,
Does any one know how to solve the problem?????
Thanks a lot for any help, (and for your patience to read my code).
(This code was compiled by MSVC 6.0).
This is how I read a sector:
Floppy_ReadSector(nDrive,pBuffer,nSector)
Floppy_InitControllerForCommands(nDrive);
Floppy_Recalibrate(nDrive);
Floppy_Seek(nDrive,nHead,nCylinder);
DMA_SetChannel2ToReadFromFloppy();
//
//READ
//
Floppy_SendByte( (BYTE)( 0x46 ) );//0100-0110//(bit 7=MT=Multi-Track function=0),(bit 6=MFM=A one selects the double density (MFM) mode=1),(bit 5=SK=Skip flag=0),-0110
byte = (BYTE)((nHead<<2)&0x4)|(BYTE)nDrive;
Floppy_SendByte( byte );//0000-0001//0000-(bit 2=HDS=0),(bit 1=DS1),(bit 0=DS0)
Floppy_SendByte( (BYTE)nCylinder );//C = Cylinder address
Floppy_SendByte( (BYTE)nHead );//H=Head address.
Floppy_SendByte( (BYTE)nSector );//R=Sector address.
Floppy_SendByte( 02 );//N (bytes per sector).
Floppy_SendByte( 18 );//EOT = End of track.
Floppy_SendByte( 0x1B );//GPL = Gap length.
Floppy_SendByte( (BYTE)0xFF );//DTL (number of bytes to be transferred)
//
//Read returned Data
//
Floppy_GetByte(&byte);//ST0
Floppy_GetByte(&byte);//ST1
ST0_ReturnedByte = byte;//<-----
ST1_ReturnedByte = byte;//<-----
Floppy_GetByte(&byte);//ST2
ST2_ReturnedByte = byte;//<-----
Floppy_GetByte(&byte);//C
Floppy_GetByte(&byte);//H
Floppy_GetByte(&byte);//R
R_ReturnedByte=byte;//<-----
Floppy_GetByte(&byte);//N
GetKey();
Floppy_Print_ST0(ST0_ReturnedByte);
Floppy_Print_ST1(ST1_ReturnedByte);
Floppy_Print_ST2(ST2_ReturnedByte);
** HELP ** HELP ** HELP ** HELP ** HELP ** HELP ** HELP ** HELP ** HELP **
This is My Floppy driver, This driver works fine on Bochs, and On
Microsoft PC Emulator, and on Qemu, But on my real PC the Read/Write
doesn't work (It claims 'No DATA' or 'didn't find address mark' in the ST1 return value),
so it seems that the error is something with the Hardware detection of the sectors,
Does any one know how to solve the problem?????
Thanks a lot for any help, (and for your patience to read my code).
(This code was compiled by MSVC 6.0).
This is how I read a sector:
Floppy_ReadSector(nDrive,pBuffer,nSector)
Floppy_InitControllerForCommands(nDrive);
Floppy_Recalibrate(nDrive);
Floppy_Seek(nDrive,nHead,nCylinder);
DMA_SetChannel2ToReadFromFloppy();
//
//READ
//
Floppy_SendByte( (BYTE)( 0x46 ) );//0100-0110//(bit 7=MT=Multi-Track function=0),(bit 6=MFM=A one selects the double density (MFM) mode=1),(bit 5=SK=Skip flag=0),-0110
byte = (BYTE)((nHead<<2)&0x4)|(BYTE)nDrive;
Floppy_SendByte( byte );//0000-0001//0000-(bit 2=HDS=0),(bit 1=DS1),(bit 0=DS0)
Floppy_SendByte( (BYTE)nCylinder );//C = Cylinder address
Floppy_SendByte( (BYTE)nHead );//H=Head address.
Floppy_SendByte( (BYTE)nSector );//R=Sector address.
Floppy_SendByte( 02 );//N (bytes per sector).
Floppy_SendByte( 18 );//EOT = End of track.
Floppy_SendByte( 0x1B );//GPL = Gap length.
Floppy_SendByte( (BYTE)0xFF );//DTL (number of bytes to be transferred)
//
//Read returned Data
//
Floppy_GetByte(&byte);//ST0
Floppy_GetByte(&byte);//ST1
ST0_ReturnedByte = byte;//<-----
ST1_ReturnedByte = byte;//<-----
Floppy_GetByte(&byte);//ST2
ST2_ReturnedByte = byte;//<-----
Floppy_GetByte(&byte);//C
Floppy_GetByte(&byte);//H
Floppy_GetByte(&byte);//R
R_ReturnedByte=byte;//<-----
Floppy_GetByte(&byte);//N
GetKey();
Floppy_Print_ST0(ST0_ReturnedByte);
Floppy_Print_ST1(ST1_ReturnedByte);
Floppy_Print_ST2(ST2_ReturnedByte);
Code: Select all
****************************************************************************/
//Floppy.h
#ifndef __Floppy_h_
#define __Floppy_h_
#define FLOPPY_STATUS_REGISTER_A 0x3F0//Read-Only//SRA
#define FLOPPY_STATUS_REGISTER_B 0x3F1//Read-Only//SRB
#define FLOPPY_DIGITAL_OUTPUT_REGISTER 0x3F2// //DOR
#define FLOPPY_TAPE_DRIVE_REGISTER 0x3F3// //TDR
#define FLOPPY_MAIN_STATUS_REGISTER 0x3F4//Read-Only//MSR
#define FLOPPY_DATA_RATE_SELECT_REGISTER 0x3F4//Write-Only//DSR
#define FLOPPY_DATA_FIFO 0x3F5// //FIFO
#define FLOPPY_DIGITAL_INPUT_REGISTER 0x3F7//Write-Only//DIR
#define FLOPPY_CONFIGURATION_CONTROL_REGISTER 0x3F7//Write-Only//CCR
//DIGITAL OUTPUT REGISTER (DOR)
#define FLOPPY_DRIVE_SEL0 0x1
#define FLOPPY_DRIVE_SEL1 0x2
#define FLOPPY_RESET 0x4
#define FLOPPY_DMA_GATE 0x8
//FLOPPY_MAIN_STATUS_REGISTER (MSR)
#define FLOPPY_MSR_READY 0x80
#define FLOPPY_MSR_READ_DRIECTION 0x40
enum FloppyCommands {
READ_TRACK = 2,
SPECIFY = 3,
SENSE_DRIVE_STATUS = 4,
WRITE_DATA = 5,
READ_DATA = 6,
RECALIBRATE = 7,
SENSE_INTERRUPT = 8,
WRITE_DELETED_DATA = 9,
READ_ID = 10,
READ_DELETED_DATA = 12,
FORMAT_TRACK = 13,
SEEK = 15,
VERSION = 16,
SCAN_EQUAL = 17,
PERPENDICULAR_MODE = 18,
CONFIGURE = 19,
VERIFY = 22,
SCAN_LOW_OR_EQUAL = 25,
SCAN_HIGH_OR_EQUAL = 29,
};
BOOL Floppy_Init();
void Floppy_Delay4us();
BOOL Floppy_GetByte(BYTE *pByte);
BOOL Floppy_SendByte(BYTE byte);
void Floppy_GetMainStatusInformation();
BOOL Floppy_WriteSector(DWORD nDrive,char *pBuffer,DWORD nSector);
BOOL Floppy_FormatFloppy(DWORD nDrive);
BOOL Floppy_DoneRW(DWORD nDrive);
BOOL Floppy_IsThereADrive(DWORD nDrive);
BOOL Floppy_IsThereADiskInTheDrive(DWORD nDrive);
BOOL Floppy_Seek(DWORD nDrive,DWORD nHead,DWORD nCylinder);
BOOL Floppy_Recalibrate(DWORD nDrive);
BOOL Floppy_InitControllerForCommands(DWORD nDrive);
BOOL Floppy_ReadSector(DWORD nDrive,char *pBuffer,DWORD nInputSector);
void Floppy_Print_ST0(BYTE ST0);
void Floppy_Print_ST1(BYTE ST1);
void Floppy_Print_ST2(BYTE ST2);
void Floppy_Print_ST3(BYTE ST3);
BOOL DMA_SetChannel2ToReadFromFloppy();
#define FLOPPY_DATA_RATE_1M 3
#define FLOPPY_DATA_RATE_500K 0
#define FLOPPY_DATA_RATE_300K 1
#define FLOPPY_DATA_RATE_250K 2
#define FLOPPY_RESERVED_AREA_FOR_IO 0x10000
#define FLOPPY_NUMBER_OF_SECTORS 18
#define FLOPPY_NUMBER_OF_CYLINDERS 80
#define FLOPPY_NUMBER_OF_HEADS 2
#define FLOPPY_MAX_NUMBER_OF_SECTORS \
FLOPPY_NUMBER_OF_SECTORS*FLOPPY_NUMBER_OF_CYLINDERS*FLOPPY_NUMBER_OF_HEADS
#endif
//Floppy.C
/***************************************************************
Refrence: 82077AA data sheet
Date: 11/1/2007
Author: S.Z.Keller
****************************************************************/
#include "Define.h"
#include "IO.h"
#include "DataManipulation.h"
#include "PEKernel.h"
#include "externals.h"
#include "Keyboard.h"
#include "Floppy.h"
#include "DMA.h"
#include "CMOS.h"
////////////////////////////////////////////
//
////////////////////////////////////////////
BOOL Floppy_Init()
{
char *pBuffer;
DWORD loop;
DWORD nDrive=0;
//Check if there is floppy drives.
if(!Floppy_IsThereADrive(nDrive))
{
nDrive=1;
if(!Floppy_IsThereADrive(nDrive))
{
PrintColor("Didn't find any floppys!!!\n",RED_BLUE);
GetKey();
return FALSE;
}
}
if(!Floppy_IsThereADiskInTheDrive(nDrive))
{
PrintColor("There is no floppy in the drive!!!\n",RED_BLUE);
GetKey();
return FALSE;
}
//Format Floppy
// Floppy_FormatFloppy(nDrive);
again:
pBuffer = (char*)FLOPPY_RESERVED_AREA_FOR_IO;
if(!Floppy_WriteSector(nDrive,pBuffer,20))
{
PrintColor("Error Writting Sector\n",YELLOW_BLUE);
GetKey();
return FALSE;
}
memset(pBuffer,0xFF,512);
if(!Floppy_ReadSector(nDrive,pBuffer,20))
{
PrintColor("Error Reading Sector\n",YELLOW_BLUE);
GetKey();
return FALSE;
}
for(loop=0;loop<512;loop++)
{
_sprintf(g_Buffer,"%X ",pBuffer[loop]&0xFF);
PrintColor(g_Buffer,YELLOW_BLUE);
}
GetKey();
goto again;
//
//Shot down floppy.
//
// Floppy_DoneRW(nDrive);
return TRUE;
}
////////////////////////////////////////////
//
////////////////////////////////////////////
void Floppy_Delay4us()//4 Micro Seconds.
{
DWORD loop;
for(loop=0;loop<10;loop++)
{
_inp_(FLOPPY_MAIN_STATUS_REGISTER);
}
}
////////////////////////////////////////////
//
////////////////////////////////////////////
BOOL Floppy_ReadSector(DWORD nDrive,char *pBuffer,DWORD nInputSector)
{
static BYTE byte;
DWORD nSector;
DWORD nCylinder;
DWORD nHead;
BYTE R_ReturnedByte;
BYTE ST0_ReturnedByte;
BYTE ST1_ReturnedByte;
BYTE ST2_ReturnedByte;
//
//Make sure that user is not trying to read larger then the floppy
//
if(nInputSector>FLOPPY_MAX_NUMBER_OF_SECTORS)
{
PrintColor("You are trying to read a to large nSector\n",RED_BLUE);
GetKey();
return FALSE;
}
//
//Init Controller
//
Floppy_InitControllerForCommands(nDrive);
//
//Recalibrate Controller (Move Floppy head to track 0).
//
Floppy_Recalibrate(nDrive);
//
//Calculate Head,Cylinder,Sector from nSector
//
nSector = nInputSector%FLOPPY_NUMBER_OF_SECTORS;
nInputSector -= nSector;
nSector++;//Remember Sectors start with 1 (not 0).
nInputSector/=FLOPPY_NUMBER_OF_SECTORS;
nHead = (nInputSector)%FLOPPY_NUMBER_OF_HEADS;
nCylinder = nInputSector/FLOPPY_NUMBER_OF_HEADS;
_sprintf(g_Buffer,"nHead = %u\n",nHead);
PrintColor(g_Buffer,YELLOW_BLUE);
_sprintf(g_Buffer,"nCylinder = %u\n",nCylinder);
PrintColor(g_Buffer,YELLOW_BLUE);
_sprintf(g_Buffer,"nSector = %u\n",nSector);
PrintColor(g_Buffer,YELLOW_BLUE);
// GetKey();
Floppy_Seek(nDrive,nHead,nCylinder);
//
//Before Issuing a Read command, Initialize the DMA Controller.
//Set up The 8237 DMA chip for reading from the floppy.
//
DMA_SetChannel2ToReadFromFloppy();
PrintColor("Finished Init DMA\n",MAGENTA_BLUE);
// GetKey();
//
//READ
//
Floppy_SendByte( (BYTE)( 0x46 ) );//0100-0110//(bit 7=MT=Multi-Track function=0),(bit 6=MFM=A one selects the double density (MFM) mode=1),(bit 5=SK=Skip flag=0),-0110
byte = (BYTE)((nHead<<2)&0x4)|(BYTE)nDrive;
Floppy_SendByte( byte );//0000-0001//0000-(bit 2=HDS=0),(bit 1=DS1),(bit 0=DS0)
Floppy_SendByte( (BYTE)nCylinder );//C = Cylinder address
Floppy_SendByte( (BYTE)nHead );//H=Head address.
Floppy_SendByte( (BYTE)nSector );//R=Sector address.
Floppy_SendByte( 02 );//N (bytes per sector).
Floppy_SendByte( 18 );//EOT = End of track.
Floppy_SendByte( 0x1B );//GPL = Gap length.
Floppy_SendByte( (BYTE)0xFF );//DTL (number of bytes to be transferred)
// Floppy_GetMainStatusInformation();
//
//Read returned Data
//
Floppy_GetByte(&byte);//ST0
Floppy_GetByte(&byte);//ST1
ST0_ReturnedByte = byte;//<-----
ST1_ReturnedByte = byte;//<-----
Floppy_GetByte(&byte);//ST2
ST2_ReturnedByte = byte;//<-----
Floppy_GetByte(&byte);//C
_sprintf(g_Buffer,"C = 0x%X\n",byte&0xFF);
PrintColor(g_Buffer,YELLOW_BLUE);
Floppy_GetByte(&byte);//H
_sprintf(g_Buffer,"H = 0x%X\n",byte&0xFF);
PrintColor(g_Buffer,YELLOW_BLUE);
Floppy_GetByte(&byte);//R
R_ReturnedByte=byte;//<-----
_sprintf(g_Buffer,"R = 0x%X\n",R_ReturnedByte&0xFF);
PrintColor(g_Buffer,YELLOW_BLUE);
Floppy_GetByte(&byte);//N
_sprintf(g_Buffer,"N = 0x%X\n",byte&0xFF);
PrintColor(g_Buffer,YELLOW_BLUE);
GetKey();
Floppy_Print_ST0(ST0_ReturnedByte);
Floppy_Print_ST1(ST1_ReturnedByte);
Floppy_Print_ST2(ST2_ReturnedByte);
GetKey();
//
//Check if Sector count increament (if not it was in error in the last operation).
//
if(nSector<FLOPPY_NUMBER_OF_SECTORS)
{
if(R_ReturnedByte!=nSector+1)
{
PrintColor("Error Reading Sector\n",RED_BLUE);
GetKey();
}
}
else//nSector==FLOPPY_NUMBER_OF_SECTORS
{
if(R_ReturnedByte!=1)
{
PrintColor("Error Reading Sector\n",RED_BLUE);
GetKey();
}
}
//
//For Floppys the output buffer is at address-->FLOPPY_RESERVED_AREA_FOR_IO
//
pBuffer = (char*)FLOPPY_RESERVED_AREA_FOR_IO;
//Wait for IRQ
if(!IRQ_WaitForIRQ(6,80))
{
PrintColor("ERROR: READ Timed Out\n",RED_BLUE);
GetKey();
}
PrintColor("Done Reading Sector\n",CYAAN_BLUE);
GetKey();
return TRUE;
}
////////////////////////////////////////////
//
////////////////////////////////////////////
BOOL Floppy_WriteSector(DWORD nDrive,char *pBuffer,DWORD nInputSector)
{
static BYTE byte;
BYTE R_ReturnedByte;
DWORD nSector;
DWORD nCylinder;
DWORD nHead;
BYTE ST0_ReturnedByte;
BYTE ST1_ReturnedByte;
BYTE ST2_ReturnedByte;
//
//Make sure that user is not trying to Write larger then the floppy
//
if(nInputSector>FLOPPY_MAX_NUMBER_OF_SECTORS)
{
PrintColor("You are trying to Write to a to large nSector\n",RED_BLUE);
GetKey();
return FALSE;
}
//
//Init Controller
//
Floppy_InitControllerForCommands(nDrive);
//
//Recalibrate Controller (Move Floppy head to track 0).
//
Floppy_Recalibrate(nDrive);
//
//Calculate Head,Cylinder,Sector from nSector
//
nSector = nInputSector%FLOPPY_NUMBER_OF_SECTORS;
nInputSector -= nSector;
nSector++;//Remember Sectors start with 1 (not 0).
nInputSector/=FLOPPY_NUMBER_OF_SECTORS;
nHead = (nInputSector)%FLOPPY_NUMBER_OF_HEADS;
nCylinder = nInputSector/FLOPPY_NUMBER_OF_HEADS;
Floppy_Seek(nDrive,nHead,nCylinder);
//
//Copy Input buffer to the DMA read buffer.
//
memcpy((char*)FLOPPY_RESERVED_AREA_FOR_IO,pBuffer,512);
//
//Before Issuing a Write command, Initialize the DMA Controller.
//Set up The 8237 DMA chip for writting to the floppy.
//
DMA_SetChannel2ToWriteToFloppy();
PrintColor("Finished Init DMA\n",MAGENTA_BLUE);
// GetKey();
//
//WRITE
//
Floppy_SendByte( (BYTE)( 0x45 ) );//0100-0101//(bit 7=MT=Multi-Track function=0),(bit 6=MFM=A one selects the double density (MFM) mode=1),(bit 5=SK=Skip flag=0),-0110
byte = (BYTE)((nHead<<2)&0x4)|(BYTE)nDrive;
Floppy_SendByte( byte );//0000-0001//0000-(bit 2=HDS=0),(bit 1=DS1),(bit 0=DS0)
Floppy_SendByte( (BYTE)nCylinder );//C = Cylinder address
Floppy_SendByte( (BYTE)nHead );//H=Head address.
Floppy_SendByte( (BYTE)nSector );//R=Sector address.
Floppy_SendByte( 02 );//N (bytes per sector).
Floppy_SendByte( 18 );//EOT = End of track.
Floppy_SendByte( 0x1B );//GPL = Gap length.
Floppy_SendByte( (BYTE)0xFF );//DTL (number of bytes to be transferred)
// Floppy_GetMainStatusInformation();
//
//Read returned Data
//
Floppy_GetByte(&byte);//ST0
Floppy_GetByte(&byte);//ST1
ST0_ReturnedByte = byte;//<-----
ST1_ReturnedByte = byte;//<-----
Floppy_GetByte(&byte);//ST2
ST2_ReturnedByte = byte;//<-----
Floppy_GetByte(&byte);//C
_sprintf(g_Buffer,"C = 0x%X\n",byte&0xFF);
PrintColor(g_Buffer,YELLOW_BLUE);
Floppy_GetByte(&byte);//H
_sprintf(g_Buffer,"H = 0x%X\n",byte&0xFF);
PrintColor(g_Buffer,YELLOW_BLUE);
Floppy_GetByte(&byte);//R
R_ReturnedByte=byte;//<-----
_sprintf(g_Buffer,"R = 0x%X\n",R_ReturnedByte&0xFF);
PrintColor(g_Buffer,YELLOW_BLUE);
Floppy_GetByte(&byte);//N
_sprintf(g_Buffer,"N = 0x%X\n",byte&0xFF);
PrintColor(g_Buffer,YELLOW_BLUE);
GetKey();
Floppy_Print_ST0(ST0_ReturnedByte);
Floppy_Print_ST1(ST1_ReturnedByte);
Floppy_Print_ST2(ST2_ReturnedByte);
GetKey();
//
//Check if Sector count increament (if not it was in error in the last operation).
//
if(nSector<FLOPPY_NUMBER_OF_SECTORS)
{
if(R_ReturnedByte!=nSector+1)
{
PrintColor("Error Writting To Sector\n",RED_BLUE);
GetKey();
}
}
else//nSector==FLOPPY_NUMBER_OF_SECTORS
{
if(R_ReturnedByte!=1)
{
PrintColor("Error Reading Sector\n",RED_BLUE);
GetKey();
}
}
//
//Wait for IRQ
//
if(!IRQ_WaitForIRQ(6,80))
{
PrintColor("ERROR: WRITE Timed Out\n",RED_BLUE);
GetKey();
}
PrintColor("Done Writting To Sector\n",CYAAN_BLUE);
GetKey();
return TRUE;
}
////////////////////////////////////////////
//
////////////////////////////////////////////
BOOL Floppy_FormatTrack(DWORD nDrive,DWORD nHead,DWORD nCylinder)
{
BYTE byte;
DWORD loop;
DWORD nSector;
char *pBuffer;
BYTE ST0_ReturnedByte;
BYTE ST1_ReturnedByte;
BYTE ST2_ReturnedByte;
Floppy_Seek(nDrive,nHead,nCylinder);
//
//Before Issuing a Write command, Initialize the DMA Controller.
//
//Set up The 8237 DMA chip for Writting to the floppy.
//
nSector=1;
pBuffer = (char*)FLOPPY_RESERVED_AREA_FOR_IO;
for(loop=0;loop<(FLOPPY_NUMBER_OF_SECTORS*4);loop+=4)
{
//C, H, R, N
pBuffer[loop]=(BYTE)nCylinder;//C
pBuffer[loop+1]=(BYTE)nHead;//H
pBuffer[loop+2]=(BYTE)nSector;//R
pBuffer[loop+3]=0x02;//512 bytes
nSector++;
}
//Init DMA
DMA_SetChannel2ToFormatFloppy();
//
//FORMAT
//
Floppy_SendByte( (BYTE)( 0x4D ) );//0100-0101//(bit 7=0),(bit 6=MFM=A one selects the double density (MFM) mode=1),(bit 5=0),-(1101==FORMAT Command)
byte = (BYTE)((nHead<<2)&0x4)|(BYTE)nDrive;
Floppy_SendByte( byte );//0000-0001//0000-(bit 2=HDS=0),(bit 1=DS1),(bit 0=DS0)
Floppy_SendByte( 02 );//N (bytes per sector).
Floppy_SendByte( 18 );//SC (sectors per cylinder).
Floppy_SendByte( 0x54 );//GPL (Gap length for Format.).
Floppy_SendByte( 0xF6 );//D (The pattern to be written in each sector data field during formatting.).
// Floppy_GetMainStatusInformation();
Floppy_GetByte(&byte);//ST0
ST0_ReturnedByte = byte;
Floppy_GetByte(&byte);//ST1
ST1_ReturnedByte = byte;
Floppy_GetByte(&byte);//ST2
ST2_ReturnedByte = byte;
Floppy_GetByte(&byte);//Undefined
Floppy_GetByte(&byte);//Undefined
Floppy_GetByte(&byte);//Undefined
Floppy_GetByte(&byte);//Undefined
Floppy_Print_ST0(ST0_ReturnedByte);
Floppy_Print_ST1(ST1_ReturnedByte);
Floppy_Print_ST2(ST2_ReturnedByte);
//Wait for IRQ
if(!IRQ_WaitForIRQ(6,80))
{
PrintColor("ERROR: FORMAT Timed Out\n",RED_BLUE);
GetKey();
}
return TRUE;
}
////////////////////////////////////////////
//
////////////////////////////////////////////
BOOL Floppy_FormatFloppy(DWORD nDrive)
{
DWORD loop;
static BYTE byte;
DWORD nSector=0;
DWORD nCylinder=0;
DWORD nHead=0;
//
//Init Controller
//
Floppy_InitControllerForCommands(nDrive);
//
//Recalibrate Controller (Move Floppy head to track 0).
//
Floppy_Recalibrate(nDrive);
for(loop=0;loop<FLOPPY_NUMBER_OF_CYLINDERS;loop++)
{
Floppy_FormatTrack(nDrive,0,loop);
Floppy_FormatTrack(nDrive,1,loop);
_sprintf(g_Buffer,"Formatting = %u\n",loop);
PrintColor(g_Buffer,CYAAN_BLUE);
}
//
PrintColor("Press any key to continue.....\n",MAGENTA_BLUE);
GetKey();
return TRUE;
}
////////////////////////////////////////////
//
////////////////////////////////////////////
BOOL Floppy_InitControllerForCommands(DWORD nDrive)
{
DWORD loop;
static BYTE byte;
//
//Reset Floppy.
//
byte = 0x08;//0000-1000 (MOT EN3,MOT EN2,MOT EN1,MOT EN0,- 0=DMA 1=!DMA,0=Reset 1=!Reset,Drive1,Drive0)
_outp_( (WORD)(FLOPPY_DIGITAL_OUTPUT_REGISTER) , byte);
//Make Sure that the Drive was reseted.
Floppy_Delay4us();
Floppy_Delay4us();
Floppy_Delay4us();
Floppy_Delay4us();
Floppy_Delay4us();
//
//Stop Reset and Enable Drive & Motor.
//
//0001-1100 (MOT EN3,MOT EN2,MOT EN1,MOT EN0,- 0=DMA 1=!DMA,0=Reset 1=!Reset,Drive1,Drive0)
if( nDrive == 0 )
byte|=0x1C;
else if( nDrive == 1 )
byte|=0x2D;
_outp_( (WORD)(FLOPPY_DIGITAL_OUTPUT_REGISTER) , byte);
//
//Program Data rate.
//
byte = 0x00;//0000-00 Data Rate//(Reset),(Power-Down),(0),(0)-(0),(0),(Data rate 1),(Data rate 0)
byte |= FLOPPY_DATA_RATE_300K;
_outp_(FLOPPY_DATA_RATE_SELECT_REGISTER,byte);
//Wait for IRQ
if(!IRQ_WaitForIRQ(6,80))
{
PrintColor("ERROR: RESET Timed Out\n",RED_BLUE);
GetKey();
}
//
//4 times send SENSE_INTERRUPT (and read ST0, and PCN).
//
for(loop=0;loop<4;loop++)
{
Floppy_SendByte(SENSE_INTERRUPT);
Floppy_GetByte(&byte);//Read ST0
Floppy_GetByte(&byte);//Read PCN
}
//
//CONFIGURE floppy
//
Floppy_SendByte( CONFIGURE );
Floppy_SendByte( 0 );//
Floppy_SendByte( 0x20 );//0010-0000//0,EIS,EFIFO,POLL, - (FIFOTHR 4-bits)
Floppy_SendByte( 0 );//PRETRK
/****************************************************************
SRT
This is the "Step Rate Time", which determines how long the floppy
drive should wait for the head to move between tracks. A reasonable
amount of time to allow for this is around 8 mS, but the actual
value used depends on the data rate. The formula for calculating
the delay from SRT value and the data rate is
"seconds = (16 - SRT_value)/data_rate * 500000".
To find the "best" SRT value this can be transformed
into "SRT_value = 16 - (seconds * data_rate / 500000)".
For a 1.44 MB floppy and 8 mS delay this gives
"SRT_value = 16 - (0.008 * 500000 / 500000)" or a value of 8.
HLT
This is the "Head Load Time", which determines how long
the floppy drive should wait for the head to become ready
after the head has been moved. A reasonable value for this is
around 10 mS, but like the SRT the delay depends on the data rate.
To find the delay from the HLT value and the data rate the formula
is "seconds = HLT_value / data_rate * 1000". To find the "best"
HLT value this can be transformed into "HLT_value = seconds * data_rate / 1000".
For a 1.44 MB floppy and a 10 mS delay this gives "HLT_value = 0.01 * 500000 / 1000" or 5.
For the specify command, a HLT value of 16 is
represented with zero (no delay isn't possible).
HUT
This is the "Head Unload Time", which determines how long
the floppy drive should wait before setting the head to it's
unloaded state after data is read or written (I think that if
the another command begins before this time expires the HLT
delay is avoided, but can't be sure). A reasonable value for
this is around 240 mS, but this delay also depends on the
data rate. To find the delay from the HUT value and the
data rate the formula is "seconds = HUT_value / data_rate * 8000".
To find the "best" HLT value this can be transformed into
"HUT_value = seconds * data_rate / 8000". For a 1.44 MB floppy
and a 240 mS delay this gives "HLT_value = 0.24 * 500000 / 8000"
or 15. For the specify command, a HUT value of 128 is represented
with zero (no delay isn't possible).
****************************************************************/
//
//SPECIFY (Init delays).
//
//HUT=(HeadUnload Time) = 240 mS
//SRT=(Step Rate Time) = 8ms = 0xD (for 250 kb rate)
//ND=None DMA
//HLT=(Head Load Time) = 10 mS
//---------------------------------------
Floppy_SendByte( SPECIFY );
byte=(BYTE)(0x0<<4)&0xF0;//SRT
byte|=0;//HUT
Floppy_SendByte( byte );//(bit 4-7)SRT, (bit 0-3)HUT
byte=(BYTE)0x00;//HLT
byte&=(0xFE|0);//ND
Floppy_SendByte( byte );//0000-1110//(bit 1-7)HLT, (bit 0)ND
//----------------------------------------
//Delay 500ms for Motor to speed up to the right speed.
for(loop=0;loop<10;loop++)
{
Floppy_Delay4us();
}
PrintColor("Done Init\n",YELLOW_BLUE);
return TRUE;
}
////////////////////////////////////////////
//When Done reading or writting or formatting, Shot down the mottor.
////////////////////////////////////////////
BOOL Floppy_DoneRW(DWORD nDrive)
{
//0x0C = 0000-1100 (MOT EN3,MOT EN2,MOT EN1,MOT EN0,- 0=DMA 1=!DMA,0=Reset 1=!Reset,Drive1,Drive0)
_outp_( (WORD)(FLOPPY_DIGITAL_OUTPUT_REGISTER) , 0x0C);
return TRUE;
}
////////////////////////////////////////////
//
////////////////////////////////////////////
BOOL Floppy_VerifySector(DWORD nDrive,char *pBuffer,DWORD nSector)
{
return TRUE;
}
////////////////////////////////////////////
//
////////////////////////////////////////////
BOOL Floppy_IsThereADrive(DWORD nDrive)
{
static BYTE byte;
CMOS_GetByte(0x10,&byte);
// _sprintf(g_Buffer,"byte = 0x%X\n",byte&0xFF);
// PrintColor(g_Buffer,YELLOW_BLUE);
if(nDrive==0)
{
byte>>=4;
byte &= 0x0F;
}
else if(nDrive==1)
{
byte &= 0x0F;
}
else
{
PrintColor("This OS dosn't support more the 2 floppys\n",RED_BLUE);
GetKey();
return FALSE;
}
switch(byte)
{
case 0:
PrintColor("No Drive\n",YELLOW_BLUE);
GetKey();
break;
case 1:
PrintColor("360KB Drive (This OS dosn't support this kind of floppy)\n",YELLOW_BLUE);
GetKey();
break;
case 2:
PrintColor("1.2MB Drive (This OS dosn't support this kind of floppy)\n",YELLOW_BLUE);
GetKey();
break;
case 3:
PrintColor("720KB Drive (This OS dosn't support this kind of floppy)\n",YELLOW_BLUE);
GetKey();
break;
case 4:
PrintColor("1.44MB Drive\n",YELLOW_BLUE);
GetKey();
return TRUE;
break;
case 5:
PrintColor("2.88MB Drive (This OS dosn't support this kind of floppy)\n",YELLOW_BLUE);
GetKey();
break;
default:
PrintColor("Unknown Value\n",RED_BLUE);
GetKey();
}
return FALSE;
}
////////////////////////////////////////////
//
////////////////////////////////////////////
BOOL Floppy_IsThereADiskInTheDrive(DWORD nDrive)
{
BYTE StatusRegister;
//
//Init Controller
//
Floppy_InitControllerForCommands(nDrive);
//
//Recalibrate Controller (Move Floppy head to track 0).
//
Floppy_Recalibrate(nDrive);
StatusRegister = _inp_( FLOPPY_DIGITAL_INPUT_REGISTER );
if(StatusRegister&0x80)//the Disk Change bit.
{
Floppy_Seek(nDrive,0,1);
Floppy_Seek(nDrive,0,0);
StatusRegister = _inp_( FLOPPY_DIGITAL_INPUT_REGISTER );
if(StatusRegister&0x80)//the Disk Change bit.
{
PrintColor("Media Not Present (Please Insert Floopy)\n",RED_BLUE);
GetKey();
Floppy_DoneRW(0);
return FALSE;
}
}
//
//Shot down floppy.
//
Floppy_DoneRW(0);
return TRUE;
}
////////////////////////////////////////////
//
////////////////////////////////////////////
BOOL Floppy_SendByte(BYTE byte)
{
BYTE StatusRegister;
DWORD dwOldTime = g_dwTimerCount;
while(1)
{
StatusRegister = _inp_( FLOPPY_MAIN_STATUS_REGISTER );//Read MSR
if( (StatusRegister & FLOPPY_MSR_READY) &&
!(StatusRegister & FLOPPY_MSR_READ_DRIECTION) )
break;
//Wait for Time out
if(g_dwTimerCount>(dwOldTime + 25)||dwOldTime>(g_dwTimerCount+25))
{
PrintColor("Floppy_SendByte() TimedOut\n",RED_BLUE);
GetKey();
return FALSE;
}
}
_outp_( (WORD)(FLOPPY_DATA_FIFO) , byte);
return TRUE;
}
////////////////////////////////////////////
//
////////////////////////////////////////////
BOOL Floppy_GetByte(BYTE *pByte)
{
BYTE StatusRegister;
DWORD dwOldTime = g_dwTimerCount;
while(1)
{
StatusRegister = _inp_( FLOPPY_MAIN_STATUS_REGISTER );//Read MSR
if( (StatusRegister & FLOPPY_MSR_READY) &&
(StatusRegister & FLOPPY_MSR_READ_DRIECTION) )
break;
//Wait for Time out
if(g_dwTimerCount>(dwOldTime + 40)||dwOldTime>(g_dwTimerCount+40))
{
PrintColor("Floppy_GetByte() TimedOut\n",RED_BLUE);
GetKey();
return FALSE;
}
}
*pByte = _inp_( (WORD)(FLOPPY_DATA_FIFO) );
return TRUE;
}
////////////////////////////////////////////
//
////////////////////////////////////////////
void Floppy_GetMainStatusInformation()
{
BYTE MainStatusRegister;
MainStatusRegister = _inp_( (WORD)(FLOPPY_MAIN_STATUS_REGISTER) );
// _sprintf(g_Buffer,"MainStatusRegister = 0x%X\n",MainStatusRegister&0xFF);
// PrintColor(g_Buffer,YELLOW_BLUE);
if(MainStatusRegister&0x1)
{
PrintColor("Drive 0 Busy\n",YELLOW_BLUE);
}
if((MainStatusRegister>>1)&0x1)
{
PrintColor("Drive 1 Busy\n",YELLOW_BLUE);
}
if((MainStatusRegister>>2)&0x1)
{
PrintColor("Drive 2 Busy\n",YELLOW_BLUE);
}
if((MainStatusRegister>>3)&0x1)
{
PrintColor("Drive 3 Busy\n",YELLOW_BLUE);
}
if((MainStatusRegister>>4)&0x1)
{
PrintColor("COMMAND BUSY (command is in progress).\n",YELLOW_BLUE);
}
if(MainStatusRegister>>5&0x1)
{
PrintColor("NON-DMA\n",YELLOW_BLUE);
}
if((MainStatusRegister>>6)&0x1)
{
PrintColor("Direction I/O Read\n",YELLOW_BLUE);
}
else
{
PrintColor("Direction I/O Write\n",YELLOW_BLUE);
}
if((MainStatusRegister>>7)&0x1)
{
PrintColor("Host can transfer data\n",YELLOW_BLUE);
}
else
{
PrintColor("Host can't transfer data\n",YELLOW_BLUE);
}
}
////////////////////////////////////////////
//
////////////////////////////////////////////
BOOL Floppy_Recalibrate(DWORD nDrive)
{
BYTE byte;
//
//RECALIBRATE (Move head to track 0).
//
Floppy_SendByte( RECALIBRATE );
if( nDrive==0 )
byte=0;
else if( nDrive==1 )
byte=1;
Floppy_SendByte( byte );//Drive Select (0-3 drives).
//Wait for IRQ
if(!IRQ_WaitForIRQ(6,80))
{
PrintColor("ERROR: RECALIBRATE Timed Out\n",RED_BLUE);
GetKey();
return FALSE;
}
//
//SENSE_INTERRUPT
//
Floppy_SendByte( SENSE_INTERRUPT );
Floppy_GetByte(&byte);//Read ST0
Floppy_GetByte(&byte);//Read PCN
return TRUE;
}
////////////////////////////////////////////
//
////////////////////////////////////////////
BOOL Floppy_Seek(DWORD nDrive,DWORD nHead,DWORD nCylinder)
{
BYTE byte;
//
//SEEK
//
Floppy_SendByte( SEEK );
byte = (BYTE)( ((BYTE)(nHead&0xFF)<<2)|(BYTE)(nDrive&0xFF) );
Floppy_SendByte( byte );//(bit 2-HDS), Drive Select (0-3 drives) (bit1 and bit0).
Floppy_SendByte( (BYTE)nCylinder );//New Cylinder
//Wait for IRQ
if(!IRQ_WaitForIRQ(6,80))
{
PrintColor("ERROR: SEEK Timed Out\n",RED_BLUE);
GetKey();
}
//
//SENSE_INTERRUPT
//
Floppy_SendByte( SENSE_INTERRUPT );
Floppy_GetByte(&byte);//Read ST0
Floppy_GetByte(&byte);//Read PCN
return TRUE;
}
////////////////////////////////////////////
//
////////////////////////////////////////////
void Floppy_Print_ST0(BYTE ST0)
{
PrintColor("*************ST0*************\n",MAGENTA_BLUE);
switch((ST0>>6)&0x3)//bit 7-6
{
case 0:
PrintColor("Normal termination of command.\n",YELLOW_BLUE);
break;
case 1:
PrintColor("Abnormal termination of command.\n",YELLOW_BLUE);
break;
case 2:
PrintColor("Invalid command. The requested command could not be executed.\n",YELLOW_BLUE);
break;
case 3:
PrintColor("Abnormal termination caused by Polling.\n",YELLOW_BLUE);
break;
}
if((ST0>>5)&0x1)
{
PrintColor("SEEK END.\n",YELLOW_BLUE);
}
if((ST0>>4)&0x1)
{
PrintColor("The TRK0 pin failed to become a '1' (For more info see datasheet).\n",YELLOW_BLUE);
}
_sprintf(g_Buffer,"Head Address = %u\n",(ST0>>2&0x1)&0xFF);
PrintColor(g_Buffer,YELLOW_BLUE);
switch(ST0&0x3)//bit 1-0
{
case 0:
PrintColor("Drive 0.\n",YELLOW_BLUE);
break;
case 1:
PrintColor("Drive 1.\n",YELLOW_BLUE);
break;
case 2:
PrintColor("Drive 2.\n",YELLOW_BLUE);
break;
case 3:
PrintColor("Drive 3.\n",YELLOW_BLUE);
break;
}
PrintColor("*****************************\n",MAGENTA_BLUE);
// GetKey();
}
////////////////////////////////////////////
//
////////////////////////////////////////////
void Floppy_Print_ST1(BYTE ST1)
{
PrintColor("*************ST1*************\n",MAGENTA_BLUE);
if((ST1>>7)&0x1)
{
PrintColor("ERROR: End of Cylinder.\n",YELLOW_BLUE);
}
//--
if((ST1>>5)&0x1)
{
PrintColor("CRC error.\n",YELLOW_BLUE);
}
if((ST1>>4)&0x1)
{
PrintColor("CPU or DMA is not R or W from controller.\n",YELLOW_BLUE);
}
//--
if((ST1>>2)&0x1)
{
PrintColor("No Data.\n",YELLOW_BLUE);
}
if((ST1>>1)&0x1)
{
PrintColor("Not Writable.\n",YELLOW_BLUE);
}
if(ST1&0x1)
{
PrintColor("Missing Address Mark.\n",YELLOW_BLUE);
}
PrintColor("*****************************\n",MAGENTA_BLUE);
// GetKey();
}
////////////////////////////////////////////
//
////////////////////////////////////////////
void Floppy_Print_ST2(BYTE ST2)
{
PrintColor("*************ST2*************\n",MAGENTA_BLUE);
//--
if((ST2>>6)&0x1)
{
PrintColor("Control Mark.\n",YELLOW_BLUE);
}
if((ST2>>5)&0x1)
{
PrintColor("Data Error in Data Field..\n",YELLOW_BLUE);
}
if((ST2>>4)&0x1)
{
PrintColor("Wrong Cylinder.\n",YELLOW_BLUE);
}
//--
//--
if((ST2>>1)&0x1)
{
PrintColor("Bad Cylinder.\n",YELLOW_BLUE);
}
if((ST2>>0)&0x1)
{
PrintColor("Missing Data Address Mark.\n",YELLOW_BLUE);
}
PrintColor("*****************************\n",MAGENTA_BLUE);
// GetKey();
}
////////////////////////////////////////////
//
////////////////////////////////////////////
void Floppy_Print_ST3(BYTE ST3)
{
PrintColor("*************ST3*************\n",MAGENTA_BLUE);
if((ST3>>6)&0x1)
{
PrintColor("Write Protected.\n",YELLOW_BLUE);
}
_sprintf(g_Buffer,"The status of the TRK0 pin = 0x%X\n",(ST3>>4&0x1)&0xFF);
PrintColor(g_Buffer,YELLOW_BLUE);
_sprintf(g_Buffer,"Head Address = %u\n",(ST3>>2&0x1)&0xFF);
PrintColor(g_Buffer,YELLOW_BLUE);
switch(ST3&0x3)//bit 1-0
{
case 0:
PrintColor("Drive 0.\n",YELLOW_BLUE);
break;
case 1:
PrintColor("Drive 1.\n",YELLOW_BLUE);
break;
case 2:
PrintColor("Drive 2.\n",YELLOW_BLUE);
break;
case 3:
PrintColor("Drive 3.\n",YELLOW_BLUE);
break;
}
PrintColor("*****************************\n",MAGENTA_BLUE);
GetKey();
}
////////////////////////////////////////////////////////////////
//DMA
////////////////////////////////////////////////////////////////
//
//DMA Address & Control registers.
//
#define DMA_8_BIT_CANNEL_0_ADDRESS_PORT 0x00
#define DMA_8_BIT_CANNEL_0_COUNT_PORT 0x01
#define DMA_8_BIT_CANNEL_1_ADDRESS_PORT 0x02
#define DMA_8_BIT_CANNEL_1_COUNT_PORT 0x03
#define DMA_8_BIT_CANNEL_2_ADDRESS_PORT 0x04
#define DMA_8_BIT_CANNEL_2_COUNT_PORT 0x05
#define DMA_8_BIT_CANNEL_3_ADDRESS_PORT 0x06
#define DMA_8_BIT_CANNEL_3_COUNT_PORT 0x07
#define DMA_16_BIT_CANNEL_4_ADDRESS_PORT 0xC0
#define DMA_16_BIT_CANNEL_4_COUNT_PORT 0xC2
#define DMA_16_BIT_CANNEL_5_ADDRESS_PORT 0xC4
#define DMA_16_BIT_CANNEL_5_COUNT_PORT 0xC6
#define DMA_16_BIT_CANNEL_6_ADDRESS_PORT 0xC8
#define DMA_16_BIT_CANNEL_6_COUNT_PORT 0xCA
#define DMA_16_BIT_CANNEL_7_ADDRESS_PORT 0xCC
#define DMA_16_BIT_CANNEL_7_COUNT_PORT 0xCE
//
//Page Registers
//
#define DMA_8_BIT_CANNEL_0_PAGE 0x87
#define DMA_8_BIT_CANNEL_1_PAGE 0x83
#define DMA_8_BIT_CANNEL_2_PAGE 0x81
#define DMA_8_BIT_CANNEL_3_PAGE 0x82
#define DMA_16_BIT_CANNEL_4_PAGE 0x8F
#define DMA_16_BIT_CANNEL_5_PAGE 0x8B
#define DMA_16_BIT_CANNEL_6_PAGE 0x89
#define DMA_16_BIT_CANNEL_7_PAGE 0x8A
//
//Status Registers
//
#define DMA_8_BIT_STATUS_REGISTERS 0x08
#define DMA_16_BIT_STATUS_REGISTERS 0xD0
//
//Command Registers (Write)
//
#define DMA_8_BIT_COMMAND_REGISTERS 0x08
#define DMA_16_BIT_COMMAND_REGISTERS 0xD0
//
//Request Registers
//
#define DMA_8_BIT_REQUST_REGISTERS 0x09
#define DMA_16_BIT_REQUST_REGISTERS 0xD2
//
//Channel Mask Registers
//
#define DMA_8_BIT_CHANNEL_MASK_REGISTERS 0x0A
#define DMA_16_BIT_CHANNEL_MASK_REGISTERS 0xD4
//
//Mask Registers
//
#define DMA_8_BIT_MASK_REGISTERS 0x0F
#define DMA_16_BIT_MASK_REGISTERS 0xDE
//
//Mode Registers
//
#define DMA_8_BIT_MODE_REGISTERS 0x0B
#define DMA_16_BIT_MODE_REGISTERS 0xD6
//
//Byte / Word Register
//
#define DMA_8_BIT_BYTE_REGISTERS 0x0C
#define DMA_16_BIT_WORD_REGISTERS 0xD8
//
//Intermediate Register
//
#define DMA_8_BIT_INTERMEDIATE_REGISTERS 0x0D
#define DMA_16_BIT_INTERMEDIATE_REGISTERS 0xDA
////////////////////////////////////////////
//
//Routine Name: DMA_SetChannel2ToReadFromFloppy()
//
//
//Routine Description:
//
// Set up the 8237 DMA chip for reading 512 bytes
// from the floppy controller, to address FLOPPY_RESERVED_AREA_FOR_IO
//
//Return Value: None
//
//Error Handeling: None
//
//Auther: S.Z.Keller
//
////////////////////////////////////////////
BOOL DMA_SetChannel2ToReadFromFloppy()
{
//Mask Channel 2
_outp_(DMA_8_BIT_CHANNEL_MASK_REGISTERS, 0x6);//0000-0110//0000-0,(1 - Set mask bit),(1- Select channel 2 mask bit),(0)
//Reset the master flip-flop
_outp_(DMA_16_BIT_WORD_REGISTERS, (BYTE)0xFF);
//Destination address
_outp_(DMA_8_BIT_CANNEL_2_ADDRESS_PORT, (BYTE)(FLOPPY_RESERVED_AREA_FOR_IO)&0xFF);//(low byte)
_outp_(DMA_8_BIT_CANNEL_2_ADDRESS_PORT, (BYTE)(FLOPPY_RESERVED_AREA_FOR_IO>>8)&0xFF);//(high byte)
//Reset the master flip-flop
_outp_(DMA_16_BIT_WORD_REGISTERS, (BYTE)0xFF);
//Number of bytes to transfore (0x1FF = 512-1) because it starts with Index 0
_outp_(DMA_8_BIT_CANNEL_2_COUNT_PORT, (BYTE)0xFF);//(low byte)
_outp_(DMA_8_BIT_CANNEL_2_COUNT_PORT, (BYTE)0x01);//(high byte)
//(The 16-20 bits of the Base address)
_outp_(DMA_8_BIT_CANNEL_2_PAGE, (BYTE)(FLOPPY_RESERVED_AREA_FOR_IO>>16)&0xFF);
//Transforem Mode
//( [0100-0110] -0100-0110
//--------------------------------------
// Single transfer, -01
// address increment, -0
// Autoinitialized, -0
// Read transfer, -01
// Channel 2 select) -10
_outp_(DMA_8_BIT_MODE_REGISTERS, (BYTE)0x46);
//unmask DMA channel 2
_outp_(DMA_8_BIT_CHANNEL_MASK_REGISTERS, (BYTE)2);
return TRUE;
}