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