⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ata_if.c~

📁 avr MP3 的源程序,包含文件系统,适合初学者
💻 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 + -