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

📄 hspdif.c

📁 WinCE5.0BSP for Renesas SH7770
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// Copyright(C) Renesas Technology Corp. 2002-2004. All rights reserved.
//
// HSPDIF Driver for ITS-DS7
//
// FILE      : HSPDIF.C
// CREATED   : 2002.06.26
// MODIFIED  : 2004.09.01
// AUTHOR    : Renesas Technology Corp.
// HARDWARE  : RENESAS ITS-DS7
// HISTORY   : 
//             2003.06.20
//              - Created release code.
//                (based on HSPDIF driver for ITS-DS4 Ver.1.4.0 for WCEfA3.5)
//             2003.12.03
//              - The common DMA code is used.
//             2003.12.25
//              - Revised recording DMA initialize.
//             2004.09.01
//              - Created release code for WCE5.0.
//

#define WINCEMACRO 1
#include <windows.h>
#include <oalintr.h>
#include <excpt.h>
#include "platform.h"
#include "drv_glob.h"
#include "sh7770.h"
#include "hspdif.h"
#include "hspdifdbg.h"
#include "ioctl_its_ds7.h"

/* Operate the row of bits */
BITS_CONVERSION	ConvBitsTx20[] = {
{0xfffff000, 12, SHIFT_R, INC_DST},{0x00000fff,  8, SHIFT_L, INC_SRC},
{0xff000000, 24, SHIFT_R, INC_DST},{0x00fffff0,  4, SHIFT_R, INC_DST},
{0x0000000f, 16, SHIFT_L, INC_SRC},{0xffff0000, 16, SHIFT_R, INC_DST},
{0x0000ffff,  4, SHIFT_L, INC_SRC},{0xf0000000, 28, SHIFT_R, INC_DST},
{0x0fffff00,  8, SHIFT_R, INC_DST},{0x000000ff, 12, SHIFT_L, INC_SRC},
{0xfff00000, 20, SHIFT_R, INC_DST},{0x000fffff,  0, SHIFT_N, INC_SRC|INC_DST}};
BITS_CONVERSION	ConvBitsTx24[] = {
{0xffffff00,  8, SHIFT_R, INC_DST},{0x000000ff, 16, SHIFT_L, INC_SRC},
{0xffff0000, 16, SHIFT_R, INC_DST},{0x0000ffff,  8, SHIFT_L, INC_SRC},
{0xff000000, 24, SHIFT_R, INC_DST},{0x00ffffff,  0, SHIFT_N, INC_DST|INC_SRC}};

BITS_CONVERSION	ConvBitsRx20[] = {
{0x000fffff, 12, SHIFT_L, INC_SRC},{0x000fff00,  8, SHIFT_R, INC_DST},
{0x000000ff, 24, SHIFT_L, INC_SRC},{0x000fffff,  4, SHIFT_L, INC_SRC},
{0x000f0000, 16, SHIFT_R, INC_DST},{0x0000ffff, 16, SHIFT_L, INC_SRC},
{0x000ffff0,  4, SHIFT_R, INC_DST},{0x0000000f, 28, SHIFT_L, INC_SRC},
{0x000fffff,  8, SHIFT_L, INC_SRC},{0x000ff000, 12, SHIFT_R, INC_DST},
{0x00000fff, 20, SHIFT_L, INC_SRC},{0x000fffff,  0, SHIFT_N, INC_SRC|INC_DST}};
BITS_CONVERSION	ConvBitsRx24[] = {
{0x00ffffff,  8, SHIFT_L, INC_SRC},{0x00ff0000, 16, SHIFT_R, INC_DST},
{0x0000ffff, 16, SHIFT_L, INC_SRC},{0x00ffff00,  8, SHIFT_R, INC_DST},
{0x000000ff, 24, SHIFT_L, INC_SRC},{0x00ffffff,  0, SHIFT_N, INC_SRC|INC_DST}};



/*++

DLLEntry :

This function is entry of DLL.

--*/
BOOL __stdcall
DllEntry(
	HINSTANCE	hinstDll,			// @param Instance pointer.
	DWORD		dwReason,			// @param Reason routine is called.
	LPVOID		lpReserved			// @param system parameter.
	)
{
	switch( dwReason ){
		case DLL_PROCESS_ATTACH :
			DEBUGREGISTER( hinstDll );
			break;
		case DLL_PROCESS_DETACH :
			break;
		default :
			break;
	}
	return TRUE;
}

/*++

SPD_Init :

This initializes SPDIF module and assigns the domain of a driver.

--*/
HANDLE
SPD_Init(
	DWORD	dwContext
	)
{
PSPDIF_DRIVER_INFO	pSpdif;
//DWORD dwRet;
HANDLE hThread;

	// The common area for drivers is acquired.
	pSpdif = (PSPDIF_DRIVER_INFO)VirtualAlloc(NULL, sizeof(SPDIF_DRIVER_INFO), MEM_COMMIT, PAGE_READWRITE);
	if ( pSpdif == NULL ){
		goto error_return;
	}
	pSpdif -> pvRegBase = (PVBYTE)VirtualAlloc(0, SPDIF_REGSIZE, MEM_RESERVE, PAGE_NOACCESS);
	if ( pSpdif -> pvRegBase == NULL ){
		goto error_return;
	}
	if ( !VirtualCopy((PVOID)pSpdif -> pvRegBase,
					(PVOID)SPDIF_REGBASE,
					SPDIF_REGSIZE,
					PAGE_READWRITE|PAGE_NOCACHE) ){
		goto error_return;
	}

	// The register of SPDIF is assigned.
	pSpdif -> pvControl = (PVULONG)(pSpdif -> pvRegBase+SPDIF_CTRL_OFFSET);
	pSpdif -> pvStatus = (PVULONG)(pSpdif -> pvRegBase+SPDIF_STAT_OFFSET);

	pSpdif -> pvGlobal = (PSPDIF_GLOBAL)VirtualAlloc(NULL, SPDIF_GLOBAL_SIZE, MEM_RESERVE, PAGE_NOACCESS);
	if ( pSpdif -> pvGlobal == NULL ){
		goto error_return;
	}
	if ( !VirtualCopy((PVOID)pSpdif -> pvGlobal,
				(PVOID)SPDIF_GLOBAL_BASE,
				SPDIF_GLOBAL_SIZE,
				PAGE_READWRITE|PAGE_NOCACHE) ){
		goto error_return;
	}
	pSpdif->pvGlobal -> dwTxStatus = 0;
	pSpdif->pvGlobal -> dwRxStatus = 0;


	pSpdif -> hInterrupt = CreateEvent(NULL, FALSE, FALSE, NULL);
	if ( !InterruptInitialize(SYSINTR_HSPDIF, pSpdif -> hInterrupt, NULL, 0) ){
		goto error_return;
	}
	hThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0,
					(LPTHREAD_START_ROUTINE)SPDIFInterruptThread,
					(PVOID)pSpdif, 0, NULL);
	if ( hThread == NULL ){
		goto error_return;
	}
	SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);

	return pSpdif;

error_return:
	if ( pSpdif -> pvRegBase != NULL ){
		VirtualFree((PVOID)(pSpdif -> pvRegBase), SPDIF_REGSIZE, MEM_RELEASE);
	}
	if ( pSpdif -> pvGlobal != NULL ){
		VirtualFree((PVOID)(pSpdif -> pvGlobal), SPDIF_GLOBAL_SIZE, MEM_RELEASE);
	}
	if ( pSpdif != NULL ){
		VirtualFree((PVOID)pSpdif, sizeof(SPDIF_DRIVER_INFO), MEM_DECOMMIT);
	}
	return NULL;
}

/*++

SPD_Deinit :

The resources of a driver are released.

--*/
BOOL
SPD_Deinit(
	PSPDIF_DRIVER_INFO	pSpdif
	)
{
//DWORD dwRet;

	if ( pSpdif -> pvRegBase != NULL ){
		VirtualFree((PVOID)(pSpdif -> pvRegBase), SPDIF_REGSIZE, MEM_RELEASE);
	}
	if ( pSpdif -> pvGlobal != NULL ){
		VirtualFree((PVOID)(pSpdif -> pvGlobal), SPDIF_GLOBAL_SIZE, MEM_RELEASE);
	}
	if ( pSpdif != NULL ){
		VirtualFree(pSpdif, sizeof(SPDIF_DRIVER_INFO), MEM_DECOMMIT);
	}


	return TRUE;
}

/*++

SPD_Open

This function is specified in the attribute of Read or Write,
and processes the case where a driver is started from application.
This driver does processing according to the specified attribute.

--*/
HANDLE
SPD_Open(
	DWORD	dwData,
	DWORD	dwAccess,
	DWORD	dwShareMode
	)
{
PSPDIF_DRIVER_INFO	pSpdif = (PSPDIF_DRIVER_INFO)dwData;
PSPDIF_OPEN_INFO	pOpen=(PSPDIF_OPEN_INFO)0;
HANDLE	hThread;

	if ( (dwAccess & (GENERIC_READ|GENERIC_WRITE)) & pSpdif -> dwAccessOwner ){
		DEBUGMSG(SPDIF_ERROR, (TEXT("SPDIF : Invalid access\r\n")));
		goto error_return;
	}
	pSpdif -> dwAccessOwner |= (dwAccess&(GENERIC_READ|GENERIC_WRITE));

	pOpen = LocalAlloc(LPTR, sizeof(SPDIF_OPEN_INFO));
	if ( !pOpen ){
		goto error_return;
	}
	pOpen -> pInfo = pSpdif;
	pOpen -> dwAccess = dwAccess;
	pOpen -> dwShareMode = dwShareMode;

	if ( dwAccess & GENERIC_WRITE ){

		dma_Init(CH_TX_HSPDIF, &pOpen->pTxDma);

		dma_SetPort(pOpen->pTxDma, DPTR_DDPT_HSPDIF);

		dma_SetPage(pOpen->pTxDma,
							0,										// Page No. 0
							SPDIF_OUT_BUFFER_BASE,					// Src address
							SPDIF_REGBASE+SPDIF_TDAD_OFFSET,		// Dst address
							(DWORD)(SPDIF_OUT_DMA_PAGE_SIZE>>2));	// Buf size

		dma_SetPage(pOpen->pTxDma,
							1,										// Page No. 0
																	// Src address
							SPDIF_OUT_BUFFER_BASE+SPDIF_OUT_DMA_PAGE_SIZE,
							SPDIF_REGBASE+SPDIF_TDAD_OFFSET,		// Dst address
							(DWORD)(SPDIF_OUT_DMA_PAGE_SIZE>>2));	// Buf size

		pSpdif -> hTxEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
		if ( pSpdif -> hTxEvent == NULL ){
			goto error_return;
		}

		pOpen -> hTxWaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
		if ( pOpen -> hTxWaitEvent == NULL ){
			goto error_return;
		}

		pOpen -> pvOutBufferBase = VirtualAlloc(NULL, SPDIF_OUT_DMA_PAGE_SIZE<<1, MEM_RESERVE, PAGE_NOACCESS);
		if ( pOpen -> pvOutBufferBase == NULL ){
			goto error_return;
		}
		if ( !VirtualCopy((PVOID)pOpen -> pvOutBufferBase,
					(PVOID)SPDIF_OUT_BUFFER_BASE,
					SPDIF_OUT_DMA_PAGE_SIZE<<1,
					PAGE_READWRITE|PAGE_NOCACHE) ){
			goto error_return;
		}

		pOpen -> pvOutWorkBuffer = VirtualAlloc(NULL, SPDIF_WORK_OBUFFER_SIZE, MEM_RESERVE, PAGE_NOACCESS);
		if ( pOpen -> pvOutWorkBuffer == NULL ){
			goto error_return;
		}
		if ( !VirtualCopy((PVOID)pOpen -> pvOutWorkBuffer,
				(PVOID)(SPDIF_WORK_OBUFFER_BASE),
				SPDIF_WORK_OBUFFER_SIZE,
				PAGE_READWRITE|PAGE_NOCACHE) ){
			goto error_return;
		}
		pOpen -> dwOutWorkWPtr = 0;
		pOpen -> dwOutWorkTPtr = 0;

		pOpen -> bTxThread = TRUE;

		hThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0,
						(LPTHREAD_START_ROUTINE)SPDIFInterruptThreadTx,
						(PVOID)pOpen, 0, NULL);
		if ( hThread == NULL ){
			goto error_return;
		}
		SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);

		InitializeCriticalSection( &(pOpen -> TxCS) );
	}
	if ( dwAccess & GENERIC_READ ){

		dma_Init(CH_RX_HSPDIF, &pOpen->pRxDma);

		dma_SetPort(pOpen->pRxDma, DPTR_SDPT_HSPDIF);

		dma_SetPage(pOpen->pRxDma,
							0,										// Page No. 0
							SPDIF_REGBASE+SPDIF_RDAD_OFFSET,		// Src address
							SPDIF_IN_BUFFER_BASE,					// Dst address
							(DWORD)(SPDIF_IN_DMA_PAGE_SIZE>>2));	// Buf size

		dma_SetPage(pOpen->pRxDma,
							1,										// Page No. 0
							SPDIF_REGBASE+SPDIF_RDAD_OFFSET,		// Src address
																	// Dst address
							SPDIF_IN_BUFFER_BASE+SPDIF_IN_DMA_PAGE_SIZE,
							(DWORD)(SPDIF_IN_DMA_PAGE_SIZE>>2));	// Buf size

		pSpdif -> hRxEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
		if ( pSpdif -> hRxEvent == NULL ){
			goto error_return;
		}

		pOpen -> hRxWaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
		if ( pOpen -> hRxWaitEvent == NULL ){
			goto error_return;
		}

		pOpen -> pvInBufferBase = VirtualAlloc(NULL, SPDIF_IN_DMA_PAGE_SIZE<<1, MEM_RESERVE, PAGE_NOACCESS);
		if ( pOpen -> pvInBufferBase == NULL ){
			goto error_return;
		}
		if ( !VirtualCopy((PVOID)pOpen -> pvInBufferBase,
					(PVOID)SPDIF_IN_BUFFER_BASE,
					SPDIF_IN_DMA_PAGE_SIZE<<1,
					PAGE_READWRITE|PAGE_NOCACHE) ){
			goto error_return;
		}

		pOpen -> pvInWorkBuffer = VirtualAlloc(NULL, SPDIF_WORK_IBUFFER_SIZE, MEM_RESERVE, PAGE_NOACCESS);
		if ( pOpen -> pvInWorkBuffer == NULL ){
			goto error_return;
		}
		if ( !VirtualCopy((PVOID)pOpen -> pvInWorkBuffer,
				(PVOID)(SPDIF_WORK_IBUFFER_BASE),
				SPDIF_WORK_IBUFFER_SIZE,
				PAGE_READWRITE|PAGE_NOCACHE) ){
			goto error_return;
		}
		pOpen -> dwInWorkWPtr = 0;
		pOpen -> dwInWorkRPtr = 0;

		pOpen -> bRxThread = TRUE;

		hThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0,
						(LPTHREAD_START_ROUTINE)SPDIFInterruptThreadRx,
						(PVOID)pOpen, 0, NULL);
		if ( hThread == NULL ){
			goto error_return;
		}
		SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);

		InitializeCriticalSection( &(pOpen -> RxCS) );
	}

	return pOpen;

error_return:
	if ( pOpen ){

		if(pOpen->pTxDma)
			dma_Deinit(pOpen->pTxDma);

		if(pOpen->pTxDma)
			dma_Deinit(pOpen->pRxDma);

		SPD_Close(pOpen);
	}
	return NULL;
}

/*++

SPD_Close :

The resources gained by the SPD_Init function are released.

--*/
BOOL
SPD_Close(
	PSPDIF_OPEN_INFO	pOpen
	)
{
PSPDIF_DRIVER_INFO	pSpdif = pOpen -> pInfo;

	if ( pOpen -> dwAccess & GENERIC_WRITE ){
		StopTransmitting(pOpen);
		pOpen -> bTxThread = FALSE;

		SetEvent(pSpdif -> hTxEvent);

		if ( pOpen -> pvOutBufferBase ){
			VirtualFree((PVOID)pOpen -> pvOutBufferBase, SPDIF_OUT_DMA_PAGE_SIZE<<1, MEM_RELEASE);
		}
		if ( pOpen -> pvOutWorkBuffer ){
			VirtualFree((PVOID)pOpen -> pvOutWorkBuffer, SPDIF_WORK_OBUFFER_SIZE, MEM_RELEASE);
		}

		dma_Deinit(pOpen->pTxDma);

		if ( pSpdif -> hTxEvent ){
			CloseHandle(pSpdif-> hTxEvent);
		}
		if ( pOpen -> hTxWaitEvent ){
			CloseHandle(pOpen -> hTxWaitEvent);
		}
	}
	if ( pOpen -> dwAccess & GENERIC_READ ){
		StopReceiving(pOpen);
		pOpen -> bRxThread = FALSE;

		SetEvent(pSpdif -> hRxEvent);

		if ( pOpen -> pvInBufferBase ){
			VirtualFree((PVOID)pOpen -> pvInBufferBase, SPDIF_IN_DMA_PAGE_SIZE<<1, MEM_RELEASE);
		}
		if ( pOpen -> pvInWorkBuffer ){
			VirtualFree((PVOID)pOpen -> pvInWorkBuffer, SPDIF_WORK_IBUFFER_SIZE, MEM_RELEASE);
		}

		dma_Deinit(pOpen->pRxDma);

		if ( pSpdif -> hRxEvent ){
			CloseHandle(pSpdif -> hRxEvent);
		}
		if ( pOpen -> hRxWaitEvent ){
			CloseHandle(pOpen -> hRxWaitEvent);
		}
	}
	pSpdif -> dwAccessOwner &= ~pOpen -> dwAccess;
	LocalFree(pOpen);
	return TRUE;
}

// The following function groups do not use.
DWORD SPD_Read(DWORD Handle, LPVOID pBuffer, DWORD dwNumBytes){return 0;}
DWORD SPD_Write(DWORD Handle, LPCVOID pBuffer, DWORD dwNumBytes){return 0;}
DWORD SPD_Seek(DWORD Handle, long lDistance, DWORD dwMoveMethod){return 0;}
void SPD_PowerUp(PVOID p)
{
}
void SPD_PowerDown(PVOID p)
{
}

/*++

SPD_IOControl :



--*/
BOOL
SPD_IOControl(
	DWORD	dwHandle,
	DWORD	dwCode,
	PVOID	pBufIn,
	DWORD	dwLenIn,
	PVOID	pBufOut,
	DWORD	dwLenOut,
	PDWORD	pdwActualOut
	)
{
	*pdwActualOut = 0;
	switch( dwCode ){
		case IOCTL_SPDIF_TRANSMITTING_DATA:
			*pdwActualOut = SPDIF_TransmittingData((PSPDIF_OPEN_INFO)dwHandle, pBufIn, dwLenIn);
			break;
		case IOCTL_SPDIF_RECEIVING_DATA:
			*pdwActualOut = SPDIF_ReceivingData((PSPDIF_OPEN_INFO)dwHandle, pBufOut, dwLenOut);
			break;
		case IOCTL_SPDIF_STOP_TRANSMIT:
			SPDIF_StopTransmit((PSPDIF_OPEN_INFO)dwHandle);
			break;
		case IOCTL_SPDIF_STOP_RECEIVE:
			SPDIF_StopReceive((PSPDIF_OPEN_INFO)dwHandle);
			break;
		case IOCTL_SPDIF_SET_TXSAMPLE_SIZE:
			if ( *((PDWORD)pBufIn) > SPDIF_SAMPLE_BIT_SIZE_24 ){
				*pdwActualOut = 0xffffffff;
			}else{
				((PSPDIF_OPEN_INFO)dwHandle) -> dwTxSampleSize = *((PDWORD)pBufIn);
			}
			break;
		case IOCTL_SPDIF_GET_TXSAMPLE_SIZE:
			*((PDWORD)pBufOut) = ((PSPDIF_OPEN_INFO)dwHandle) -> dwTxSampleSize;
			break;
		case IOCTL_SPDIF_SET_RXSAMPLE_SIZE:
			if ( *((PDWORD)pBufIn) > SPDIF_SAMPLE_BIT_SIZE_24 ){
				*pdwActualOut = 0xffffffff;
			}else{
				((PSPDIF_OPEN_INFO)dwHandle) -> dwRxSampleSize = *((PDWORD)pBufIn);
			}
			break;
		case IOCTL_SPDIF_GET_RXSAMPLE_SIZE:
			*((PDWORD)pBufOut) = ((PSPDIF_OPEN_INFO)dwHandle) -> dwRxSampleSize;
			break;
		default :
			return FALSE;
	}
	return TRUE;
}


/*++

SPDIF_TransmittingData :

Perform data transmission.
When transmitting for the first time, start DMA and SPDIF.

--*/
DWORD
SPDIF_TransmittingData(
	PSPDIF_OPEN_INFO pOpen,
	PVOID pBuff,
	DWORD dwSize
	)
{
DWORD	dwLoop = 0;
DWORD	dwWritten;
DWORD	dwValue;

	if ( !(pOpen -> dwAccess & GENERIC_WRITE) ){
		return 0;
	}

	dwWritten = FillWorkBuffer(pOpen, pBuff, dwSize);

	if ( !(pOpen -> pInfo -> dwStatus & SPDIF_TRANSMITTING) ){
		SPDIFControlRegister cr;

		DEBUGMSG(SPDIF_TEST, (TEXT("SPDIF:Start transmission processing.\r\n")));
		pOpen -> dwTxShiftPtr = 0;
		pOpen -> dwTxWork = 0;
		pOpen -> dwTxFlipBuff = 0;
		if ( pOpen -> dwTxSampleSize == SPDIF_SAMPLE_BIT_SIZE_20 ){
			pOpen -> TxBits = &ConvBitsTx20[0];
		}else if ( pOpen -> dwTxSampleSize == SPDIF_SAMPLE_BIT_SIZE_24 ){
			pOpen -> TxBits = &ConvBitsTx24[0];
		}
		if ( SPDIF_FillBuffer( pOpen ) == TRUE ){
			SPDIF_FillBuffer( pOpen );
		}

		// DMA Control Register Setting

		dwValue		=	DCR_DTAMD_PIN		|
						DCR_DTAC_DISABLE	|
						DCR_DTAU_BYTE		|
						DCR_BTMD_DISABLE	|
						DCR_PKMD_DISABLE	|
						DCR_CT_ENABLE		|
						DCR_ACMD_ENABLE		|
						DCR_DIP_2PAGE		|
						DCR_SMDL_MEMORY		|
						DCR_SPDAM_INCREMENT	|
						DCR_SDRMD_MODULE	|
						DCR_SPDS_32BIT		|
						DCR_DMDL_PERIPHERAL	|
						DCR_DPDAM_FIX		|
						DCR_DDRMD_MODULE	|
						DCR_DPDS_32BIT		;

		dma_SetControl(pOpen->pTxDma, dwValue);

		// DMA-TransferCompleteInterrupt Enable

		dma_InterruptEnable(pOpen->pTxDma);

		cr.AsDWORD = READ_REGISTER_ULONG(pOpen -> pInfo -> pvControl);
		cr.bits.AOS  = 1; // Audio only samples
//		cr.bits.NCSI = 1; // New channel status information
		cr.bits.TME  = 1; // Transmitter module enable
		cr.bits.TDE  = 1; // Transmitter dma enable
		cr.bits.TASS = pOpen -> dwTxSampleSize; // Transmitter audio samlple bit size
		WRITE_REGISTER_ULONG(pOpen -> pInfo -> pvControl, cr.AsDWORD);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -