📄 ata_if.c~
字号:
/*---------------------------------------------------------------
FileName : ata_if.c
Created by : ZhengYanbo
Crtated date : 2006.3.31
Version : v1.0
Last Modified: 2007.5.2
Comments : ata low-level drive
************
2007.5.2:
************
Funciton Bug fixed: ATA_Read_Sector_Bytes()
description: when player scan disk, drop some file.
---------------------------------------------------------------*/
#include "ata_if.h"
#include "fat.h"
#include "type.h"
//*************************************************************
//init ata interface port
void ATA_Port_Init(void)
//*************************************************************
{
//ata lower byte
ATA_DATA_PORT_L_IN();
//ata high byte
ATA_DATA_PORT_H_IN();
//set ata IORD output
ATA_IORD_OUT();
//set ata IOWR output
ATA_IOWR_OUT();
//disable output
nIORD = 1; nIOWR = 1;
}
//*************************************************************
// ATA init,setup up some ide registers
void ATA_Init(void)
//*************************************************************
{
unsigned char value=0;
// SRST and nIEN bits
RegWrite(Interrupt,0x06);
delay_ms(100); // 100mS delay
RegWrite(Interrupt, 0x02); // nIEN bit
delay_ms(100); // 100 mS delay
do
{ delay_ms(1000);
value=RegRead(CmdStsReg); //Read status register
}
while (( value & 0xC0) != 0x40 );
//Initialize Standby timer, currently set standby after 5 mins of hard drive inactivity.
RegWrite(SecCountReg,60); //Set 5 mins (60=5mins standby, read ATA documentation)
RegWrite(DrvHeadReg,LBAMaster); //For Master drive
RegWrite(CmdStsReg,0xE2); //Write standby command to command register.
//RegWrite(CmdStsReg,0x96); //0x96 or 0xE2->:standby command(from ata-3)
WaitTillNotBusy(); //Wait until command taken.
}
//*************************************************************
// Init CF Card,using 16 bit mode for data transfer
byte CF_Initialize(void)
//*************************************************************
{
unsigned char temp;
RegWrite(CmdStsReg, CF_CMD_DIAGNOSTIC); //执行诊断指令,判断CF卡是否可用
WaitTillNotBusy(); //等待BUSY位清空
if (RegRead(ErrorReg)==0x01) //读错误寄存器 ,返回0x01表示成功!
{
RegWrite(CF_FeatureReg, 0x01); //enable 8 bit mode.
RegWrite(DrvHeadReg, 0xa0);
RegWrite(DrvHeadReg,LBAMaster); //For Master drive
RegWrite(CmdStsReg, CF_CMD_SETFEATURE); //设置驱动器特性
WaitTillNotBusy(); //等待busy清空
temp=RegRead(ErrorReg); //read Error regsiter.
return temp; //return value of ErrorReg
}
else
{
temp=RegRead(ErrorReg); //CF is not available
return temp; //返回错误寄存器状态
}
}
//*************************************************************
//get drive info by 0xEC command
void ATA_Device_Indentify(void)
//*************************************************************
{
byte i;
struct driveID *driveInfo;
dword startSector;
RegWrite(DrvHeadReg,LBAMaster);
RegWrite(CmdStsReg,0xEC); //ATA identify command.
while ((RegRead(CmdStsReg) & SR_DRQ)!=SR_DRQ); //no error handling
readPos=0;
ATA_Read(512, sectorBuffer.data);
driveInfo = (struct driveID *) sectorBuffer.data;
LCDclrscr(); //Clear LCD to display HDD information.
//i<16 for LCM122*32.
for (i=0; i<16; i+=2) {writechar(driveInfo->model[i+1]); writechar(driveInfo->model[i]); };
//Determine drive size. Multiplication and division is done by shifts
startSector = driveInfo->totalSecHi;
//store total sectors
totalSectors = startSector<<16 + (dword)(driveInfo->totalSecLo);
startSector = ((startSector<<16) + driveInfo->totalSecLo)>>11;
//-------------------------------------------
// com debug info
//-------------------------------------------
printf("CF Mode:");
for (i=0; i<40; i+=2)
{putchar(driveInfo->model[i+1]); putchar(driveInfo->model[i]); };
printf("\n\r");
printf("Total: %-u MB\n\r" ,startSector);
printf("Cycls: %-u\n\r", driveInfo->cylinder);
printf("Heads: %-u\n\r", driveInfo->head);
//--------------------------------------------
// LCD output
//--------------------------------------------
/*
gotoxy(1,0);
writestring("Total:");
writeNumber(startSector); //Display drive size
writestring("MB ");
delay_ms(1000);
LCDclrscr();
writestring("cyls:");
writeNumber(driveInfo->cylinder); //write total cylinders
gotoxy(1,0);
writestring("head:");
writeNumber(driveInfo->head); //write total heads of drive
delay_ms(1000); */
}
//*************************************************************
// Return: 0->no errors 1->sector read command error
byte ATA_start_read_n_sectors(dword lba, byte nSectors)
//*************************************************************
{
byte temp;
WaitTillNotBusy();
//Setup all the specific registers with LBA address.
RegWrite(DrvHeadReg, LBAMaster); //set to master
RegWrite(SecCountReg, nSectors); //n sectors to be read
RegWrite(SecReg,lba); //lba 0-7
RegWrite(LoCylReg,lba>>8 ); //lba 8-15
RegWrite(HiCylReg,lba>>16 ); //lba 16-23
RegWrite(DrvHeadReg, LBAMaster + (lba>>24));//lba 24-27
/*
RegWrite(DrvHeadReg, LBAMaster + (lba>>24));//lba 24-27
RegWrite(HiCylReg,lba>>16 ); //lba 16-23
RegWrite(LoCylReg,lba>>8 ); //lba 8-15
RegWrite(SecReg,lba); //lba 0-7
RegWrite(SecCountReg, nSectors);//n sectors to be read */
// Issue Sector read with retry command...
RegWrite(CmdStsReg, 0x20);
do
{
temp=RegRead(CmdStsReg);
if (temp & SR_ERR) return(1); //Sector read error
}
//Wait for DRQ, meaing wait until disk has ready for reading
while ((temp & SR_DRQ) != SR_DRQ);
return(0); //command has been accepted.
}
//*************************************************************
//send write a sector command
byte ATA_start_write_n_sectors(dword lba, byte nSectors)
//*************************************************************
{
byte temp;
WaitTillNotBusy();
//Setup all the specific registers with LBA address.
RegWrite(DrvHeadReg, LBAMaster); //set to master
RegWrite(SecCountReg, nSectors); //n sectors to be written
RegWrite(SecReg,lba); //lba 0-7
RegWrite(LoCylReg,lba>>8 ); //lba 8-15
RegWrite(HiCylReg,lba>>16 ); //lba 16-23
RegWrite(DrvHeadReg, LBAMaster + (lba>>24)); //lba 24-27
/*
RegWrite(DrvHeadReg, LBAMaster + (lba>>24));//lba 24-27
RegWrite(HiCylReg,lba>>16 ); //lba 16-23
RegWrite(LoCylReg,lba>>8 ); //lba 8-15
RegWrite(SecReg,lba); //lba 0-7
RegWrite(SecCountReg, 1); //1 sectors to be written */
// Issue Sector write command...
RegWrite(CmdStsReg, 0x30);
do
{
temp=RegRead(CmdStsReg);
if (temp & SR_ERR) return(1); //Sector write error
}
//Wait for DRQ, meaing wait until disk has ready for writing
while ((temp & SR_DRQ) != SR_DRQ);
return(0);
}
//*************************************************************
//Reads 16bit word from the ATA IO register.
//Before calling this function head must be moved to desired sector.
void ATA_Read(word bytesToRead, byte *buffer)
//*************************************************************
{
word j;
for(j=0; j<bytesToRead; j++)
{
*buffer++ = IOReg;
}
}
//*************************************************************
//Write 16 bit words to the ATA IO register.
//Before calling this function head must be moved to desired sector.
void ATA_Write(word bytesToWrite, byte *buffer)
//*************************************************************
{
word i;
for(i=0; i<bytesToWrite; i++)
{
IOReg = *buffer++;
}//for(i=0; i<bytesToWrite; i++)
}
//*************************************************************
//read a sector(512 bytes) to buffer
byte ATA_Read_Sector(unsigned long lba, unsigned char *buffer)
//*************************************************************
{
byte temp; byte i;
//start to read
temp=ATA_start_read_n_sectors(lba, 1);
//buffer data
//for speed...
#pragma optsize-
for(i=0; i<64; i++)
{
*buffer++ = IOReg;
*buffer++ = IOReg;
*buffer++ = IOReg;
*buffer++ = IOReg;
*buffer++ = IOReg;
*buffer++ = IOReg;
*buffer++ = IOReg;
*buffer++ = IOReg;
}
#pragma optsize+
//return status
return(temp);
}
//*************************************************************
// Write a whole sector(512 bytes)
// Return: 0->no errors 1->sector write error
byte ATA_Write_Sector(unsigned long lba, unsigned char *buffer)
//*************************************************************
{ //writes on 512 bytes of the sector specified
byte temp;
byte i; //512 bytes to be written
temp=ATA_start_write_n_sectors(lba, 1);
//for speed...
#pragma optsize-
for(i=0; i<64; i++)
{
IOReg = *buffer++;
IOReg = *buffer++;
IOReg = *buffer++;
IOReg = *buffer++;
IOReg = *buffer++;
IOReg = *buffer++;
IOReg = *buffer++;
IOReg = *buffer++;
}
#pragma optsize+
return(temp); //Write sector successfully!
}
/*
//*************************************************************
//read some bytes part of a sector
void ATA_Read_Sector_Bytes(dword lba,word offset,word len,byte *buffer)
//*************************************************************
{
word i=0; byte temp;
//open a lba address
ATA_start_read_n_sectors(lba, 1);
//goto offset
while(offset>i) {temp=IOReg; i++;};
//read bytes
for(i=0; i<len; i++) *buffer++=IOReg;
//read reset of sector
offset=offset+len;
while(offset<512) temp = IOReg;
//increase readPos
readPos += len;
if(readPos==512) readPos=0;
} */
//*************************************************************
//read some bytes part of a sector
void ATA_Read_Sector_Bytes(dword lba, word len, byte *buffer)
//*************************************************************
{
word i; byte temp;
//close lba
while ((RegRead(CmdStsReg) & SR_DRQ) == SR_DRQ) {temp=IOReg;};
//open a new lba address
ATA_start_read_n_sectors(lba, 1);
//arrive at offset=readPos;
for(i=0; i<readPos; i++) {temp = IOReg;};
for(i=0; i<len; i++) {*buffer++ = IOReg;};
readPos = readPos + len;
//reset readPos
if(readPos>=512) readPos=0;
}
/*
//*************************************************************
void ATA_lba_close(void)
//*************************************************************
{
byte temp;
while(readPos!=512) {temp=IOReg; readPos++;};
readPos=0;
}*/
//*************************************************************
void ATA_lba_close(void)
//*************************************************************
{
byte temp;
while ((RegRead(CmdStsReg) & SR_DRQ) == SR_DRQ){temp=IOReg;};
readPos=0; //clear readPos
}
//*************************************************************
// ATA wait driver ready
void WaitTillNotBusy(void)
//*************************************************************
{ //Loop until drive is busy.
while ((RegRead(CmdStsReg) & SR_BSY) == SR_BSY);
}
//*************************************************************
// Read ata status register
byte ATA_get_status(void)
//*************************************************************
{
byte temp;
//read status register
temp=RegRead(CmdStsReg);
return(temp);
}
//*************************************************************
void GoToSectorOffset(dword LBASector,word offset)
//*************************************************************
{
word i; byte temp;
//Find the offset in the sector
ATA_start_read_n_sectors(LBASector,1);
i=0;
while(i<offset) {temp=IOReg; i++;};
}
/*---------------- end of ata_if.c ---------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -