⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fdbios.cpp

📁 dos下直接对软盘控制器操作的C++类, 用它可以制作
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*

Floppy Disk Tools v1.2 Final version write by 孙宝建
12-15-2002

*/
//#include "stdafx.h"
#include "fdbios.h"
#include <stdlib.h>
#include <dos.h>
#include <stdio.h>
#include<io.h>
#include<fcntl.h>
#include <conio.h>

BOOL CFDBios::SendCommand(USHORT ucCommand)
{
  if(IsWriteReady())
	{
	  _outp(0x3f5,ucCommand);
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

BOOL CFDBios::IsReadReady()
{
	int i=0;
	while( i<CONTROL_TIME)
	{
		
		CHAR ret=_inp(0x3f4);
		if( READREADY(ret) )
		{
			return TRUE;
		}
		if( WRITEREADY(ret) )
		{
			uError=STATUS_READ;
			return FALSE;
		}
		i++;
	}
	uError=CONTROL_OVER_TIME;
	return FALSE;
}
 BOOL CFDBios::IsWriteReady()
{
	int i=0;
	while( i<CONTROL_TIME)
	{
		
		CHAR ret=_inp(0x3f4);
		if( WRITEREADY(ret) )
		{
			return TRUE;
		}
		if( READREADY(ret) )
		{
			uError=STATUS_WRITE;
			return FALSE;
		}
    i++;
	}
	uError=CONTROL_OVER_TIME;
	return FALSE;
}

void CFDBios::DetectFD(void)
{
	ucDiskNumber=0;
	_outp(0x3f7,0);
	uError=NO_FD;
	StartMotor();
	if( Reset())
	{
		uError=OK;
	}
	else
	{
		uError=NO_FD;
	}
	ShutMotor();
}
void CFDBios::StartMotor(void)
{
	switch(ucDiskNumber)
	{
	case 0:_outp(0x3f2,0x1C);break;
	case 1:_outp(0x3f2,0x2d);break;
	default:;
	}
	Delay(START_MOTOR_DELAY);
  bMotorWork=TRUE;
}
void CFDBios::ShutMotor(void)
{
  switch(ucDiskNumber)
	{
	case 0:_outp(0x3f2,0x0c);break;
	case 1:_outp(0x3f2,0x0d);break;
	default:;
	}
  bMotorWork=FALSE;
}
BOOL CFDBios::IsComplete(void)
{
	int i;
	for(i=0;i<WAIT_INT_TIME;i++)
	{
	#ifdef __BORLANDC__	
		Delay30us(MAX_WAIT);
		char *pcIntFlag=(char far*)MK_FP(0X40,0X3E);
		if( (*pcIntFlag) & 0x80)
		{
			*pcIntFlag=0;
			return 1;
		}
		
		/*char ret=_inp(0x3f4);
		if(COMPLETE(ret))
      return TRUE;
      */
	#endif
	#ifdef __DJGPP__
		
	#endif
//	StartMotor();
	_outp(0x3f2,0x1C);
	}	
	return 0;
}

void CFDBios::Delay(int Count)
{
	Delayms(Count);
}

void CFDBios::IoDelay(int delaytimes)
{
//  int i=0;
 // for(i=0;i<delaytimes;i++)
    Delay500ns(delaytimes);
}

BOOL CFDBios::Reset(void)
{
/*  if(!(_inp(0x3f7)&0x80))
  {
    return TRUE;
  }
*/
	if(ExistDisk())
		return TRUE;
	EnableINT();
  for(int i=0;i<MAX_RETRY;i++)
	{
		if( SendCommand(7) )
		{
			
			if( SendCommand(ucDiskNumber) )
			{
				if( IsComplete() )
				{
	        if( IsTrack(0) )
	        {
	          return TRUE;
	        }
				}
			}
		}
		if( !CanRetry() )
			return FALSE;
	}
	uError=OVER_TIMES;
	return FALSE;

}


void CFDBios::DisplayError(char *psErr)
{
	switch (uError)
	{
		case NO_FD					 :sprintf(psErr,"No disk\n"); break;
		case INVALID_BUFFER  :sprintf(psErr,"Invalid buffer\n"); break;
		case OVER_TIME 			 :sprintf(psErr,"Over time\n"); break;
		case STATUS_WRITE		 :sprintf(psErr,"Controller error:Status write \n"); break;
		case STATUS_READ 		 :sprintf(psErr,"Controller error:Status read \n"); break;
		case CONTROL_OVER_TIME :sprintf(psErr,"Controller over time\n"); break;
		case NO_RESPONSE 		 :sprintf(psErr,"Controller no response \n"); break;
		case OVER_TIMES 		 :sprintf(psErr,"Retry fail\n"); break;
		case NO_INT					 :sprintf(psErr,"No int	\n"); break;
		case VALID_COMMAND 	 :sprintf(psErr,"Valid command \n"); break;
		case EXCEPT_TERMINATE:sprintf(psErr,"Except terminate\n"); break;
		case INCORRECT_TRACK :sprintf(psErr,"Incorrect track\n"); break;
		case OVER_LAST_SECTOR:sprintf(psErr,"Over last sector\n");break;
		case ID_CRC          :sprintf(psErr,"Sector id CRC error \n");break;
		case DMA_OVER_TIME   :sprintf(psErr,"DMA over time\n");break;
		case WRITE_PROTECT   :sprintf(psErr,"Write protect\n");break;
		case LOST_ID         :sprintf(psErr,"Lost sector id\n");break;
		case CONTRL_ID       :sprintf(psErr,"Lost contrl id\n");break;
		case DATA_CRC        :sprintf(psErr,"Data CRC error\n");break;
		case TRACK_ERR       :sprintf(psErr,"Track error\n");break;
		case BAD_TRACK       :sprintf(psErr,"Bad track\n");break;
		case ADDRESS_ID      :sprintf(psErr,"ADDRESS_ID\n");break;
		default				 :uError=UNKNOWN_ERROR;sprintf(psErr,"Unknown error\n");
	}
}
void CFDBios::ClearCommand(void)
{ 
	CHAR ret=_inp(0x3f4);
		if( READREADY(ret) )
		{
			ret=_inp(0x3f5);
			while(1)
			{
				ret=_inp(0x3f4);
				if( READREADY(ret) )
				{
					ret=_inp(0x3f5);
				}
				else
				{
					_outp(0x3f2,0x1C);
					return;
				}
			}
		}
		if( WRITEREADY(ret) )
		{
			_outp(0x3f5,0x36);
			while(1)
			{
				ret=_inp(0x3f4);
				if( WRITEREADY(ret) )
				{
					_outp(0x3f5,0x36);
				}
				else
				{
					_outp(0x3f2,0x1C);
					return;
				}
			}
		}		
}

BOOL CFDBios::CanRetry()
{
	switch (uError)
	{
		case STATUS_WRITE:
		case STATUS_READ :
		case CONTROL_OVER_TIME :
		case NO_INT:
		case NO_RESPONSE :
						ClearCommand();return TRUE;

		case VALID_COMMAND :
		case EXCEPT_TERMINATE:
			 /*			ResetController();*/return TRUE;
		case OVER_TIMES:
						return FALSE;
		default:
				 /*		ResetController();*/return TRUE;
	}
}

void CFDBios::ResetController(void)
{
	CHAR tmp=(_inp(0x3f2)|ucDiskNumber)&(0x0fb);
	_outp(0x3f2,tmp);
	_outp(0x3f5,0x36);
	Delay(RESET_TIME);
}

BOOL CFDBios::IsTrack(USHORT ucTrack)
{
	StartMotor();
	for(int i=0;i<MAX_RETRY;i++)
	{
		if( SendCommand(8) )
		{
			Delay(COMMAND8_DELAY);
			if( GetResult() )
			{
				//char tmp=ucResult;
				if( ((~ucResult)&0x80)
				 && ((~ucResult)&0x40) )
				{
					if( GetResult() )
					{
						if( ucResult==ucTrack )
							return TRUE;
						if( ucResult==0x80 )
						{
							uError=NO_INT;
							return FALSE;
						}
						else
						{
							if( ucResult<80)
							{
								uError=INCORRECT_TRACK;
								return FALSE;
							}
						}
					}
				}
				else
				{
					TranResult(ucResult);
				}
			}
		}
		if( !CanRetry() )
			return FALSE;
	}
	uError=OVER_TIMES;
	return FALSE;
}

BOOL CFDBios::GetResult(void)
{
	if( IsReadReady() )
	{
		ucResult=_inp(0x3f5);
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

void CFDBios::TranResult(CHAR Result)
{
	if( (Result&0x80) && (!(Result&0x40)) )
	{
		uError=VALID_COMMAND;
	}
	if( !(Result&0x80) && (Result&0x40) )
	{
		uError=EXCEPT_TERMINATE;
	}
	if( !(Result&0x80) && !(Result&0x40) )
	{
		uError=OK;
	}
}

BOOL CFDBios::GotoTrack(USHORT ucTrack)
{
	for(int i=0;i<MAX_RETRY;i++)
	{
		EnableINT();
		if( SendCommand(0x0f) )
		{
			
			if( SendCommand(ucDiskNumber) )
			{
				
				if( SendCommand(ucTrack) )
				{
					if( IsComplete() )
					{
						Delay(COMMANDF_DELAY);
						if( IsTrack(ucTrack) )
							return TRUE;
					}
				}
			}
		}
		if( !CanRetry() )
			return FALSE;
	}
	uError=OVER_TIMES;
	return FALSE;
}

void CFDBios::StartDMA(CHAR ucCommand,CHAR ucnSectors,
					int ucBytesOfSector,char  *pBuffer)
{

#ifdef __BORLANDC__
  ULONG uwSegment=(FP_SEG(pBuffer));
	int uwOffset=(FP_OFF(pBuffer));//%16;
	int uCount=ucnSectors*ucBytesOfSector-1;
	ULONG tmp=uwSegment*16;
				tmp=tmp+uwOffset;
	_outp(0x0c,ucCommand);
	_outp(0x0b,ucCommand);
	_outp(0x4,tmp & 0x00ff);
	_outp(0x4,(tmp>>8) & 0x0ff );
	_outp(0x81,(tmp>>16)  & 0x0f );
	_outp(0x5,uCount&0x0ff);
	_outp(0x5,(uCount>>8) & 0xff);
	_outp(0x0a,2);
#else
  int uCount=ucnSectors*ucBytesOfSector-1;
	ULONG tmp=(ULONG)pBuffer;
	_outp(0x0c,ucCommand);
	_outp(0x0b,ucCommand);
	_outp(0x4,tmp & 0x00ff);
	_outp(0x4,(tmp>>8) & 0x0ff );
	_outp(0x81,(tmp>>16)  & 0xFf );
	_outp(0x481,(tmp>>24)  & 0xFf );
	_outp(0x5,uCount&0x0ff);
	_outp(0x5,(uCount>>8) & 0xff);
	_outp(0x0a,2);
#endif
}

BOOL CFDBios::ReadSector(CHAR ucTrack,CHAR ucHead,CHAR ucStartSector,
	CHAR ucnSectors,CHAR ucSectorBytesCode,CHAR ucLastSector,
	CHAR ucSectorL)
{
	for( int i=0;i<MAX_RETRY;i++)
	{
		if( Reset() )
		{
			if( GotoTrack(ucTrack) )
			{
				int tmp=GetSectorBytes(ucSectorBytesCode);
				StartDMA(READ_DISK,ucnSectors,tmp,pBuffer);//MAX_ALL_BYTES,pBuffer);
				EnableINT();
				if( SendCommand(0x0e6) )
				{
					
					CHAR tmp2= ucHead<<2;
					if( SendCommand(ucDiskNumber|tmp2) )
					{
						
						if( SendCommand(ucTrack) )
						{
							
							if( SendCommand(ucHead) )
							{
								
								if( SendCommand(ucStartSector) )
								{
									
									if( SendCommand(ucSectorBytesCode) )
									{
										
										if( SendCommand(ucLastSector) )
										{

											if( SendCommand(ucSectorL) )
											{
	
												if( SendCommand(0x0ff) )
												{
													
													if( IsComplete() )
													{
														if( GetErr(7) )
															return TRUE;

													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
		if( !CanRetry() )
			return FALSE;
	}
	if( uError==OK )
		return TRUE;
	else
		return FALSE;
}


BOOL CFDBios::ReadSectorEx(CHAR ucTrack,CHAR ucHead,CHAR ucStartSector,
	CHAR ucnSectors,CHAR ucSectorBytesCode,CHAR ucLastSector,
	CHAR ucSectorL,int uReadBytes)
{
	for( int i=0;i<MAX_RETRY;i++)
	{
		if(Reset() )
		{
			if( GotoTrack(ucTrack) )
			{
				StartDMA(READ_DISK,ucnSectors,uReadBytes,pBuffer);//MAX_ALL_BYTES,pBuffer);
				EnableINT();
				if( SendCommand(0x0e6) )
				{
					
					CHAR tmp2= ucHead<<2;
					if( SendCommand(ucDiskNumber|tmp2) )
					{
						
						if( SendCommand(ucTrack) )
						{
							
							if( SendCommand(ucHead) )
							{
								
								if( SendCommand(ucStartSector) )
								{
									
									if( SendCommand(ucSectorBytesCode) )
									{
										
										if( SendCommand(ucLastSector) )
										{

											if( SendCommand(ucSectorL) )
											{
	
												if( SendCommand(0x0ff) )
												{
													if( IsComplete() )
													{
														if( GetErr(7) )
															return TRUE;

													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
		if( !CanRetry() )
			return FALSE;
	}
	if( uError==OK )
		return TRUE;
	else
		return FALSE;
}

BOOL CFDBios::WriteSectorEx(CHAR ucTrack,CHAR ucHead,CHAR ucStartSector,
	CHAR ucnSectors,CHAR ucSectorBytesCode,CHAR ucLastSector,
	CHAR ucSectorL,int uReadBytes)
{
	for( int i=0;i<MAX_RETRY;i++)
	{
		if(Reset() )
		{
			if( GotoTrack(ucTrack) )
			{
				StartDMA(READ_DISK,ucnSectors,uReadBytes,pBuffer);//MAX_ALL_BYTES,pBuffer);
				EnableINT();
				if( SendCommand(0x0c5) )
				{
					
					CHAR tmp2= ucHead<<2;
					if( SendCommand(ucDiskNumber|tmp2) )
					{
						
						if( SendCommand(ucTrack) )
						{
							
							if( SendCommand(ucHead) )
							{
								
								if( SendCommand(ucStartSector) )
								{
									
									if( SendCommand(ucSectorBytesCode) )
									{
										
										if( SendCommand(ucLastSector) )
										{

											if( SendCommand(ucSectorL) )
											{
	
												if( SendCommand(0x0ff) )
												{
													if( IsComplete() )
													{
														if( GetErr(7) )
															return TRUE;

													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
		if( !CanRetry() )
			return FALSE;
	}
	if( uError==OK )
		return TRUE;
	else
		return FALSE;
}


BOOL CFDBios::WriteSector(CHAR ucTrack,CHAR ucHead,CHAR ucStartSector,
	CHAR ucnSectors,CHAR ucSectorBytesCode,CHAR ucLastSector,
	CHAR ucSectorL)
{
	for( int i=0;i<MAX_RETRY;i++)
	{
		if(Reset() )
		{
			if( GotoTrack(ucTrack) )
			{
				int tmp=GetSectorBytes(ucSectorBytesCode);
				StartDMA(WRITE_DISK,ucnSectors,tmp,pBuffer);//MAX_ALL_BYTES,pBuffer);
				EnableINT();
				if( SendCommand(0x0C5) )
				{
					
					CHAR tmp2= ucHead<<2;
					if( SendCommand(ucDiskNumber|tmp2) )
					{
						
						if( SendCommand(ucTrack) )
						{
							
							if( SendCommand(ucHead) )
							{
								
								if( SendCommand(ucStartSector) )
								{
									
									if( SendCommand(ucSectorBytesCode) )
									{
										
										if( SendCommand(ucLastSector) )
										{

											if( SendCommand(ucSectorL) )
											{
	
												if( SendCommand(0x0ff) )
												{
													if( IsComplete() )
													{
														if( GetErr(7) )
															return TRUE;

													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
		if( !CanRetry() )
			return FALSE;
	}
	if( uError==OK )
		return TRUE;
	else
		return FALSE;
}

BOOL CFDBios::WriteDelSector(CHAR ucTrack,CHAR ucHead,CHAR ucStartSector,
	CHAR ucnSectors,CHAR ucSectorBytesCode,CHAR ucLastSector,
	CHAR ucSectorL)
{
	for( int i=0;i<MAX_RETRY;i++)
	{
		if( Reset() )
		{
			if( GotoTrack(ucTrack) )
			{
				int tmp=GetSectorBytes(ucSectorBytesCode);
				StartDMA(WRITE_DISK,ucnSectors,tmp,pBuffer);//MAX_ALL_BYTES,pBuffer);
				EnableINT();
				if( SendCommand(0x0C9) )
				{
					
					CHAR tmp2= ucHead<<2;
					if( SendCommand(ucDiskNumber|tmp2) )
					{
						
						if( SendCommand(ucTrack) )
						{
							
							if( SendCommand(ucHead) )
							{
								
								if( SendCommand(ucStartSector) )
								{
									
									if( SendCommand(ucSectorBytesCode) )
									{
										
										if( SendCommand(ucLastSector) )
										{

											if( SendCommand(ucSectorL) )
											{
	
												if( SendCommand(0x0ff) )
												{
													if( IsComplete() )
													{
														if( GetErr(7) )
															return TRUE;

													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
		if( !CanRetry() )
			return FALSE;
	}
	if( uError==OK )
		return TRUE;
	else
		return FALSE;
}


BOOL CFDBios::WriteCRCSector(CHAR ucTrack,CHAR ucHead,CHAR ucStartSector,
	CHAR ucnSectors,CHAR ucSectorBytesCode,CHAR ucLastSector,
	CHAR ucSectorL)
{
	for( int i=0;i<MAX_RETRY;i++)
	{
		if( Reset() )
		{
			if( GotoTrack(ucTrack) )
			{
				int BytesOfSector=GetSectorBytes(ucSectorBytesCode);
				StartDMA(WRITE_DISK,ucnSectors,BytesOfSector,pBuffer);
				EnableINT();
				if( SendCommand(0x0C5) )
				{
					
					CHAR tmp2= ucHead<<2;
					if( SendCommand(ucDiskNumber|tmp2) )
					{
						
						if( SendCommand(ucTrack) )
						{
							
							if( SendCommand(ucHead) )
							{
								
								if( SendCommand(ucStartSector) )
								{
									

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -