******************************************************************
Read a sector 
device = 0x00 or 0x01  
This routine reads an LBA-addressed sector into a SRAM page.
******************************************************************  	
unsigned char ata_read_sector(unsigned char device, unsigned long lbasector \
                               ,unsigned int page)
{
 unsigned int i,ram_address;
 lbasector &= 0x0FFFFFFF;
 ata_set_io_addr(ATA_IO_DEVICE_HEAD);
 switch (device)
 {
  case 0x00:
  	   ata_write_byte(lbasector >> 24 | 0xE0);
	   break;
  case 0x01:
  	   ata_write_byte(lbasector >> 24 | 0xF0);
	   break;
  default:
  	   ata_write_byte(lbasector >> 24 | 0xE0);
	   break; 
 } 
 while(busy);
 ata_set_io_addr(ATA_IO_CYL_H);
 ata_write_byte(lbasector >> 16);
 while(busy);
 ata_set_io_addr(ATA_IO_CYL_L);
 ata_write_byte(lbasector >> 8);
 while(busy);
 ata_set_io_addr(ATA_IO_SECTORNUM);
 ata_write_byte(lbasector);
 while(busy);
 ata_set_io_addr(ATA_IO_SECTORCNT);
 ata_write_byte(0x01);
 while(busy);
 ata_send_cmd(CMD_READ_SECTORS);
 while(busy);
 while(!drq);
  
 ram_address = page * 0x100;
 for(i=0;i<256;++i)
 {
  avr_databus_out;
  PORT_ATA_DATA_H_OUT = ram_address >> 8;
  PORT_ATA_DATA_L_OUT = ram_address;
  latch_ram_addr;
  avr_databus_in;
  ram_on;
  while(busy);
  PORT_ATA_IO_CNTL = ATA_IO_DATA;
  PORT_ATA_IO_CNTL &= ~ATA_DIOR;
  delay_us(1);
  ram_write_pulse;
  delay_us(1);
  PORT_ATA_IO_CNTL |= ATA_DIOR;
  PORT_ATA_IO_CNTL = ATA_IO_HIZ;
  while(busy);
  ram_off;
  ++ram_address;
 } 
  return (error);
}			 		

Listing 3—There aren’t any tricks in this code. It’s all simple read and write I/O between the hard disk and the SRAM. The routine reads an LBA-addressed sector into an SRAM page.