/*
this is the code to input data from HD
It works only with the comand Identify
When a try to read a sector it fails...
Sameone cand get a help ??
Note : This DOS version, but is easy to port to any other
*/
#include <dos.h>
#include <stdio.h>
#define BSY( status ) ( ( status & 0x80 ) != 0 )
#define DRDY( status ) ( ( status & 0x40 ) != 0 )
#define DRQ( status ) ( ( status & 0x08 ) != 0 )
#define ERROR( status ) ( ( status & 0x01 ) != 0 )
#define ASTATUS 0x3F6 // Device Control
#define CONTROL 0x3F6 // Device Control
#define DRIVE_ADDRESS 0x3F7 // Not Used
#define DATA 0x1F0 //Data Port
#define ERROREG 0x1F1 // Error Register Precomp
#define SECTOR_COUNT 0x1F2
#define SECTOR_NUMBER 0x1F3
#define CYLINDER_LOW 0x1F4
#define CYLINDER_HIGH 0x1F5
#define DEVICE_HEAD 0x1F6
#define COMMAND 0x1F7
#define PRISTATUS 0x1F7
#define RESET_PIC { outportb(0xA0,0x20); outportb(0x20,0x20);}
#define inportw( p ) inport( p )
// from Hale Davis
#define DELAY400NS {inportb(ASTATUS);inportb(ASTATUS);inportb(ASTATUS);inportb(ASTATUS);}
typedef unsigned int word ;
typedef unsigned long int dword ;
typedef unsigned char byte ;
static byte ErrorCode = 0 ;
typedef struct SAtaCmd
{
word SectorCount,
SectorNumber,
CylinderLow,
CylinderHigh,
DeviceHead,
Command,
*Buffer;
word DataSize;
byte Result;
} TAtaCmd;
void CmdIn(TAtaCmd *Cmd )
{
byte Status , PriStatus ;
int i;
do Status = inportb( ASTATUS);
while ( BSY( Status ) );
// set device
outportb( DEVICE_HEAD , 0 ) ; // device 0 in lba mode
do Status = inportb( ASTATUS );
while ( BSY( Status ) & !DRDY( Status ) );
outportb( SECTOR_COUNT , Cmd->SectorCount );
outportb( SECTOR_NUMBER , Cmd->SectorNumber );
outportb( CYLINDER_HIGH , Cmd->CylinderHigh );
outportb( CYLINDER_LOW , Cmd->CylinderLow );
outportb( DEVICE_HEAD , Cmd->DeviceHead ) ;
outportb( COMMAND, Cmd->Command );
RESET_PIC ;
do Status =inportb( ASTATUS ) ;
while ( BSY( Status ) & !DRDY( Status ) );
// check error
if ( ERROR( Status ) )
{
ErrorCode = 3 ; // COMMAND_EXECUTION_ERROR
return ;
}
// wait Command completion poolling status reg...
DELAY400NS;
do Status =inportb( ASTATUS );
while ( BSY( Status ) );
// clear intrq reading the PrimaryStatusReg
Status = inportb( PRISTATUS );
RESET_PIC ;
DELAY400NS;
for ( i = 0 ; i < Cmd->DataSize ; i++) Cmd->Buffer[ i ] = inportw( DATA ) ; // INPUT IN WORDS !!!
Status =inportb( ASTATUS ) ;
if ( ERROR( Status ) )
{
ErrorCode = 4 ; // DATA_IN_ERROR
return ;
}
}
void main(void)
{
TAtaCmd Cmd ;
byte SectorBuffer[512];
int i;
dword LbaSector = 1 ;
byte Device = 0 ;
Cmd.SectorCount = 1 ;
Cmd.SectorNumber = (byte)LbaSector ;
Cmd.CylinderLow = (byte)(LbaSector>>8) ;
Cmd.CylinderHigh = (byte)(LbaSector>>16 ) ;
Cmd.DeviceHead = (Device | 0xE0) | (byte)( LbaSector >> 24) ;
Cmd.Command = 0x20 ; // read sector
Cmd.Buffer = SectorBuffer ;
Cmd.DataSize = 512 ;
Cmd.Result = 0 ;
CmdIn(&Cmd ) ;
for ( i = 0 ; i <= 512 ; i++) printf("%c",SectorBuffer[i]);
// ...always buffer is full of 0x0....
}