Executing identify device command in PIO mode for Hard disk.

Programming, for all ages and all languages.
Post Reply
ravi_chobey
Posts: 13
Joined: Mon Apr 14, 2008 2:32 am
Location: Pune,India

Executing identify device command in PIO mode for Hard disk.

Post by ravi_chobey »

Hi All,

This is my first post to this forum.

Currently i am working on ATA protocol[PIO mode] for hard drives.
I am facing a problem while executing Identify device command.I am performing the flow as per flow mentioned in ATA datasheet as follows:
1) reading status register and checking for BSY bit. I am getting it low whenever hard disk is not busy. So that is fine
2)Now selecting device by setting dev bit low. I am setting it low because it's status should match with the cable_Select pin. In my hardware cable select is connected to ground. So i am writing A0h in device/head register.
3)Reading the status register and checking for BSY and DRDY bits. I am getting BSY = 0 and DRDY = 1. So it is ok.
4)Writing command ECh in command register.[Identify Device = ECh].
5) Checking for Error bit in status register and BSY bit also. I am getting BSY low and ERR bit low. That means no error has occured till now.
6) no I am checking for DRQ bit. But i am not getting DRQ = 1 as per the flow mentioned in ATA-3 Datasheet.
Even if I ignore DRQ bit, and start reading data register, i always get FF00, which is not as per outputs mentioned in datasheet for Identify device command. I am getting all 256 words as FF00h only.

So i am facing this problem for last seven days and i am not getting any proper documents on internet to sort out this issue.If any body can support me in sorting out this issue,please support me for this.
Embarassed
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post by bewing »

You don't need step 3. If the drive exists, but is not ready, then sending the identify command will bring it ready (technically, it could take 30 seconds).

In general, it sounds like you are doing everything right. So that means that you must be doing something wrong with your registers.

Did you read my wiki article on PIO mode, and the Identify command?
http://www.osdev.org/wiki/ATA_PIO_Mode

Please read that, and then post more info on exactly which registers you are writing (with your drive select 0xA0 byte and your 0xEC command). And on which status register you are reading. If those look OK, then we will need to look at the exact code you are using for doing your INs and OUTs to the IO ports.
ravi_chobey
Posts: 13
Joined: Mon Apr 14, 2008 2:32 am
Location: Pune,India

Post by ravi_chobey »

Hi Bewing,

Thanks for going thorough my post.

I have gone through your Article on Osdev/Wiki and it is as per the ATA standard.
I am writing 0xA000 in my device/head register and 0xEC00 in Command register.I am writing in this format as my processor is Big endian processor i.e Microblaze.I am reading the Status register(Not Alternate Status register).I am posting my code for you, so that u will get an idea of what i have done.My code is as per C syntax and as i have used Xilinx EDK tool for compiling and i am testing my outputs on Hyperterminal:

The code goes like this:

Code: Select all

 
 /*
 *
 * Your XPS project directory is at:
 *    D:\HARD_DISC\EXE_DIAGNOSTIC_1\
 */


// Located in: microblaze_0/include/xparameters.h
#include "xparameters.h"

#include "stdio.h"

#include "xutil.h"

#include "ata.h"

//====================================================

int main (void) {

    /* Enable and initialize cache
    */
   #if XPAR_MICROBLAZE_0_USE_ICACHE
      microblaze_init_icache_range(0, XPAR_MICROBLAZE_0_CACHE_BYTE_SIZE);
      microblaze_enable_icache();
   #endif

   #if XPAR_MICROBLAZE_0_USE_DCACHE
      microblaze_init_dcache_range(0, XPAR_MICROBLAZE_0_DCACHE_BYTE_SIZE);
      microblaze_enable_dcache();
   #endif

   print("-- Entering main() --\r\n");

   /* 
    * MemoryTest routine will not be run for the memory at 
    * 0x00000000 (dlmb_cntlr)
    * because it is being used to hold a part of this application program
    */


   /* Testing SDRAM Memory (Micron_SDRAM_MT48V2M32LFFC)*/
   {
      XStatus status;

      print("Starting MemoryTest for Micron_SDRAM_MT48V2M32LFFC:\r\n");
      print("  Running 32-bit test...");
      status = XUtil_MemoryTest32((Xuint32*)XPAR_MICRON_SDRAM_MT48V2M32LFFC_BASEADDR, 1024, 0xAAAA5555, XUT_ALLMEMTESTS);
      if (status == XST_SUCCESS) {
         print("PASSED!\r\n");
      }
      else {
         print("FAILED!\r\n");
      }
      print("  Running 16-bit test...");
      status = XUtil_MemoryTest16((Xuint16*)XPAR_MICRON_SDRAM_MT48V2M32LFFC_BASEADDR, 2048, 0xAA55, XUT_ALLMEMTESTS);
      if (status == XST_SUCCESS) {
         print("PASSED!\r\n");
      }
      else {
         print("FAILED!\r\n");
      }
      print("  Running 8-bit test...");
      status = XUtil_MemoryTest8((Xuint8*)XPAR_MICRON_SDRAM_MT48V2M32LFFC_BASEADDR, 4096, 0xA5, XUT_ALLMEMTESTS);
      if (status == XST_SUCCESS) {
         print("PASSED!\r\n");
      }
      else {
         print("FAILED!\r\n");
      }
   }
   /*
    * Disable cache and reinitialize it so that other
    * applications can be run with no problems
    */
   #if XPAR_MICROBLAZE_0_USE_DCACHE
      microblaze_disable_dcache();
      microblaze_init_dcache_range(0, XPAR_MICROBLAZE_0_DCACHE_BYTE_SIZE);
   #endif

   #if XPAR_MICROBLAZE_0_USE_ICACHE
      microblaze_disable_icache();
      microblaze_init_icache_range(0, XPAR_MICROBLAZE_0_CACHE_BYTE_SIZE);
   #endif
	
	int i,j,k;
 
 
/*------------------------------------MY CODE WILL START HERE--------------------------------------*/
check_busy_bit();
*memory_location_DHR = 0xA000; // for DVD
xil_printf("Address of Device Head Register: %x ,Value at this register: %x\r\n",memory_location_DHR,*memory_location_DHR);
*memory_location_FPGA = 0x7400;
xil_printf("Address of Control Register: %x ,Value at this register: %x\r\n",memory_location_FPGA,*memory_location_FPGA);
check_for_done_pin();
*memory_location_FPGA = 0x0C00;
xil_printf("Address of Control Register: %x ,Value at this register: %x\r\n",memory_location_FPGA,*memory_location_FPGA);
print("i m in in Drive head register");

/*------------------------------------------------------------------------------------------------------------------------*/

for(i = 0;i < 1000 ; i++)
{
	}

/*------------------------------------------------------------------------------------------------------------------------*/

*memory_location_CR = 0xEC00; // for DVD
xil_printf("Add %x command reg data %x\r\n",memory_location_CR,*memory_location_CR);
*memory_location_FPGA = 0xF400;
xil_printf("Address of control Register: %x ,Value at this register: %x\r\n",memory_location_FPGA,*memory_location_FPGA);
check_for_done_pin();
*memory_location_FPGA  = 0x0C00;
xil_printf("Address of control Register: %x ,Value at this register: %x\r\n",memory_location_FPGA,*memory_location_FPGA);
/*-------------------------------------------------------------------------------------------------------------------------*/
check_busy_bit();

check_busy_drq_bit();

/*-------------------------------------------------------------------------------------------------------------------------*/

//print("Read data register");

/*for(i=0;i<5;i++)
{
	rd_data_reg();
}*/


/*------------------------------------MY CODE WILL END HERE----------------------------------------*/
  
//***********************
   print("-- Exiting main() --\r\n");
   return 0;
}
void check_for_done_pin()
{	
	char done=0,INTRQ=0;
   volatile short *memory_location_DPSR  = 0x7a800024;
//  check slv_reg18 (0x77200024)
//  pin no 3 if it is one come out from this loop else wait till it becomes zero.

  unsigned short  memory_status_register;
  int remainder;
    
  memory_status_register = *memory_location_DPSR;
//  xil_printf("Address %x  Status Register %x\r\n",memory_location_DPSR,memory_status_register);
  memory_status_register  = memory_status_register >> 8;
  
  
   if(memory_status_register <= 1)
   {
     return memory_status_register;
   }
  remainder = memory_status_register % 2;
  if(remainder == 1);   
//   xil_printf("a");
     
   memory_status_register = memory_status_register  >> 1 ; 
    remainder = memory_status_register %2;
    if(remainder == 1);
//  xil_printf("b");
    
     
    memory_status_register = memory_status_register  >> 1 ; 
    remainder = memory_status_register %2;
    if(remainder == 1);
//  xil_printf("c");
    
     
    memory_status_register = memory_status_register  >> 1 ; 
    remainder = memory_status_register %2;
    if(remainder == 1); 
//  xil_printf("d");
    
    memory_status_register = memory_status_register  >> 1 ; 
    remainder = memory_status_register %2;
    if(remainder == 1) 
    {
//  xil_printf("DONE IS high\r\n");
    done=1;
    }
    else
    {
//  xil_printf("DONE IS low\r\n");
    done =0;
    }
    memory_status_register = memory_status_register  >> 1 ; 
    remainder = memory_status_register %2;
    if(remainder == 1) 
    INTRQ = 1;
    else
    INTRQ = 0;
//  xil_printf("INTRQ");
    
    memory_status_register = memory_status_register  >> 1 ; 
    remainder = memory_status_register %2;
    if(remainder == 1) ;
//  xil_printf("IORDY\r\n");
    
    memory_status_register = memory_status_register  >> 1 ; 
    remainder = memory_status_register %2;
    if(remainder == 1); 
//  xil_printf("dmreq\r\n");
//   xil_printf("\r\n");
 
   return;
}
void check_busy_bit()
{  int i;
   volatile short m = 0x0000;
	*memory_location_FPGA = 0xF600;
	xil_printf("Address of Control Register: %x ,Value at this register: %x\r\n",memory_location_FPGA,*memory_location_FPGA);
	check_for_done_pin();
	*memory_location_FPGA = 0x0C00;
	xil_printf("Address of Control Register: %x ,Value at this register: %x\r\n",memory_location_FPGA,*memory_location_FPGA);
	
	xil_printf("Address %x  Status Register Data %x\r\n",memory_location_SR,*memory_location_SR);
	m = *memory_location_SR & 0x0080;
	if(m == 0x0080)
		check_busy_bit(); //changed by ravi
	else
		return;
}
void check_busy_drdy_bit()
{
   volatile short n = 0x0000;
	*memory_location_FPGA = 0xF600;
	//xil_printf("Add %x control reg data %x\r\n",memory_location_FPGA,*memory_location_FPGA);
	check_for_done_pin();
	*memory_location_FPGA = 0x0C00;
	//xil_printf("Add of control Register: %x ,Value at this register: %x\r\n",memory_location_FPGA,*memory_location_FPGA);
	xil_printf("Add %x  Status Reg Data %x\r\n",memory_location_SR,*memory_location_SR);
	n = *memory_location_SR & 0x00C0;
   xil_printf("Address %x\r\n",n);
	while(n != 0x0040)
	{
			check_busy_drdy_bit();
			}
	return;
}
void check_busy_drq_bit()
{
   volatile short n = 0x0000;
	*memory_location_FPGA = 0xF600;
	xil_printf("Add %x control reg data %x\r\n",memory_location_FPGA,*memory_location_FPGA);
	check_for_done_pin();
	*memory_location_FPGA = 0x0C00;
	xil_printf("Add of control Register: %x ,Value at this register: %x\r\n",memory_location_FPGA,*memory_location_FPGA);
	xil_printf("Add %x  Status Reg Data %x\r\n",memory_location_SR,*memory_location_SR);
	n = *memory_location_SR & 0x0088;
	//xil_printf("Address %x\r\n",n);
	while (n != 0x0008)
	{
			check_busy_drq_bit();
			}
		 return;
}

void rd_data_reg()
{
	*memory_location_FPGA = 0x1600;
	//xil_printf("Add %x control reg data %x\r\n",memory_location_FPGA,*memory_location_FPGA);
	check_for_done_pin();	
	*memory_location_FPGA = 0x0C00;	
	xil_printf("Add of data Register: %x ,Value at this register: %lx\r\n",memory_location_DR,*memory_location_DR);
	check_busy_bit();
	return;
}

Code: Select all

...
tags exist for a reason - Combuster[/i]
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post by bewing »

Your hardware is very non-standard, and that makes this much harder, of course. To the best that I can tell, the problem comes down to your declaration of your memory_location_ variables. It looks like you must have them all declared as shorts in one of your .h files. You must access ATA bus IO ports as bytes -- they cannot be two byte accesses. You need to change the declarations of all those variables. This will make your compiler stop accessing two bytes every time it reads/writes the ports.

In detail, I think the problem comes when you try to write the drive select and command "bytes" to your memory mapped IO ports. There is an extra zero byte being sent to some IO port, along with the byte that you are actually trying to send. The zero is ending up being written on top of an IO port that needs a proper value.
ravi_chobey
Posts: 13
Joined: Mon Apr 14, 2008 2:32 am
Location: Pune,India

Post by ravi_chobey »

Hi bewing,

I have done the changes as told by you.But i am getting zero output.What i did, in my header file i changed that data type Volatile short to volatile char or unsigned char.But when i change it to volatile short,i am getting FFFFFF50 value in status register.And according to bit patten of status register,i am getting DRDY and DSC bit high.Because i am considering only the last two nibbles for my case.As i am using 16 bit registers,that why i am using volatile short as my data type.Hope it is clear to you.

I have referred one document from sourceforge:

http://minirighi.sourceforge.net/html/IdeAta_8c.html

they have the same thing, as told by you.

I am having a different code,which i m using for DVD drive.when i am testing that code for DVD drive,the last two nibbles i am getting them as 58h,that means i am getting DRDY,DSC and DRQ bits high.But when i m testing the same code for Hard disk drives,by changing the contents of Device head and Command register,i am still getting 50h for hard disks.
As far as i know hard disk is an ATA device and DVD is an ATAPI device.

What can be difference between the two drives.

For your reference i have posted the code of DVD drive:

#include "xparameters.h"
#include "stdio.h"

#include "xutil.h"
#include "atapi.h"

//========================================================
int check_val=0;
short data_write[5];
short *memory_read_data;
//====================================================
//====================================================

int main (void) {

int i=0,j=0,k=0;

/*
* Enable and initialize cache
*/
#if XPAR_MICROBLAZE_0_USE_ICACHE
microblaze_init_icache_range(0, XPAR_MICROBLAZE_0_CACHE_BYTE_SIZE);
microblaze_enable_icache();
#endif

#if XPAR_MICROBLAZE_0_USE_DCACHE
microblaze_init_dcache_range(0, XPAR_MICROBLAZE_0_DCACHE_BYTE_SIZE);
microblaze_enable_dcache();
#endif

print("-- Entering main() --\r\n");

/*
* MemoryTest routine will not be run for the memory at
* 0x00000000 (dlmb_cntlr)
* because it is being used to hold a part of this application program
*/


/* Testing SDRAM Memory (Micron_SDRAM_MT48V2M32LFFC)*/
{
XStatus status;

// print("Starting MemoryTest for Micron_SDRAM_MT48V2M32LFFC:\r\n");
// print(" Running 32-bit test...");
status = XUtil_MemoryTest32((Xuint32*)XPAR_MICRON_SDRAM_MT48V2M32LFFC_BASEADDR, 1024, 0xAAAA5555, XUT_ALLMEMTESTS);
if (status == XST_SUCCESS) {
print("PASSED!\r\n");
}
else {
print("FAILED!\r\n");
}
// print(" Running 16-bit test...");
status = XUtil_MemoryTest16((Xuint16*)XPAR_MICRON_SDRAM_MT48V2M32LFFC_BASEADDR, 2048, 0xAA55, XUT_ALLMEMTESTS);
if (status == XST_SUCCESS) {
print("PASSED!\r\n");
}
else {
print("FAILED!\r\n");
}
// print(" Running 8-bit test...");
status = XUtil_MemoryTest8((Xuint8*)XPAR_MICRON_SDRAM_MT48V2M32LFFC_BASEADDR, 4096, 0xA5, XUT_ALLMEMTESTS);
if (status == XST_SUCCESS) {
print("PASSED!\r\n");
}
else {
print("FAILED!\r\n");
}
}
/*
* Disable cache and reinitialize it so that other
* applications can be run with no problems
*/
#if XPAR_MICROBLAZE_0_USE_DCACHE
microblaze_disable_dcache();
microblaze_init_dcache_range(0, XPAR_MICROBLAZE_0_DCACHE_BYTE_SIZE);
#endif

#if XPAR_MICROBLAZE_0_USE_ICACHE
microblaze_disable_icache();
microblaze_init_icache_range(0, XPAR_MICROBLAZE_0_CACHE_BYTE_SIZE);
#endif

/***********/
Master_IDENTIFY_DEVICE(0xEC00,1);
print("-- Exiting main() --\r\n");
return;
}

void Master_IDENTIFY_DEVICE(unsigned int cmd,short pr)
{
unsigned int identify[256];
int i,d,j;

xil_printf("\r\n==========================================\r\n");
Device_selection_protocol();

/* xil_printf("Writing required command \r\n");

// Command_Register(write,0xA000,0xF400);
Command_Register(write,cmd,0xF400);

for(i=0;i<5;i++)
{
if (BUSY == 0 && DRQ == 1 || DRDY==1)
{
i =10;
xil_printf("BUSY =0 DRQ =1 OR DRDY =1\r\n");
}
else
{
Master_Status_Register();
i=2;
}
}

for(j=0;j<=256;j++)
{
*memory_location_FPGA = 0x1600;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done == 1)
{
*memory_location_FPGA = 0x0C00;
done =0;
i=10;
}
else
{
check_for_done_pin();
i=2;
}
}
// xil_printf("j =%d \r\n",j);
identify[j] = *memory_location_DR;
}

for(j=1;j<=9;j++)
readall_memory(j);

xil_printf("\r\n");

if(pr == 1)
{
for(j=0;j<=256;j++)
{
xil_printf("data[%d] %c = %x \r\n",j,identify[j],identify[j]);
}
}
*/
return ;
}
void Device_selection_protocol()
{ int i=0;
// xil_printf("\r\n Device Selection protocol Function\r\n");
Master_Status_Register();
Master_Busy_Drq();

*memory_location_DHR = 0xA000;//0x0000 ;
*memory_location_FPGA =0x7400; //0x7800 ;
check_for_done_pin();
for(i=0;i<5;i++)
{
if(done==1)
{
*memory_location_FPGA = 0x0C00; //0x6C00 ;
done =0;
i=10;
}
else
{
check_for_done_pin();
i=2;
}
}
//DELAY(1);
Master_Status_Register();
Master_Busy_Drq();

return;
}

void Master_Status_Register()
{
int i=0;

unsigned short memory_status_register;
short error_code;
int remainder;

*memory_location_FPGA = 0xF600;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done==1)
{
*memory_location_FPGA = 0x0C00;
done =0;
i=10;
}
else
{
i =2;
check_for_done_pin();
}
}
// reading from the memory address and comparing to expacted
memory_status_register = *memory_location_SR;
error_code = memory_status_register ;

xil_printf("Address %x Status Register %x \r\n",memory_location_SR,*memory_location_SR);

// memory_status_register = memory_status_register << 8;

// xil_printf("Address %x Status Register %x\r\n",memory_location_SR,memory_status_register);
if(memory_status_register <= 1)
{
//xil_printf("Asif");
return memory_status_register;
}
remainder = memory_status_register % 2;
if(remainder == 1) {
xil_printf("%s\r\n",Master_Status_Register_Read[0]);
Err = 1;
}
else {
Err = 0;
}
// xil_printf("Error = %x \r\n",Err);

memory_status_register = memory_status_register >> 1 ;
remainder = memory_status_register %2;
if(remainder == 1)
xil_printf("%s\r\n",Master_Status_Register_Read[1]);

memory_status_register = memory_status_register >> 1 ;
remainder = memory_status_register %2;
if(remainder == 1)
xil_printf("%s\r\n",Master_Status_Register_Read[2]);

memory_status_register = memory_status_register >> 1 ;
remainder = memory_status_register %2;
if(remainder == 1) {
xil_printf("%s\r\n",Master_Status_Register_Read[3]);
DRQ =1;
}
else {
DRQ =0;
}
// xil_printf("DRQ = %x \r\n",DRQ);

memory_status_register = memory_status_register >> 1 ;
remainder = memory_status_register %2;
if(remainder == 1)
{
xil_printf("%s\r\n",Master_Status_Register_Read[4]);
SERV =1;
}
else
{
SERV =0;
}

memory_status_register = memory_status_register >> 1 ;
remainder = memory_status_register %2;
if(remainder == 1)
xil_printf("%s\r\n",Master_Status_Register_Read[5]);

memory_status_register = memory_status_register >> 1 ;
remainder = memory_status_register %2;
if(remainder == 1)
{
xil_printf("%s\r\n",Master_Status_Register_Read[6]);
DRDY =1;
}
else
{
DRDY =0;
}


memory_status_register = memory_status_register >> 1 ;
remainder = memory_status_register %2;
if(remainder == 1) {
xil_printf("%s\r\n",Master_Status_Register_Read[7]);
BUSY = 1;
}
else {
BUSY = 0;
}

// xil_printf("BUSY = %x \r\n",BUSY);
return ;//error_code;
}

void Master_Busy_Drq()
{
int i;
for(i=0;i<5;i++) {
if(BUSY == 1 || DRQ == 1)
{
Master_Status_Register();
i=2;
}
else
i=10;
}
}

void check_for_done_pin()
{

// check slv_reg18 (0x77200024)
// pin no 3 if it is one come out from this loop else wait till it becomes zero.

unsigned short memory_status_register;
int remainder;

memory_status_register = *memory_location_DPSR;
// xil_printf("Address %x Status Register %x\r\n",memory_location_DPSR,memory_status_register);
memory_status_register = memory_status_register >> 8;


if(memory_status_register <= 1)
{
return memory_status_register;
}
remainder = memory_status_register % 2;
if(remainder == 1);
// xil_printf("a");

memory_status_register = memory_status_register >> 1 ;
remainder = memory_status_register %2;
if(remainder == 1);
// xil_printf("b");


memory_status_register = memory_status_register >> 1 ;
remainder = memory_status_register %2;
if(remainder == 1);
// xil_printf("c");


memory_status_register = memory_status_register >> 1 ;
remainder = memory_status_register %2;
if(remainder == 1);
// xil_printf("d");

memory_status_register = memory_status_register >> 1 ;
remainder = memory_status_register %2;
if(remainder == 1)
{
// xil_printf("DONE IS high\r\n");
done=1;
}
else
{
// xil_printf("DONE IS low\r\n");
done =0;
}
memory_status_register = memory_status_register >> 1 ;
remainder = memory_status_register %2;
if(remainder == 1)
INTRQ = 1;
else
INTRQ = 0;
// xil_printf("INTRQ");

memory_status_register = memory_status_register >> 1 ;
remainder = memory_status_register %2;
if(remainder == 1) ;
// xil_printf("IORDY\r\n");

memory_status_register = memory_status_register >> 1 ;
remainder = memory_status_register %2;
if(remainder == 1);
// xil_printf("dmreq\r\n");
// xil_printf("\r\n");

return;
}

void DELAY(unsigned int a)
{
int i=0,j=0;
for(i=0;i<=a;i++)
for(j=0;j<=255;j++)
;
// xil_printf("%x\t",j);
return ;
}

void Writing_required_command(short as, unsigned int value)
{
short i = 0;
// xil_printf(" Write Required Command == %x \r\n ",as);
// xil_printf(" Write Required Value == %x \r\n ",value);

switch(as)
{
case Feature:
*memory_location_FR = value;//0x0000;
*memory_location_FPGA = 0x9400;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done==1)
{
*memory_location_FPGA = 0x8C00;
done =0;
i=10;
}
else
{
check_for_done_pin();
i=2;
}
}
break;

case Sector_count:
*memory_location_SCR = value;
*memory_location_FPGA = 0x5400;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done==1)
{
*memory_location_FPGA = 0x4C00;
done =0;
i = 10;
}
else
{
check_for_done_pin();
i=2;
}
}
break;

case Sector_Number:
*memory_location_SNR = value;//0x0000 ;
*memory_location_FPGA = 0xD400 ;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done==1)
{
*memory_location_FPGA = 0xCC00;
done =0;
i = 10;
}
else
{
check_for_done_pin();
i=2;
}
}
break;

case Cylinder_Low:
*memory_location_CLB = value;
*memory_location_FPGA = 0x3400 ;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done==1)
{
*memory_location_FPGA = 0x2400;
done =0;
i = 10;
}
else
{
check_for_done_pin();
i=2;
}
}
break;


case Cylinder_High:
*memory_location_CHB = value;//0x0000;
*memory_location_FPGA = 0xB400 ;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done==1)
{
*memory_location_FPGA = 0xA400;
done =0;
i = 10;
}
else
{
check_for_done_pin();
i=2;
}
}
break;

case Device_Head:
// Drive Head Register write

*memory_location_DHR = value;
*memory_location_FPGA = 0x7400;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done==1)
{
*memory_location_FPGA = 0x6C00;
done =0;
i=10;
}
else
{
check_for_done_pin();
}
}
break;
default:
break;
}
//DELAY(1);
return ;
}

/*

*/
void Master_Error()
{
unsigned short memory_data_read;
short error_test;
int remainder;
xil_printf("Master Error Function\r\n");

*memory_location_FPGA = 0x9600;
check_for_done_pin();
if(done==1)
{
*memory_location_FPGA = 0x0C00;
done =0;
}
else
{
check_for_done_pin();
}

// reading from the memory address and comparing to expacted
memory_data_read = *memory_location_ER;
// memory_data_read = memory_data_read << 8;

xil_printf("Address %x Error Register Data %x\r\n",memory_location_ER,memory_data_read);
/*
if(memory_data_read <= 1)
{
// xil_printf("ASIF %x\r\n",memory_data_read);
return memory_data_read;
}
remainder = memory_data_read % 2;
if(remainder == 1)
{
xil_printf("%s\r\n",Master_error_read_BIT_0[1]);
}
else
{
xil_printf("%s\r\n",Master_error_read_BIT_0[0]);
}
memory_data_read = memory_data_read >> 1 ;
remainder = memory_data_read %2;
if(remainder == 1)
{
xil_printf("%s\r\n",Master_error_read_BIT_1[1]);
}
else
{
xil_printf("%s\r\n",Master_error_read_BIT_1[0]);
}
memory_data_read = memory_data_read >> 1 ;
remainder = memory_data_read %2;
if(remainder == 1)
{
xil_printf("%s\r\n",Master_error_read_BIT_2[1]);
}
else
{
xil_printf("%s\r\n",Master_error_read_BIT_2[0]);
}
memory_data_read = memory_data_read >> 1 ;
remainder = memory_data_read %2;
if(remainder == 1)
{
xil_printf("%s\r\n",Master_error_read_BIT_3[1]);
}
else
{
xil_printf("%s\r\n",Master_error_read_BIT_3[0]);
}
memory_data_read = memory_data_read >> 1 ;
remainder = memory_data_read %2;
if(remainder == 1)
{
xil_printf("%s\r\n",Master_error_read_BIT_4[1]);
}
else
{
xil_printf("%s\r\n",Master_error_read_BIT_4[0]);
}
memory_data_read = memory_data_read >> 1 ;
remainder = memory_data_read %2;
if(remainder == 1)
{
xil_printf("%s\r\n",Master_error_read_BIT_5[1]);
}
else
{
xil_printf("%s\r\n",Master_error_read_BIT_5[0]);
}

memory_data_read = memory_data_read >> 1 ;
remainder = memory_data_read %2;
if(remainder == 1)
{
xil_printf("%s\r\n",Master_error_read_BIT_6[1]);
}
else
{
xil_printf("%s\r\n",Master_error_read_BIT_6[0]);
}
memory_data_read = memory_data_read >> 1 ;
remainder = memory_data_read %2;
if(remainder == 1)
{
xil_printf("%s\r\n",Master_error_read_BIT_7[1]);
}
else
{
xil_printf("%s\r\n",Master_error_read_BIT_7[0]);
}*/

}

/*
*/
void readall_memory(short any)
{
//volatile int *memory_location = 0x73e00000;
volatile short *memory_location = 0x77200000;// 0x73e00000;
//int mem_size = 0x26;
short i=0;
short any1 = 0;
//xil_printf("Read all Register\r\n");


switch(any)
{
case 1:
// DATA Register
*memory_location_FPGA = 0x1600;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done==1)
{
*memory_location_FPGA = 0x0C00;
done =0;
i=10;
}
else
{
check_for_done_pin();
}
}
xil_printf("Data Register Address = %x data == %x \r\n",memory_location_DR,*memory_location_DR);
break;

case 2:
// Read Cylinder High Register
*memory_location_FPGA = 0xB600;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done==1)
{
*memory_location_FPGA = 0xA600;
done =0;
i=10;
}
else
{
check_for_done_pin();
}
}
xil_printf("Cylinder High Register Address = %x data == %x \r\n",memory_location_CHB_r,*memory_location_CHB_r);
break;

case 3:
// Read Cylinder Low Register
*memory_location_FPGA = 0x3600;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done==1)
{
*memory_location_FPGA = 0x2600;
done =0;
i=10;
}
else
{
check_for_done_pin();
}
}
xil_printf("Cylinder Low Register Address = %x data == %x \r\n",memory_location_CLB_r,*memory_location_CLB_r);
break;

case 4:
// Device HEAD Register
*memory_location_FPGA = 0x7600;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done==1)
{
*memory_location_FPGA = 0x6C00;
done =0;
i=10;
}
else
{
check_for_done_pin();
}
}
xil_printf("Device HEAD REGISTER Address = %x data == %x \r\n",memory_location_DHR_r,*memory_location_DHR_r);
break;

case 5:
// Error Register
*memory_location_FPGA = 0x9600;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done==1)
{
*memory_location_FPGA = 0x8C00;
done =0;
i=10;
}
else
{
check_for_done_pin();
}
}
xil_printf("Error REGISTER Address = %x data == %x \r\n",memory_location_ER,*memory_location_ER);
break;

case 6:

// Sector count Register
*memory_location_FPGA = 0x5600;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done==1)
{
*memory_location_FPGA = 0x4C00;
done =0;
i=10;
}
else
{
check_for_done_pin();
}
}
xil_printf("Sector count REGISTER Address = %x data == %x \r\n",memory_location_SCR_r,*memory_location_SCR_r);
break;

case 7:
// Sector Number Register
*memory_location_FPGA = 0xD600;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done==1)
{
*memory_location_FPGA = 0xCC00;
done =0;
i=10;
}
else
{
check_for_done_pin();
}
}
xil_printf("Sector Number REGISTER Address = %x data == %x \r\n",memory_location_SNR_r,*memory_location_SNR_r);
break;

case 8:
// Status Register
*memory_location_FPGA = 0xF600;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done==1)
{
*memory_location_FPGA = 0xEC00;
done =0;
i=10;
}
else
{
check_for_done_pin();
}
}
xil_printf("Status REGISTER Address = %x data == %x \r\n",memory_location_SR,*memory_location_SR);
break;

case 9:

// read Alternate Status Register
*memory_location_FPGA = 0x7A00;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done==1)
{
*memory_location_FPGA = 0x6A00;
done =0;
i=10;
}
else
{
check_for_done_pin();
}
}
xil_printf("Read Alternate Status Register Address = %x Memory Read data == %x \r\n",memory_location_ASR,*memory_location_ASR);
break;
}
return;
}


/*
*/

/*
This function is working fine
*/

void Master_Alt_Status_Register()
{ int i=0;
*memory_location_FPGA = 0x7A00;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done==1)
{
*memory_location_FPGA = 0x6C00;
done =0;
i=10;
}
else
{
check_for_done_pin();
}
}
xil_printf("Read Alternate Status Register Address = %x Memory Read data == %x \r\n",memory_location_ASR,*memory_location_ASR);

return;
}

/*
read =1
write =0
*/

void Command_Register(short rw,int cmd,int Add_cs)
{
short m=0;

xil_printf("RW =%x,CMD =%x,add_cs= %x\r\n ",rw,cmd,Add_cs);

if(rw == read)
{
*memory_location_FPGA = Add_cs;
}

if(rw == write)
{
*memory_location_CR = cmd;
*memory_location_FPGA = Add_cs;
}
check_for_done_pin();
for(m=0;m<=5;m++)
{
if(done == 1)
{
*memory_location_FPGA = 0x0C00;
done =0;
m=10;
}
else
{
// xil_printf("a1");
check_for_done_pin();
m=2;
}
}
return ;
}

/*
drw = 1 read
drw = 0 write
*/


void Data_Register_read_Write(short drw,short data)
{
short i=0;

if(drw == write)
{
*memory_location_DW = data;//0x0000;
*memory_location_FPGA = 0x1400;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done == 1)
{
*memory_location_FPGA = 0x0C00;
done =0;
i=10;
}
else
{
check_for_done_pin();
i=2;
}
}
xil_printf("Data = %x \r\n",*memory_location_DW);
}

if(drw == read)
{
*memory_location_FPGA = 0x1600;
check_for_done_pin();
for(i=0;i<=5;i++)
{
if(done == 1)
{
*memory_location_FPGA = 0x0C00;
done =0;
i=10;
}
else
{
check_for_done_pin();
i=2;
}
}
xil_printf("Data %x \r\n",*memory_location_DR);
}
return ;
}
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

will you PLEASE use code tags
or preferrably, upload the source as an attachment
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post by bewing »

0x50 is exactly the value that you should be getting in the status register for the hard disk. (If the upper byte is 0xFF then there is still something wrong with your code.) Setting the value as volatile is correct.

Status starts out at 0x40 or 0x50. After you send the command byte, the status should change for an instant to 0xc0. Then it should change to 0x48 or 0x58. You should only be paying attention to the 0x80 and 0x8 bits. Once the 0x8 bit turns on, then read the 512bytes of data from the data port. With your memory mapped setup, you will need to read them as bytes.

I understand that you are currently using 16 bit registers. But the important question is "how is your memory mapped IO port system set up?" Since you are using completely non-standard hardware, this is the vital question. If IO port 0x1f7 is mapped in the very next byte as IO port 0x1f6, and you try to write a short to port 0x1f6, using your big-endian shorts, then you will be writing to BOTH ports AT THE SAME TIME. And the value that you write to Port 0x1f7 can mess up everything. But maybe your IO ports are mapped to every other memory address. I have no idea, with your non-standard hardware.

So, what are the actual values of memory_location_DR, memory_location_CR, memory_location_SR, and memory_location_DHR?

As far as the DVD drive goes, yes it is an ATAPI device. If you try to use the identify command on it, you should get an error. That is, in the status register, bit 0 (value = 1) should turn on. With your current code, that is the only thing you should see.
ravi_chobey
Posts: 13
Joined: Mon Apr 14, 2008 2:32 am
Location: Pune,India

Post by ravi_chobey »

hi Bewing,

I am following the same flowchart mentioned in ATA-3 datasheet for Pio data in protocol.
I want to chat with you on this topic.If possible pls send me your Skype ID,msn ID etc.So that i move ahead.


Regards,
Ravi
ravi_chobey
Posts: 13
Joined: Mon Apr 14, 2008 2:32 am
Location: Pune,India

Post by ravi_chobey »

Hi Bewing,

Thanks for ur suggestions.I have tried with writing 0xE000 in device head register for LBA mode.And also i have have tried for reading 512 bytes in case of hard disks.But i not getting any proper results.
I have discussed it with some people and they told me that there is some problem with my check_done_pin() code,that i am looking and I am
trying the next command READ sector.please share ur anymore experience on ATA protocol with me.

Regards,
Ravi
ravi_chobey
Posts: 13
Joined: Mon Apr 14, 2008 2:32 am
Location: Pune,India

Post by ravi_chobey »

Can u come tomorrow at 9:30 pm in morning in India.So that i can further discuss on this topic.

Regards,
Ravi
Post Reply