📄 ata.c
字号:
unsigned int ata_read_word(void)
{
unsigned int ata_word_read,ata_byte_read;
avr_databus_in;
PORT_ATA_IO_CNTL = ATA_IO_DATA;
PORT_ATA_IO_CNTL &= ~ATA_DIOR;
delay_us(1);
ata_byte_read = PORT_ATA_DATA_H_IN;
ata_word_read = ata_byte_read << 8;
ata_byte_read = PORT_ATA_DATA_L_IN;
ata_word_read |= ata_byte_read;
PORT_ATA_IO_CNTL |= ATA_DIOR;
PORT_ATA_IO_CNTL = ATA_IO_HIZ;
return ata_word_read;
}
//******************************************************************
//* WRITE WORD TO ATA DEVICE
//* This routine does not use SRAM as a buffer.
//*
//******************************************************************
unsigned int ata_write_word(unsigned int wordout)
{
unsigned int returncode;
avr_databus_out;
PORT_ATA_DATA_H_OUT = wordout >> 8;
PORT_ATA_DATA_L_OUT = wordout;
PORT_ATA_IO_CNTL = ATA_IO_DATA;
ata_write_pulse;
PORT_ATA_IO_CNTL = ATA_IO_HIZ;
avr_databus_in;
return returncode;
}
//******************************************************************
//* WRITE A BYTE TO THE ATA I/O
//* This routine writes a byte on the lower 8 bits of the data bus.
//*
//******************************************************************
void ata_write_byte(unsigned char atabyte)
{
avr_databus_out;
PORT_ATA_DATA_L_OUT = atabyte;
ata_write_pulse;
PORT_ATA_IO_CNTL = ATA_IO_HIZ;
avr_databus_in;
}
//******************************************************************
//* SEND ATA COMMAND
//* Sends an ATA command out of lower 8 bits of data bus.
//*
//******************************************************************
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;
}
//******************************************************************
//* READ STATUS BYTE
//* Read ATA status byte.
//*
//******************************************************************
unsigned char ata_get_status_byte(void)
{
unsigned char ata_byte_read;
avr_databus_in;
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;
avr_databus_in;
return ata_byte_read;
}
//******************************************************************
//* READ REGISTER
//*
//*
//******************************************************************
unsigned char ata_get_register(unsigned char cbreg)
{
unsigned char ata_byte_read;
avr_databus_in;
PORT_ATA_IO_CNTL = cbreg;
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;
avr_databus_in;
return ata_byte_read;
}
//******************************************************************
//* PERFORM HARDWARE RESET
//* This routine toggles ATA RESET line low for 10ms.
//*
//******************************************************************
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;
}
//******************************************************************
//* CHECK ATA READY BIT
//* Checks READY status bit.
//* Returns 1 if device is ready.
//******************************************************************
unsigned int ata_rdy(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_RDY)
return 1;
else
return 0;
}
//******************************************************************
//* CHECK ATA BUSY BIT
//* Checks READY status bit.
//* Returns 1 if device is busy.
//******************************************************************
unsigned int ata_bsy(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)
return 1;
else
return 0;
}
//******************************************************************
//* CHECK ATA DRQ BIT
//* Checks READY status bit.
//* Returns 1 if device is requesting service.
//******************************************************************
unsigned int ata_drq(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_DRQ)
return 1;
else
return 0;
}
//******************************************************************
//* CHECK ATA ERROR BIT
//* Checks READY status bit.
//* Returns 1 if device is reporting an error condition.
//******************************************************************
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_ERR)
return 1;
else
return 0;
}
//******************************************************************
//* READ A PAGE OF SRAM
//* A page = 256 words.
//* This routine reads 512 bytes from SRAM to a buffer in the AVR.
//******************************************************************
void ram_read_page(unsigned int page)
{
unsigned int i,j,ram_page,ram_address;
j=0x00;
ram_page = page;
ram_address = ram_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;
nop;
ram_page_buffer[j] = PORT_ATA_DATA_L_IN; //changed H to L
ram_page_buffer[j+1] = PORT_ATA_DATA_H_IN;//changed L to H
ram_off;
++ram_address;
j += 2;
}
}
//******************************************************************
//* FILL A PAGE OF RAM
//* A page = 256 words.
//* This routine fills a ram page with a user-defined word.
//******************************************************************
void ram_fill_page(unsigned int page,unsigned int dataword)
{
unsigned int ram_address,i;
ram_address = page * 0x100;
avr_databus_out;
for(i=0;i<256;++i)
{
PORT_ATA_DATA_H_OUT = ram_address >> 8;
PORT_ATA_DATA_L_OUT = ram_address;
latch_ram_addr;
PORT_ATA_DATA_H_OUT = dataword >> 8;
PORT_ATA_DATA_L_OUT = dataword;
ram_on;
ram_write_pulse;
ram_off;
++ram_address;
//++dataword; // this line increments the original dataword
}
}
//******************************************************************
//* WRITE A SECTOR
//* device = 0x00 or 0x01 ////
//* This routine writes an LBA-addressed sector.
//******************************************************************
unsigned char ata_write_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);
#if debug
gotreg=ata_get_register(ATA_IO_DEVICE_HEAD);
printf("devhead %#x\r\n",gotreg);
gotreg=ata_get_register(ATA_IO_CYL_H);
printf("cylH %#x\r\n",gotreg);
gotreg=ata_get_register(ATA_IO_CYL_L);
printf("cylL %#x\r\n",gotreg);
gotreg=ata_get_register(ATA_IO_SECTORNUM);
printf("sectnum %#x\r\n",gotreg);
for(;;);
#endif
ata_send_cmd(CMD_WRITE_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;
PORT_ATA_IO_CNTL = ATA_IO_DATA;
ata_write_pulse;
delay_us(1); // nop works here too
while(busy);
ram_off;
++ram_address;
}
return (error);
}
//******************************************************************
//* 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);
//printf("\r\nhead %#x\r\n",ata_get_register(ATA_IO_DEVICE_HEAD));
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);
//printf("cylh %#x\r\n",ata_get_register(ATA_IO_CYL_H));
while(busy);
ata_set_io_addr(ATA_IO_CYL_L);
ata_write_byte(lbasector >> 8);
//printf("cyll %#x\r\n",ata_get_register(ATA_IO_CYL_L));
while(busy);
ata_set_io_addr(ATA_IO_SECTORNUM);
ata_write_byte(lbasector);
//printf("sector %#x\r\n",ata_get_register(ATA_IO_SECTORNUM));
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);
}
//******************************************************************
//* Delay millisecond Function
//* This function uses Timer 3 and the A compare registers
//* to produce millisecond delays.
//* Clock = 14.746MHz
//******************************************************************
void delay_ms(unsigned int delay)
{
unsigned int i;
OCR3AH = 0x39;
OCR3AL = 0x9A;
TCCR3B = 0x00; // Stop Timer3
for(i=0;i<delay;++i)
{
TCCR3B = 0x00; // Stop Timer3
TCNT3H = 0x00; // Clear Timer3
TCNT3L = 0x00;
TCCR3B = 0x09; // Start Timer3 with clk/1
while(!(ETIFR & 0x10));
ETIFR |= 0x10;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -