#define recalibrate		 ata_send_cmd(CMD_RECALIBRATE)
#define CMD_RECALIBRATE          0x10
#define PORT_ATA_IO_CNTL	 PORTF
#define ATA_DIOR		 0x20
#define PORT_ATA_DATA_L_IN  	 PINA
#define ATA_STAT_BSY  		 0x80  		//ATA busy
#define ATA_STAT_RDY  		 0x40  		//ATA ready
#define ATA_STAT_ERR  		 0x01  		//ATA error 
#define busy			 ata_bsy()
#define drq			 ata_drq()
#define error			 ata_err()
#define ready			 ata_rdy()	
#define hard_reset		 ata_hard_reset()	
#define select_device_0		 ata_select_device(0x00)
#define select_device_1		 ata_select_device(0x01)	
#define recalibrate		 ata_send_cmd(CMD_RECALIBRATE)
#define identify_device		 ata_send_cmd(CMD_IDENTIFY_DEVICE)	
******************************************************************
Initialize drive
This routine assumes Drive 0 is the only drive that is attached.
******************************************************************
void init_ata(void)
{
 while(!ready & busy);
 hard_reset;
 delay_ms(10);
 while(!ready & busy);
 select_device_0;
 while(!ready & busy);
 recalibrate;
 while(busy);
 if(error)
   printf("ERROR!");
 printf("\r\nDrive is READY!\r\n");

//Functions are squashed for space     savings
unsigned int ata_bsy(void)
unsigned int ata_rdy(void)
unsigned int ata_err(void)
{
   unsigned char ata_byte_read;
   avr_databus_in;
   delay_us(1);
   PORT_ATA_IO_CNTL = ATA_IO_STATUS;
   PORT_ATA_IO_CNTL &= ~ATA_DIOR;
   delay_us(1);
   ata_byte_read = PORT_ATA_DATA_L_IN;
   PORT_ATA_IO_CNTL |= ATA_DIOR;
   PORT_ATA_IO_CNTL = ATA_IO_HIZ;
   if(ata_byte_read & ATA_STAT_BSY)
   if(ata_byte_read & ATA_STAT_RDY)
   if(ata_byte_read & ATA_STAT_ERR)
   	return 1;
   else
    return 0;				
}
//End of squashed functions
void ata_hard_reset(void)
{
   avr_databus_in;
   PORT_ATA_IO_CNTL = ATA_IO_HIZ;
   PORT_ATA_IO_CNTL &= ~ATA_RESET;
   delay_ms(10);
   PORT_ATA_IO_CNTL |= ATA_RESET;
}   

void ata_select_device(unsigned char device)
{
  PORT_ATA_IO_CNTL = ATA_IO_DEVICE_HEAD;
  switch (device)
  {
   		 case 0x00:
		 	  ata_write_byte(ATA_DH_DEV0);
			  break;
  		 case 0x01:
		 	  ata_write_byte(ATA_DH_DEV1);
			  break;
		 default:
		 	  ata_write_byte(ATA_DH_DEV0);
		 	  break;
  }
}

void ata_send_cmd(unsigned char atacmd)
{
  PORT_ATA_IO_CNTL = ATA_IO_CMD;
  avr_databus_out;
  PORT_ATA_DATA_L_OUT = atacmd;
  ata_write_pulse;
  PORT_ATA_IO_CNTL = ATA_IO_HIZ;
  avr_databus_in;
}




Listing  2—Because the routines are identical, with exception to the status bit that’s checked, I took some liberties 
and squashed all three ready, busy, and error routines into a single function to save some space. The unsigned 
 int ata_bsy(void) function includes the if(ata_byte_read & ATA_STAT_BSY) line and the other two functions.