?? hspdif.c
字號(hào):
//
// 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);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -