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

📄 usbh_hcds_fifo.c

📁 epson usb2.0 控制芯片 S1R72V05 固件程序。
💻 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 + -