📄 usbh_hcds_fifo.c
字号:
/*
* description : USBH HCD FIFO Management(static)
* Maker : Hiromichi Kondo
* Copyright : (C)2005,SEIKO EPSON Corp. All Rights Reserved.
*/
#include <string.h> /* memset */
#include <SPRDEF.h>
#include <SPRSTS.h>
#include <usbh_hcd.h>
#include <usbh_hcds_common.h>
#include <usbh_hcds_72V05.h>
#include <usbh_hcds_fifo.h>
/*****************************************
* Define definition
*****************************************/
#define NUM_USB_CH USBH_HCDS_HC_NUM_USB_CH
#define NUM_FIFO_TABLE (NUM_USB_CH * 2)
#define NOT_USED_CH_NUM (0xFF)
#define TYPE_CTL USBH_HCDS_FIFO_TYPE_CTL
#define TYPE_BULK USBH_HCDS_FIFO_TYPE_BULK
#define TYPE_INT USBH_HCDS_FIFO_TYPE_INT
#define TYPE_ISO USBH_HCDS_FIFO_TYPE_ISO
#define TYPE_UNKNOWN (0xFF)
#define ALL_AREA (0)
#define EMPTY_AREA (1)
/*****************************************
* Structure definition
*****************************************/
typedef struct tagFIFO_TABLE{
USBH_HCD_LIST_HEAD sList;
unsigned long startAdrs;
unsigned long endAdrs;
unsigned char chNum;
unsigned char type;
}FIFO_TABLE;
typedef struct tagFIFO_MAP{
unsigned short ctlStartAdrs; /* Start address of FIFO area for Control */
unsigned short ctlFIFOSize; /* Size of FIFO area for control */
unsigned short bulkStartAdrs; /* Start address of FIFO area for bulk */
unsigned short bulkFIFOSize; /* Size of FIFO area for Bulk */
unsigned short intStartAdrs; /* Start address of FIFO area for interrupt */
unsigned short intFIFOSize; /* Size of FIFO area for interrupt */
unsigned short isoStartAdrs; /* Start address of FIFO area for Iso */
unsigned short isoFIFOSize; /* Size of FIFO area for Iso */
}FIFO_MAP;
typedef struct tagFIFO_MANAGER{
FIFO_MAP sFIFOMap;
USBH_HCD_LIST_HEAD sFIFOTableList;
USBH_HCD_LIST_HEAD sFreeFIFOTableList;
unsigned short endFIFOTable;
}FIFO_MANAGER;
/*****************************************
* Function prototype declaration
*****************************************/
Inline FIFO_TABLE *SearchFIFOArea( long *retValue, unsigned long *allocStartAdrs, unsigned char area, USBH_HCD_LIST_HEAD *psFIFOList,
unsigned long searchStartAdrs, unsigned long searchEndAdrs, unsigned long allocSize );
/*****************************************
* Variable definition
*****************************************/
#ifdef DEBUG_C
FIFO_MANAGER FIFOStatus;
FIFO_TABLE FIFOTable[NUM_FIFO_TABLE];
#else /* #ifdef DEBUG_C */
static FIFO_MANAGER FIFOStatus;
static FIFO_TABLE FIFOTable[NUM_FIFO_TABLE];
#endif /* #ifdef DEBUG_C */
/*=============================================================================================
// Function_Name: USBH_HCDS_FIFOInit
//
// description : FIFO management block initialization
//
// Initializae FIFO management block
//
// argument : None
//
// return : None
===============================================================================================*/
void USBH_HCDS_FIFOInit( void )
{
FIFO_TABLE *psFIFOTable;
FIFO_MAP *psFIFOMap;
unsigned int i;
memset(&FIFOStatus, 0, sizeof(FIFOStatus));
memset(&FIFOTable, 0, sizeof(FIFOTable));
psFIFOMap = &(FIFOStatus.sFIFOMap);
psFIFOMap->ctlStartAdrs = USBH_HCDS_HC_FIFO_START_ADRS_CTRL;
psFIFOMap->ctlFIFOSize = USBH_HCDS_HC_FIFO_SIZE_CTRL;
psFIFOMap->bulkStartAdrs = USBH_HCDS_HC_FIFO_START_ADRS_BULK;
psFIFOMap->bulkFIFOSize = USBH_HCDS_HC_FIFO_SIZE_BULK;
psFIFOMap->intStartAdrs = USBH_HCDS_HC_FIFO_START_ADRS_INT;
psFIFOMap->intFIFOSize = USBH_HCDS_HC_FIFO_SIZE_INT;
psFIFOMap->isoStartAdrs = USBH_HCDS_HC_FIFO_START_ADRS_ISO;
psFIFOMap->isoFIFOSize = USBH_HCDS_HC_FIFO_SIZE_ISO;
USBH_HCDS_InitListHead(&FIFOStatus.sFIFOTableList);
USBH_HCDS_ListAdd(&FIFOTable[0].sList, &FIFOStatus.sFIFOTableList);
psFIFOTable = USBH_HCDS_ListEntry(FIFOStatus.sFIFOTableList.psNext, FIFO_TABLE, sList);
psFIFOTable[0].chNum = NOT_USED_CH_NUM;
psFIFOTable[0].startAdrs = USBH_HCDS_HC_FIFO_START_ADRS_ALLOC;
psFIFOTable[0].endAdrs = USBH_HCDS_HC_FIFO_END_ADRS_ALLOC;
psFIFOTable[0].type = TYPE_UNKNOWN;
USBH_HCDS_InitListHead(&FIFOStatus.sFreeFIFOTableList);
for( i = 1; i < NUM_FIFO_TABLE; i++ ){
USBH_HCDS_ListAddTail(&FIFOTable[i].sList, &FIFOStatus.sFreeFIFOTableList);
}
}
/*=============================================================================================
// Function_Name: USBH_HCDS_FIFOAlloc
//
// description : Allocation of FIFO area
//
// The area of the specified FIFO size is allocated
//
// argument : *psFIFOInfo (in)FIFO information
//
// return : STATUS_SUCCESS Processing completed successfully
// STATUS_INVALID_PARAMETER Parameter error
// STATUS_MEM_ERROR Failed to allocate memory
// STATUS_CANNOT_SETUP It is not possible to allocate it because it is used by another
===============================================================================================*/
long USBH_HCDS_FIFOAlloc( USBH_HCDS_FIFOINFO *psFIFOInfo )
{
FIFO_TABLE *psFIFOTable, *psFreeFIFOTable;
USBH_HCD_LIST_HEAD *psFIFOList;
long retValue;
unsigned long searchStartAdrs, searchEndAdrs;
unsigned long allocStartAdrs, allocEndAdrs;
unsigned short endFIFOTable;
switch( psFIFOInfo->type ){
case USBH_HCDS_FIFO_TYPE_CTRL:
searchStartAdrs = USBH_HCDS_HC_FIFO_START_ADRS_CTRL;
searchEndAdrs = USBH_HCDS_HC_FIFO_END_ADRS_CTRL;
break;
case USBH_HCDS_FIFO_TYPE_BULK:
searchStartAdrs = USBH_HCDS_HC_FIFO_START_ADRS_BULK;
searchEndAdrs = USBH_HCDS_HC_FIFO_END_ADRS_BULK;
break;
case USBH_HCDS_FIFO_TYPE_INT:
searchStartAdrs = USBH_HCDS_HC_FIFO_START_ADRS_INT;
searchEndAdrs = USBH_HCDS_HC_FIFO_END_ADRS_INT;
break;
case USBH_HCDS_FIFO_TYPE_ISO:
searchStartAdrs = USBH_HCDS_HC_FIFO_START_ADRS_ISO;
searchEndAdrs = USBH_HCDS_HC_FIFO_END_ADRS_ISO;
break;
default:
return STATUS_INVALID_PARAMETER;
}
psFIFOList = &(FIFOStatus.sFIFOTableList);
psFIFOTable = SearchFIFOArea(&retValue, &allocStartAdrs, EMPTY_AREA, psFIFOList, searchStartAdrs, searchEndAdrs, psFIFOInfo->size);
if( retValue != STATUS_SUCCESS ){
/* FIFO cannot be allocated */
if( psFIFOInfo->type == USBH_HCDS_FIFO_TYPE_INT || psFIFOInfo->type == USBH_HCDS_FIFO_TYPE_ISO ){
/* Confirm whether the Bulk transfer is used when in synchronous transfer(Interrupt and Isochronous) */
psFIFOTable = SearchFIFOArea(&retValue, &allocStartAdrs, ALL_AREA, psFIFOList, searchStartAdrs, searchEndAdrs, psFIFOInfo->size);
return retValue;
} else {
return STATUS_MEM_ERROR;
}
}
retValue = USBH_HCDS_HCFIFOAlloc(psFIFOInfo->chNum, allocStartAdrs, &allocEndAdrs, psFIFOInfo->size);
if( retValue != STATUS_SUCCESS ){
if( retValue == STATUS_NOT_READY ){
/* Transfer is not prepared */
return STATUS_MEM_ERROR;
}
return retValue;
}
endFIFOTable = FIFOStatus.endFIFOTable;
psFIFOList = &(psFIFOTable->sList);
if( psFIFOTable->startAdrs < allocStartAdrs ){
/* Hold the empty area and continue to add */
endFIFOTable++;
psFreeFIFOTable = USBH_HCDS_ListEntry(FIFOStatus.sFreeFIFOTableList.psNext, FIFO_TABLE, sList);
USBH_HCDS_ListDel(FIFOStatus.sFreeFIFOTableList.psNext);
psFreeFIFOTable->chNum = psFIFOInfo->chNum;
psFreeFIFOTable->startAdrs = allocStartAdrs;
psFreeFIFOTable->endAdrs = allocEndAdrs;
psFreeFIFOTable->type = psFIFOInfo->type;
USBH_HCDS_ListAdd(&(psFreeFIFOTable->sList), psFIFOList);
psFIFOList = psFIFOList->psNext;
}
if( allocEndAdrs < psFIFOTable->endAdrs ){
/* Empty area dividing into parts */
endFIFOTable++;
psFreeFIFOTable = USBH_HCDS_ListEntry(FIFOStatus.sFreeFIFOTableList.psNext, FIFO_TABLE, sList);
USBH_HCDS_ListDel(FIFOStatus.sFreeFIFOTableList.psNext);
psFreeFIFOTable->chNum = psFIFOTable->chNum;
psFreeFIFOTable->startAdrs = allocEndAdrs;
psFreeFIFOTable->endAdrs = psFIFOTable->endAdrs;
psFreeFIFOTable->type = psFIFOTable->type;
USBH_HCDS_ListAdd(&(psFreeFIFOTable->sList), psFIFOList);
}
if( psFIFOTable->startAdrs < allocStartAdrs ){
/* Hold the empty area */
psFIFOTable->endAdrs = allocStartAdrs;
} else {
psFIFOTable->chNum = psFIFOInfo->chNum;
psFIFOTable->startAdrs = allocStartAdrs;
psFIFOTable->endAdrs = allocEndAdrs;
psFIFOTable->type = psFIFOInfo->type;
}
FIFOStatus.endFIFOTable = endFIFOTable;
return STATUS_SUCCESS;
}
/*=============================================================================================
// Function_Name: USBH_HCDS_FIFOFree
//
// description : Free of FIFO area
//
// The FIFO area allocated in the specified channel is freed
//
// argument : chNum (in)Channel number
//
// return : STATUS_SUCCESS Processing completed successfully
===============================================================================================*/
long USBH_HCDS_FIFOFree( unsigned char chNum )
{
FIFO_TABLE *psFIFOTable, *psPrevFIFOTable, *psNextFIFOTable;
USBH_HCD_LIST_HEAD *psFIFOList;
unsigned int i;
psFIFOList = &(FIFOStatus.sFIFOTableList);
for( i = 0; ; i++ ){
psFIFOTable = USBH_HCDS_ListEntry(psFIFOList->psNext, FIFO_TABLE, sList);
if( psFIFOTable->chNum == chNum ){
/* There is an area of the specified channel number */
psFIFOTable->chNum = NOT_USED_CH_NUM;
psFIFOTable->type = TYPE_UNKNOWN;
/* Free the FIFO area */
USBH_HCDS_HCFIFOFree(chNum);
if( FIFOStatus.endFIFOTable > 0 ){
/* case of the FIFO table exists behind */
psNextFIFOTable = USBH_HCDS_ListEntry(psFIFOTable->sList.psNext, FIFO_TABLE, sList);
if( psNextFIFOTable->chNum == NOT_USED_CH_NUM ){
/* Uniting when FIFO table indicate empty area behind*/
psFIFOTable->endAdrs = psNextFIFOTable->endAdrs;
USBH_HCDS_ListDel(&(psNextFIFOTable->sList));
FIFOStatus.endFIFOTable--;
USBH_HCDS_ListAddTail(&(psNextFIFOTable->sList), &FIFOStatus.sFreeFIFOTableList);
}
}
if( (i != 0) && (FIFOStatus.endFIFOTable > 0) ){
/* Except the first FIFO area */
psPrevFIFOTable = USBH_HCDS_ListEntry(psFIFOTable->sList.psPrev, FIFO_TABLE, sList);
if( psPrevFIFOTable->chNum == NOT_USED_CH_NUM ){
/* Uniting when the FIFO table indicate empty area previous*/
psPrevFIFOTable->endAdrs = psFIFOTable->endAdrs;
USBH_HCDS_ListDel(&(psFIFOTable->sList));
FIFOStatus.endFIFOTable--;
USBH_HCDS_ListAddTail(&(psFIFOTable->sList), &FIFOStatus.sFreeFIFOTableList);
}
}
break;
}
if( i == FIFOStatus.endFIFOTable ){
/* Checked the FIFO table to the end*/
break;
}
psFIFOList = psFIFOList->psNext;
}
return STATUS_SUCCESS;
}
/*=============================================================================================
// Function_Name: SearchFIFOArea
//
// description : Search the specified FIFO area
//
// Search the specified FIFO area, and return the pointer of FIFO table
//
// argument : portState (in)State of port to set
//
// return : STATUS_SUCCESS Processing completed successfully
// STATUS_UNSUCCESSFUL Failed to allocate the FIFO area
===============================================================================================*/
Inline FIFO_TABLE *SearchFIFOArea( long *retValue, unsigned long *allocStartAdrs, unsigned char area, USBH_HCD_LIST_HEAD *psFIFOList,
unsigned long searchStartAdrs, unsigned long searchEndAdrs, unsigned long allocSize )
{
FIFO_TABLE *psFIFOTable;
unsigned long startAdrs, endAdrs;
unsigned int i;
if( area == EMPTY_AREA ){
for( i = 0; ; i++ ){
psFIFOTable = USBH_HCDS_ListEntry(psFIFOList->psNext, FIFO_TABLE, sList);
if( psFIFOTable->chNum == NOT_USED_CH_NUM ){
/* Not used FIFO area be found */
startAdrs = psFIFOTable->startAdrs;
endAdrs = psFIFOTable->endAdrs;
if( startAdrs <= searchStartAdrs && endAdrs >= searchEndAdrs ){
/* The specified range exists in a not used area */
*allocStartAdrs = searchStartAdrs;
break;
} else if( searchStartAdrs <= startAdrs ){
/* An empty area exists within the specified range */
if( searchEndAdrs >= (startAdrs + allocSize) ){
if( (endAdrs - startAdrs) >= allocSize ){
/* There is required size in a not used area */
*allocStartAdrs = startAdrs;
break;
}
}
} else if( searchEndAdrs >= endAdrs ){
/* The specified range lapped over a not used area */
if( (endAdrs - searchStartAdrs) >= allocSize ){
/* There is required size in a not used area */
*allocStartAdrs = searchStartAdrs;
break;
}
}
}
if( i == FIFOStatus.endFIFOTable ){
/* Checked the FIFO table to the end */
*retValue = STATUS_MEM_ERROR;
return NULL;
}
psFIFOList = psFIFOList->psNext;
}
} else {
for( i = 0; ; i++ ){
psFIFOTable = USBH_HCDS_ListEntry(psFIFOList->psNext, FIFO_TABLE, sList);
startAdrs = psFIFOTable->startAdrs;
if( searchStartAdrs <= startAdrs ){
/* The specified range is used */
if( psFIFOTable->type == USBH_HCDS_FIFO_TYPE_BULK ){
*retValue = STATUS_CANNOT_SETUP;
return NULL;
}
}
if( i == FIFOStatus.endFIFOTable ){
/* Checked the FIFO table to the end */
*retValue = STATUS_MEM_ERROR;
return NULL;
}
psFIFOList = psFIFOList->psNext;
}
}
*retValue = STATUS_SUCCESS;
return psFIFOTable;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -