?? ctrl_atapi.c
字號:
/************************************************************************Source file name : ctrl_atapi.cDescription: Implementation of the ATA Control Interface and Device/Protocol setup intermediate modules following the API Design Document v0.9.0 of the ATAPI driver. COPYRIGHT (C) STMicroelectronics 2000************************************************************************//*Includes-------------------------------------------------------------*/#include <string.h>#include "stlite.h"#include "stcommon.h"#include "statapi.h"#include "hal_atapi.h"#include "ata.h"/*Private Types--------------------------------------------------------*//*Private Constants----------------------------------------------------*/#define HARD_RESET_TIMEOUT_SECONDS 10/*Private Variables----------------------------------------------------*//*Private Macros-------------------------------------------------------*//*Private functions prototypes-----------------------------------------*//*Functions------------------------------------------------------------*/ /************************************************************************Name: ata_ctrl_SelectDeviceDescription: Attempts to select the device by writing to the Device/Header reg. Also delays the mandatory 400 ns to ensure subsequent device access is safeParameters: Two params: Ata_p : Pointer to the ATA control block Device: number identifying the device (0,1) ************************************************************************/BOOL ata_ctrl_SelectDevice(ata_ControlBlock_t *Ata_p, U8 Device){ U8 data; /* First wait for not busy (BSY=0)... */ if(WaitForBit(Ata_p->HalHndl,ATA_REG_STATUS,BSY_BIT_MASK,0)) { Ata_p->LastExtendedErrorCode=0x11; return TRUE; } /* ..then wait for DRQ=0 */ if(WaitForBit(Ata_p->HalHndl,ATA_REG_STATUS,DRQ_BIT_MASK,0)) { Ata_p->LastExtendedErrorCode=0x12; return TRUE; } data= hal_RegInByte(Ata_p->HalHndl,ATA_REG_DEVHEAD); if(Device==DEVICE_0) data= data & ~BIT_4; else data= data | BIT_4; hal_RegOutByte(Ata_p->HalHndl,ATA_REG_DEVHEAD,data); WAIT400NS; /* First wait for not busy (BSY=0)... */ if(WaitForBit(Ata_p->HalHndl,ATA_REG_STATUS,BSY_BIT_MASK,0)) { Ata_p->LastExtendedErrorCode=0x11; return TRUE; } /* ...then wait for DRQ=0 */ if(WaitForBit(Ata_p->HalHndl,ATA_REG_STATUS,DRQ_BIT_MASK,0)) { Ata_p->LastExtendedErrorCode=0x12; return TRUE; } return FALSE;}/************************************************************************Name: ata_ctrl_SoftResetDescription: Pulses the SRST bit in the DeviceCtrl register high for 400 ns and then low. Delays for mandatory 400ns afterwardsParameters: Two params: Ata_p : Pointer to the ATA control block Device: number identifying the device (0,1) ************************************************************************/BOOL ata_ctrl_SoftReset(ata_ControlBlock_t *Ata_p){ S32 TimeOut=ATA_TIMEOUT; U8 sc,sn; /* Assert SRST and disable interrupts */ hal_RegOutByte(Ata_p->HalHndl,ATA_REG_CONTROL,SRST_SET|nIEN_SET); /* Wait t > 2ms */ task_delay(TWO_MS); /*Deassert SRTS and enable interrupts if necessary*/#if ATAPI_USING_INTERRUPTS hal_RegOutByte(Ata_p->HalHndl, ATA_REG_CONTROL, 0x00);#else hal_RegOutByte(Ata_p->HalHndl, ATA_REG_CONTROL, 0x02);#endif WAIT400NS; /*RESET DONE. This causes device 0 be selected.*/ /* If there is a device 0, wait for device 0 to set BSY=0.*/ if(Ata_p->DevInBus[0] != NONE_DEVICE) { if(WaitForBit(Ata_p->HalHndl, ATA_REG_STATUS, BSY_BIT_MASK, 0)) { Ata_p->LastExtendedErrorCode = 0x01; return TRUE; } } /* If there is a device 1, wait until device 1 allows register access.*/ if(Ata_p->DevInBus[1] != NONE_DEVICE) { /* Select the device */ hal_RegOutByte(Ata_p->HalHndl, ATA_REG_DEVHEAD, DEVHEAD_DEV1); WAIT400NS; while(TimeOut >= 0) { sn = hal_RegInByte(Ata_p->HalHndl, ATA_REG_SECNUM); sc = hal_RegInByte(Ata_p->HalHndl, ATA_REG_SECCOUNT); if ((sn == 0x01) && (sc == 0x01)) break; TimeOut--; } if(TimeOut<0) { Ata_p->LastExtendedErrorCode = 0x02; return TRUE; } /* Now wait for device 1 to set BSY=0 */ if(WaitForBit(Ata_p->HalHndl, ATA_REG_STATUS, BSY_BIT_MASK, 0)) { Ata_p->LastExtendedErrorCode = 0x03; return TRUE; } } return FALSE;}/************************************************************************Name: ata_ctrl_ProbeDescription: Probes the ATA bus to determine the number of devices attached and their type (ATA or ATAPI)Parameter: Ata_p : Pointer to the ATA control block ************************************************************************/BOOL ata_ctrl_Probe(ata_ControlBlock_t *Ata_p){ U8 error=0; volatile U8 sc,sn,cl,ch,st; Ata_p->DevInBus[0]=NONE_DEVICE; Ata_p->DevInBus[1]=NONE_DEVICE; /* lets see if there is a device 0*/ hal_RegOutByte(Ata_p->HalHndl,ATA_REG_DEVHEAD,DEVHEAD_DEV0); WAIT400NS; hal_RegOutByte(Ata_p->HalHndl,ATA_REG_SECCOUNT ,0x55); hal_RegOutByte(Ata_p->HalHndl,ATA_REG_SECNUM ,0xaa); hal_RegOutByte(Ata_p->HalHndl,ATA_REG_SECCOUNT ,0xaa); hal_RegOutByte(Ata_p->HalHndl,ATA_REG_SECNUM ,0x55); hal_RegOutByte(Ata_p->HalHndl,ATA_REG_SECCOUNT ,0x55); hal_RegOutByte(Ata_p->HalHndl,ATA_REG_SECNUM ,0xaa); sc = hal_RegInByte(Ata_p->HalHndl,ATA_REG_SECCOUNT); sn = hal_RegInByte(Ata_p->HalHndl,ATA_REG_SECNUM); if ( ( sc == 0x55 ) && ( sn == 0xaa ) ) Ata_p->DevInBus[0]= UNKNOWN_DEVICE; /* lets see if there is a device 1*/ hal_RegOutByte(Ata_p->HalHndl,ATA_REG_DEVHEAD,DEVHEAD_DEV1); WAIT400NS; hal_RegOutByte(Ata_p->HalHndl,ATA_REG_SECCOUNT ,0x55); hal_RegOutByte(Ata_p->HalHndl,ATA_REG_SECNUM ,0xaa); hal_RegOutByte(Ata_p->HalHndl,ATA_REG_SECCOUNT ,0xaa); hal_RegOutByte(Ata_p->HalHndl,ATA_REG_SECNUM ,0x55); hal_RegOutByte(Ata_p->HalHndl,ATA_REG_SECCOUNT ,0x55); hal_RegOutByte(Ata_p->HalHndl,ATA_REG_SECNUM ,0xaa); sc = hal_RegInByte(Ata_p->HalHndl,ATA_REG_SECCOUNT); sn = hal_RegInByte(Ata_p->HalHndl,ATA_REG_SECNUM); if ( ( sc == 0x55 ) && ( sn == 0xaa ) ) Ata_p->DevInBus[1]= UNKNOWN_DEVICE; /* now we think we know which devices, if any are there, so lets try a soft reset (ignoring any errors).*/ /*Assert SRST and disable interrupts */ hal_RegOutByte(Ata_p->HalHndl,ATA_REG_CONTROL,SRST_SET|nIEN_SET); /* Wait t > 2ms */ task_delay(TWO_MS); /*Deassert SRTS and enable interrupts if necessary*/ #if ATAPI_USING_INTERRUPTS hal_RegOutByte(Ata_p->HalHndl,ATA_REG_CONTROL,0x08); #else hal_RegOutByte(Ata_p->HalHndl,ATA_REG_CONTROL,0x00); #endif WaitForBit(Ata_p->HalHndl,ATA_REG_STATUS,BSY_BIT_MASK,0); /*RESET DONE. This causes device 0 be selected.*/ sc = hal_RegInByte(Ata_p->HalHndl,ATA_REG_SECCOUNT); sn = hal_RegInByte(Ata_p->HalHndl,ATA_REG_SECNUM); if ( ( sc == 0x01 ) && ( sn == 0x01 ) ) { Ata_p->DevInBus[0]= UNKNOWN_DEVICE; ch = hal_RegInByte(Ata_p->HalHndl,ATA_REG_CYLHIGH); cl = hal_RegInByte(Ata_p->HalHndl,ATA_REG_CYLLOW); st = hal_RegInByte(Ata_p->HalHndl,ATA_REG_STATUS); if ( ( cl == 0x14 ) && ( ch == 0xeb ) ) Ata_p->DevInBus[0] = ATAPI_DEVICE; else if ( ( cl == 0x00 ) && ( ch == 0x00 ) && ( st != 0x00 ) ) Ata_p->DevInBus[0] = ATA_DEVICE; } /*Now for the device 1*/ hal_RegOutByte(Ata_p->HalHndl,ATA_REG_DEVHEAD,DEVHEAD_DEV1); WAIT400NS; sc = hal_RegInByte(Ata_p->HalHndl,ATA_REG_SECCOUNT); sn = hal_RegInByte(Ata_p->HalHndl,ATA_REG_SECNUM); if ( ( sc == 0x01 ) && ( sn == 0x01 ) ) { Ata_p->DevInBus[1]= UNKNOWN_DEVICE; cl = hal_RegInByte(Ata_p->HalHndl,ATA_REG_CYLHIGH); ch = hal_RegInByte(Ata_p->HalHndl,ATA_REG_CYLLOW); st = hal_RegInByte(Ata_p->HalHndl,ATA_REG_STATUS); if ( ( cl == 0x14 ) && ( ch == 0xeb ) ) Ata_p->DevInBus[1] = ATAPI_DEVICE; else if ( ( cl == 0x00 ) && ( ch == 0x00 ) && ( st != 0x00 ) ) Ata_p->DevInBus[1] = ATA_DEVICE; } return error; }/************************************************************************Name: ata_ctrl_HardResetDescription: Probes the ATA bus to determine the number of devices attached and their type (ATA or ATAPI)Parameter: Ata_p : Pointer to the ATA control block ************************************************************************/BOOL ata_ctrl_HardReset(ata_ControlBlock_t *Ata_p){ volatile U8 Dummy; clock_t timeout; U32 TimeoutTicks; TimeoutTicks = HARD_RESET_TIMEOUT_SECONDS * ST_GetClocksPerSecond(); hal_HardReset(Ata_p->HalHndl); timeout = time_plus(time_now(), TimeoutTicks); /* Wait for BSY=0 or timeout */ while(TRUE) { WAIT400NS; Dummy=hal_RegInByte(Ata_p->HalHndl,ATA_REG_STATUS); if ((Dummy & BSY_BIT_MASK) == 0) break; /* Returns 1 if first time is after the second */ if (time_after(time_now(), timeout) == 1) break; } /* Check */ if ((Dummy & BSY_BIT_MASK) == 0) return FALSE; else return TRUE;}/************************************************************************Name: ata_bus_AcquireDescription: Obtains the bus check semaphore and checks the bus busy flag (SW flag). If not set the bus busy flag is set. Releases the bus check semaphoreParameter: Ata_p : Pointer to the ATA control block ************************************************************************/BOOL ata_bus_Acquire(ata_ControlBlock_t *Ata_p){ /* Semaphore needs to protect check, as well as any set */ semaphore_wait ( &Ata_p->BusMutexSemaphore ); if(Ata_p->BusBusy==FALSE) { Ata_p->BusBusy=TRUE; semaphore_signal ( &Ata_p->BusMutexSemaphore ); return FALSE; } semaphore_signal ( &Ata_p->BusMutexSemaphore ); return TRUE;}/************************************************************************Name: ata_bus_ReleaseDescription: Obtains the bus check semaphore and checks the bus busy flag (SW flag). If set the bus busy flag is cleared. Releases the bus check semaphoreParameter: Ata_p : Pointer to the ATA control block ************************************************************************/BOOL ata_bus_Release(ata_ControlBlock_t *Ata_p){ /* Semaphore needs to protect check, as well as any set */ semaphore_wait ( &Ata_p->BusMutexSemaphore ); if(Ata_p->BusBusy == TRUE) { Ata_p->BusBusy=FALSE; semaphore_signal ( &Ata_p->BusMutexSemaphore ); return FALSE; } semaphore_signal ( &Ata_p->BusMutexSemaphore ); return TRUE;}/************************************************************************Name: WaitForBitDescription: Wait for a bit to be setParameters: Three params: HalHndl : Pointer to the HAL control block regNo: Register number bitNo: mask with the bit to test expected_val: expected value of the register after applying a mask to use only the relevant bits ************************************************************************/BOOL WaitForBit(hal_Handle_t *HalHndl,ATA_Register_t regNo,U8 bitNo,U8 expected_val){ U32 i; volatile U8 dummy; for (i=0;i<ATA_TIMEOUT;i++) { WAIT400NS; dummy=hal_RegInByte(HalHndl,regNo); if( (dummy & bitNo)== expected_val) return FALSE; } return TRUE;}/************************************************************************Name: WaitForBitPktDescription: Wait for a bit to be set.Version for the packet command interface.we need a different verion because of the longer delay of the ATAPI devicesParameters: Three params: HalHndl : Pointer to the HAL control block regNo: Register number bitNo: mask with the bit to test expected_val: expected value of the register after applying a mask to use only the relevant bits ************************************************************************/BOOL WaitForBitPkt(hal_Handle_t *HalHndl,ATA_Register_t regNo,U8 bitNo,U8 expected_val){ U32 i; volatile U8 dummy; for (i=0;i<ATAPI_TIMEOUT;i++) { WAIT400NS; dummy=hal_RegInByte(HalHndl,regNo); if( (dummy & bitNo)== expected_val) return FALSE; } return TRUE;}/*end of ctrl_atapi.c --------------------------------------------------*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -