#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.