?? cmmd_ata.c
字號:
/************************************************************************Source file name : cmmd_ata.cDescription: Implementation of the ATA Command Interface intermediate module following the API Design Document v0.9.0 of the ATAPI driver.COPYRIGHT (C) STMicroelectronics 200031-08-00 Added an extra 400 ns delay at the end of the PIO in protocol to allow slow drives as CD-ROM's to update their status registers. (MV) ************************************************************************//*Includes-------------------------------------------------------------*/#include <stdio.h>#include <string.h>#include "stlite.h"#include "statapi.h"#include "stsys.h"#include "hal_atapi.h"#include "ata.h"#include "stcommon.h"#include "sttbx.h"/*Private Types--------------------------------------------------------*//*Private Constants----------------------------------------------------*//*Private Variables----------------------------------------------------*/extern U32 intcount;extern U32 inttrace[15];/* Kind of messy, but since we need to get status differently for * an extended command, and we can't expect the user to tell us what type * a command was... */BOOL LastCommandExtended = FALSE;/*Private Macros-------------------------------------------------------*/#if defined(ST_5512) #define ATAPI_DATA 0x60080000 #elif defined(ST_5508) || defined(ST_5518) #define ATAPI_DATA 0x50200000 #endif/*Private functions prototypes-----------------------------------------*/static void GetCmdStatus(ata_ControlBlock_t *Ata_p, STATAPI_CmdStatus_t *Stat_p);static void ata_cmd_WriteRegs(ata_ControlBlock_t *Ata_p, ata_Cmd_t *Cmd_p);extern BOOL Trace;/*Functions------------------------------------------------------------*//************************************************************************Name: ata_cmd_WriteRegsDescription: Programs registers for sector count/number, cylinder, etc.Parameters: Two params: Ata_p : Pointer to the ATA control block Cmd_p : Pointer to a command structureReturn: none ************************************************************************/static void ata_cmd_WriteRegs(ata_ControlBlock_t *Ata_p, ata_Cmd_t *Cmd_p){ /* Feature is reserved with extended commands, so don't write. */ if ((Cmd_p->CmdType & ATA_EXT_BIT) == 0) hal_RegOutByte(Ata_p->HalHndl, ATA_REG_FEATURE, Cmd_p->Feature);#if defined(STTBX_PRINT) if (Trace == TRUE) { STTBX_Print(("Feature: %i\n", Cmd_p->Feature)); STTBX_Print(("SC: 0x%x\nSN: %i\nCL: %i\nCH: %i\n", Cmd_p->SecCount, Cmd_p->SecNum, Cmd_p->CylLow, Cmd_p->CylHigh)); STTBX_Print(("DH: %i\n", Cmd_p->DevHead)); STTBX_Print(("CC: 0x%02x\n", Cmd_p->CommandCode)); }#endif hal_RegOutByte(Ata_p->HalHndl, ATA_REG_SECCOUNT, Cmd_p->SecCount); hal_RegOutByte(Ata_p->HalHndl, ATA_REG_SECNUM, Cmd_p->SecNum); hal_RegOutByte(Ata_p->HalHndl, ATA_REG_CYLLOW, Cmd_p->CylLow); hal_RegOutByte(Ata_p->HalHndl, ATA_REG_CYLHIGH, Cmd_p->CylHigh); /* "first" write of devhead is also reserved */ if ((Cmd_p->CmdType & ATA_EXT_BIT) == 0) hal_RegOutByte(Ata_p->HalHndl, ATA_REG_DEVHEAD, Cmd_p->DevHead); /* If it's an extended command, now write the other bits and head. */ if ((Cmd_p->CmdType & ATA_EXT_BIT) != 0) { LastCommandExtended = TRUE; hal_RegOutByte(Ata_p->HalHndl, ATA_REG_SECCOUNT, Cmd_p->SecCount2); hal_RegOutByte(Ata_p->HalHndl, ATA_REG_SECNUM, Cmd_p->SecNum2); hal_RegOutByte(Ata_p->HalHndl, ATA_REG_CYLLOW, Cmd_p->CylLow2); hal_RegOutByte(Ata_p->HalHndl, ATA_REG_CYLHIGH, Cmd_p->CylHigh2); hal_RegOutByte(Ata_p->HalHndl, ATA_REG_DEVHEAD, Cmd_p->DevHead); } else LastCommandExtended = FALSE;}/************************************************************************Name: ata_cmd_NoDataDescription: executes a non data command. The device is already selected no parameters check is performed. We totally trust on the caller Parameters: Two params: Ata_p : Pointer to the ATA control block Cmd_p : Pointer to a command structureReturn: TRUE: Extended error is set FALSE: No error ************************************************************************/BOOL ata_cmd_NoData(ata_ControlBlock_t *Ata_p, ata_Cmd_t *Cmd_p){ DU8 status; /* First we write the registers */ ata_cmd_WriteRegs(Ata_p, Cmd_p); if(WaitForBit(Ata_p->HalHndl, ATA_REG_ALTSTAT, DRDY_BIT_MASK, DRDY_BIT_MASK)) { STTBX_Print(("Device not ready 0x26\n")); Ata_p->LastExtendedErrorCode= 0x26; GetCmdStatus(Ata_p,Cmd_p->Stat.CmdStat); return TRUE; } /* Finally write the command */ hal_RegOutByte(Ata_p->HalHndl,ATA_REG_COMMAND, Cmd_p->CommandCode); #if ATAPI_USING_INTERRUPTS if(hal_AwaitInt(Ata_p->HalHndl,INT_TIMEOUT)) { STTBX_Print(("Not interrupt 0x22\n")); Ata_p->LastExtendedErrorCode= 0x22; GetCmdStatus(Ata_p,Cmd_p->Stat.CmdStat); return TRUE; }#else WAIT400NS; if(WaitForBit(Ata_p->HalHndl,ATA_REG_ALTSTAT,BSY_BIT_MASK,0)) { STTBX_Print(("BSY not set, 0x23\n")); Ata_p->LastExtendedErrorCode= 0x23; GetCmdStatus(Ata_p,Cmd_p->Stat.CmdStat); return TRUE; }#endif /* ATAPI_USING_INTERRUPTS */ /* Now Check the Status */ status= hal_RegInByte(Ata_p->HalHndl,ATA_REG_STATUS); if( status & (BSY_BIT_MASK | DRQ_BIT_MASK| DF_BIT_MASK | ERR_BIT_MASK)) { STTBX_Print(("Unwanted bit 0x21\n")); Ata_p->LastExtendedErrorCode= 0x21; GetCmdStatus(Ata_p,Cmd_p->Stat.CmdStat); return TRUE; } GetCmdStatus(Ata_p,Cmd_p->Stat.CmdStat); Ata_p->LastExtendedErrorCode= 0x00; return FALSE;}/************************************************************************Name: ata_cmd_PioInDescription: executes a command with data transfer from the device to the host via PIO. The device is already selected, no parameters check is performed. We totally trust on the caller Parameters: Two params: Ata_p : Pointer to the ATA control block Cmd_p : Pointer to a command structureReturn: TRUE: Extended error is set FALSE: No error ************************************************************************/BOOL ata_cmd_PioIn(ata_ControlBlock_t *Ata_p, ata_Cmd_t *Cmd_p){ volatile U8 status; BOOL Error=FALSE; U16* Data_p; U32 loopcount = 0; *Cmd_p->BytesRW =0; Data_p= (U16*) Cmd_p->DataBuffer; /* First we write the registers */ ata_cmd_WriteRegs(Ata_p, Cmd_p); if(WaitForBit(Ata_p->HalHndl,ATA_REG_ALTSTAT,DRDY_BIT_MASK,DRDY_BIT_MASK)) { STTBX_Print(("Device not ready 0x36\n")); Ata_p->LastExtendedErrorCode= 0x36; GetCmdStatus(Ata_p,Cmd_p->Stat.CmdStat); return TRUE; } /* Finally write the command */ hal_RegOutByte(Ata_p->HalHndl, ATA_REG_COMMAND, Cmd_p->CommandCode); WAIT400NS; /* Transfering Data: Read Loop*/ while (TRUE) { #if ATAPI_USING_INTERRUPTS if(hal_AwaitInt(Ata_p->HalHndl, INT_TIMEOUT)) { STTBX_Print(("No interrupt 0x34\n")); GetCmdStatus(Ata_p, Cmd_p->Stat.CmdStat); STTBX_Print(("intcount: %i\n", intcount)); STTBX_Print(("loopcount: %i\n", loopcount)); STTBX_Print(("Sectors remaining: %i\n", Cmd_p->SecCount)); if (1) { U32 i; for (i = 0; i < intcount; i++) STTBX_Print(("%i %04x\n", i, inttrace[i])); } Ata_p->LastExtendedErrorCode= 0x34; Error= TRUE; break; } intcount = 0; #endif if(WaitForBit(Ata_p->HalHndl, ATA_REG_ALTSTAT, BSY_BIT_MASK, 0)) { Ata_p->LastExtendedErrorCode= 0x35; Error= TRUE; break; } /* Now check the status*/ status=hal_RegInByte(Ata_p->HalHndl,ATA_REG_STATUS); /* Checking if Busy =0 and DRQ=1 in order to enter into the transfer phase */ if ((status & (BSY_BIT_MASK | DRQ_BIT_MASK)) == DRQ_BIT_MASK) { /* Read one DRQ sector*/#ifdef BMDMA_ENABLE ATA_BMDMA((U8*)ATAPI_DATA, (U8*)Data_p, Cmd_p->MultiCnt * SECTOR_BSIZE); *Cmd_p->BytesRW += (Cmd_p->MultiCnt * SECTOR_BSIZE); Data_p += (Cmd_p->MultiCnt * SECTOR_WSIZE);#else hal_RegInBlock(Ata_p->HalHndl, Data_p, SECTOR_BSIZE * Cmd_p->MultiCnt, Cmd_p->UseDMA); Data_p += SECTOR_WSIZE * Cmd_p->MultiCnt; *Cmd_p->BytesRW += SECTOR_BSIZE * Cmd_p->MultiCnt;#endif Cmd_p->SecCount = Cmd_p->SecCount - Cmd_p->MultiCnt; } else { /* BSY 0, DRQ 0 => error */ status=hal_RegInByte(Ata_p->HalHndl,ATA_REG_STATUS); if((status & (ERR_BIT_MASK | DF_BIT_MASK)) != 0) { STTBX_Print(("Unwanted bits; 0x%02x; 0x31\n", status)); STTBX_Print(("Feature: %i\n", Cmd_p->Feature)); STTBX_Print(("SC: 0x%x\nSN: %i\nCL: %i\nCH: %i\n", Cmd_p->SecCount, Cmd_p->SecNum, Cmd_p->CylLow, Cmd_p->CylHigh)); STTBX_Print(("DH: %i\n", Cmd_p->DevHead)); STTBX_Print(("CC: 0x%02x\n", Cmd_p->CommandCode)); Ata_p->LastExtendedErrorCode= 0x31; Error= TRUE; break; } } if(Cmd_p->SecCount<1) { /* Since the drive has transferred all of the requested sectors without error, the drive should not have BUSY, DEVICE FAULT, DATA REQUEST or ERROR active now.*/ WAIT400NS; status = hal_RegInByte(Ata_p->HalHndl,ATA_REG_STATUS); if (status & (BSY_BIT_MASK | ERR_BIT_MASK | DF_BIT_MASK | DRQ_BIT_MASK)) { STTBX_Print(("Unwanted bits; 0x%02x; 0x33\n", status)); Ata_p->LastExtendedErrorCode= 0x33; Error= TRUE; break; } /* All sectors have been read without error, exit */ Ata_p->LastExtendedErrorCode= 0x00; break; } /*End of read loop*/ loopcount++; } /*read the output registers and store them in the cmd status structure*/ GetCmdStatus(Ata_p, Cmd_p->Stat.CmdStat); return Error; } /************************************************************************Name: ata_cmd_PioOutDescription: executes a command with data transfer from the host to the device via PIO. The device is already selected, no parameters check is performed. We totally trust on the caller Parameters: Two params: Ata_p : Pointer to the ATA control block Cmd_p : Pointer to a command structureReturn: TRUE: Extended error is set FALSE: No error ************************************************************************/BOOL ata_cmd_PioOut(ata_ControlBlock_t *Ata_p, ata_Cmd_t *Cmd_p){ volatile U8 status; BOOL Error=FALSE; U16* Data_p; *Cmd_p->BytesRW =0; Data_p= (U16*) Cmd_p->DataBuffer; /* First we write the registers */ ata_cmd_WriteRegs(Ata_p, Cmd_p); if(WaitForBit(Ata_p->HalHndl,ATA_REG_ALTSTAT,DRDY_BIT_MASK,DRDY_BIT_MASK)) { STTBX_Print(("Device not ready 0x46\n")); Ata_p->LastExtendedErrorCode= 0x46; GetCmdStatus(Ata_p,Cmd_p->Stat.CmdStat); return TRUE; } /* Finally write the command */ hal_RegOutByte(Ata_p->HalHndl,ATA_REG_COMMAND, Cmd_p->CommandCode); WAIT400NS; if(WaitForBit(Ata_p->HalHndl,ATA_REG_STATUS,BSY_BIT_MASK,0)) { STTBX_Print(("Device busy 0x45\n")); Ata_p->LastExtendedErrorCode= 0x45; return TRUE; } /* Transfering Data: Write Loop*/ while (TRUE) { intcount = 0; /* Check the status*/ status=hal_RegInByte(Ata_p->HalHndl,ATA_REG_STATUS); /* Checking if Busy =0 and DRQ=1 in order to enter into the transfer phase */ if((status & ( BSY_BIT_MASK | DRQ_BIT_MASK))== DRQ_BIT_MASK) { /* Write one DRQ sector*/ #ifdef BMDMA_ENABLE ATA_BMDMA((U8*)Data_p, (U8*)ATAPI_DATA, Cmd_p->MultiCnt * SECTOR_BSIZE); *Cmd_p->BytesRW += (Cmd_p->MultiCnt * SECTOR_BSIZE); Data_p += (Cmd_p->MultiCnt * SECTOR_WSIZE);#else hal_RegOutBlock(Ata_p->HalHndl, Data_p, SECTOR_BSIZE * Cmd_p->MultiCnt, Cmd_p->UseDMA); Data_p += SECTOR_WSIZE * Cmd_p->MultiCnt; *Cmd_p->BytesRW += SECTOR_BSIZE * Cmd_p->MultiCnt; #endif Cmd_p->SecCount = Cmd_p->SecCount - Cmd_p->MultiCnt; } if (Cmd_p->SecCount < 1) { #if ATAPI_USING_INTERRUPTS if(hal_AwaitInt(Ata_p->HalHndl, INT_TIMEOUT)) { status = hal_RegInByte(Ata_p->HalHndl, ATA_REG_STATUS); STTBX_Print(("int timeout; status: 0x%02x; 0x44\n", status)); Ata_p->LastExtendedErrorCode = 0x44; Error = TRUE; break; }#else WAIT400NS; if (WaitForBit(Ata_p->HalHndl, ATA_REG_ALTSTAT, BSY_BIT_MASK, 0)) { Ata_p->LastExtendedErrorCode= 0x45; Error= TRUE; break; }#endif /* ATAPI_USING_INTERRUPTS */ /*Since the drive has transferred all of the requested sectors without error, the drive should not have BUSY, DEVICE FAULT, DATA REQUEST or ERROR active now.*/ WAIT400NS; status= hal_RegInByte(Ata_p->HalHndl,ATA_REG_STATUS); if(status & (BSY_BIT_MASK | ERR_BIT_MASK | DF_BIT_MASK | DRQ_BIT_MASK)) { STTBX_Print(("Unwanted bits; 0x%02x; 0x43\n", status)); Ata_p->LastExtendedErrorCode= 0x43; Error= TRUE;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -