📄 scif0.c
字号:
//
// Copyright(C) Renesas Technology Corp. 1999-2004. All rights reserved.
//
// Serial(SCIF0) driver for ITS-DS7
//
// FILE : scif0.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 Serial driver for
// ITS-DS4 Source Kit Ver.1.2.0 for WCE 4.2)
// 2003.11.25
// - Transmitting processing was changed into exclusion
// - Changed for corresponding to COM_MDD2.
// - Bug fixed. (fail,etc in CETK)
// 2004.09.01
// - Created release code for WCE5.0.
//
#include <windows.h>
#include <types.h>
#include <ceddk.h>
#include <memory.h>
#include <notify.h>
#include <serhw.h>
#include <nkintr.h>
#include <oalintr.h>
#include <devload.h>
#include <windev.h>
#undef ZONE_INIT
#include <serdbg.h>
#include <celog.h>
#include <its_ds7.h>
#include <drv_glob.h>
#include <sh7770.h>
#include "..\inc\scif.h"
#define RX_FLOW_CONTROL 1
extern BOOL SCIF_PostInit(
PVOID pHead // @parm PVOID returned by SerInit.
);
// Miscellaneous internal routines. (scif_cmn.c)
extern PUCHAR Ser_InternalMapRegisterAddresses(
ULONG HWAddress,
ULONG Size );
extern const HW_VTBL SCIF3IoVTbl;
/*
@doc OEM
@func PVOID | SerInit | Initializes device identified by argument.
* This routine sets information controlled by the user
* such as Line control and baud rate. It can also initialize events and
* interrupts, thereby indirectly managing initializing hardware buffers.
* Exported only to driver, called only once per process.
*
@rdesc The return value is a PVOID to be passed back into the HW
dependent layer when HW functions are called.
*/
static
PVOID
SCIF0Init(
ULONG Identifier, // @parm Device identifier.
PVOID pMddHead, // @parm First argument to mdd callbacks.
PHWOBJ pHWObj // @parm Pointer to our own HW OBJ for this device
)
{
PSCIF_INFO pHWHead;
// Allocate for our main data structure and one of it's fields.
pHWHead = (PSCIF_INFO)LocalAlloc( LMEM_ZEROINIT|LMEM_FIXED , sizeof(SCIF_INFO) );
if ( !pHWHead )
goto ALLOCFAILED;
if ( ! Ser_GetRegistryData(pHWHead, (LPCTSTR)Identifier) ) {
DEBUGMSG (ZONE_INIT|ZONE_ERROR,
(TEXT("SCIF0Init - Unable to read registry data. Failing Init !!! \r\n")));
goto ALLOCFAILED;
}
// This call will map the address space for the 16550 UART.
if ( !(pHWHead->pBaseAddress = Ser_InternalMapRegisterAddresses(
SCIF0_REGBASE, SCIF0_REGSIZE )) )
goto ALLOCFAILED;
pHWHead -> pSMR = (volatile USHORT *)((PVBYTE)pHWHead -> pBaseAddress + SCIF_SCSMR_OFFSET);
pHWHead -> pBRR = (volatile BYTE *)((PVBYTE)pHWHead -> pBaseAddress + SCIF_SCBRR_OFFSET);
pHWHead -> pSCR = (volatile USHORT *)((PVBYTE)pHWHead -> pBaseAddress + SCIF_SCSCR_OFFSET);
pHWHead -> pFTDR = (volatile BYTE *)((PVBYTE)pHWHead -> pBaseAddress + SCIF_SCFTDR_OFFSET);
pHWHead -> pFSR = (volatile USHORT *)((PVBYTE)pHWHead -> pBaseAddress + SCIF_SCFSR_OFFSET);
pHWHead -> pFRDR = (volatile BYTE *)((PVBYTE)pHWHead -> pBaseAddress + SCIF_SCFRDR_OFFSET);
pHWHead -> pFCR = (volatile USHORT *)((PVBYTE)pHWHead -> pBaseAddress + SCIF_SCFCR_OFFSET);
pHWHead -> pFDR = (volatile USHORT *)((PVBYTE)pHWHead -> pBaseAddress + SCIF_SCFDR_OFFSET);
pHWHead -> pSPTR = (volatile USHORT *)((PVBYTE)pHWHead -> pBaseAddress + SCIF_SCSPTR_OFFSET);
pHWHead -> pLSR = (volatile USHORT *)((PVBYTE)pHWHead -> pBaseAddress + SCIF_SCLSR_OFFSET);
pHWHead -> pBRGDL = (volatile USHORT *)((PVBYTE)pHWHead -> pBaseAddress + SCIF_BRG_DL);
pHWHead -> pBRGCKS = (volatile USHORT *)((PVBYTE)pHWHead -> pBaseAddress + SCIF_BRG_CKS);
pHWHead -> EventCallback = (EVENT_FUNC)EvaluateEventFlag;
pHWHead -> pMddHead = pMddHead;
pHWHead -> pHWObj = pHWObj;
pHWHead -> OpenCount = 0;
// Set up our Comm Properties data
pHWHead->CommProp.wPacketLength = 0xffff;
pHWHead->CommProp.wPacketVersion = 0xffff;
pHWHead->CommProp.dwServiceMask = SP_SERIALCOMM;
pHWHead->CommProp.dwReserved1 = 0;
pHWHead->CommProp.dwMaxTxQueue = 16;
pHWHead->CommProp.dwMaxRxQueue = 16;
pHWHead->CommProp.dwMaxBaud = BAUD_115200;
pHWHead->CommProp.dwProvSubType = PST_RS232;
pHWHead->CommProp.dwProvCapabilities = PCF_RTSCTS |
PCF_SETXCHAR |
PCF_INTTIMEOUTS |
PCF_PARITY_CHECK |
PCF_SPECIALCHARS |
PCF_TOTALTIMEOUTS |
PCF_XONXOFF;
pHWHead->CommProp.dwSettableBaud = BAUD_110 |
BAUD_300 |
BAUD_600 |
BAUD_1200 |
BAUD_2400 |
BAUD_4800 |
BAUD_9600 |
BAUD_19200 |
BAUD_38400 |
BAUD_57600 |
BAUD_115200 ;
pHWHead->CommProp.dwSettableParams = SP_BAUD |
SP_DATABITS |
SP_HANDSHAKING |
SP_PARITY |
SP_PARITY_CHECK |
SP_STOPBITS;
pHWHead->CommProp.wSettableData = DATABITS_7 |
DATABITS_8;
pHWHead->CommProp.wSettableStopParity = STOPBITS_10 |
STOPBITS_20 |
PARITY_NONE |
PARITY_ODD |
PARITY_EVEN;
if ( !(pHWHead -> FlushDone = CreateEvent(0, FALSE, FALSE, NULL)) )
goto ALLOCFAILED;
if ( !(pHWHead -> pTxBuff = (PBYTE)Ser_InternalMapRegisterAddresses
( SCIF0_TX_BUFFER_BASE, SCIF0_TXBUFFER_SIZE )) )
goto ALLOCFAILED;
if ( !(pHWHead -> pRxBuff = (PBYTE)Ser_InternalMapRegisterAddresses
( SCIF0_RX_BUFFER_BASE, SCIF0_RXBUFFER_SIZE * 2 )) )
goto ALLOCFAILED;
if ( !dma_Init(CH_TX_SCIF0, &(pHWHead -> pTxDma)) )
goto ALLOCFAILED;
if ( !dma_Init(CH_RX_SCIF0, &(pHWHead -> pRxDma)) )
goto ALLOCFAILED;
pHWHead -> ulRxDmaRegBase = SCIF0_REGBASE + SCIF_SCFRDR_OFFSET;
pHWHead -> ulRxDmaBuffBase1 = SCIF0_RX_BUFFER_BASE;
pHWHead -> ulRxDmaBuffBase2 = SCIF0_RX_BUFFER_BASE + SCIF0_RXBUFFER_SIZE;
pHWHead -> ulRxDmaBuffSize = SCIF0_RXBUFFER_SIZE;
pHWHead -> dwRxDmaPort = DPTR_SDPT_SCIF0;
pHWHead -> bFirstBaudRate = FALSE;
InitializeCriticalSection(&(pHWHead->TransmitCritSec));
InitializeCriticalSection(&(pHWHead->RegCritSec));
pHWHead->PowerDown = FALSE;
pHWHead->bSuspendResume = FALSE;
DEBUGMSG (ZONE_INIT,
(TEXT("SCIF_Init - Disabling UART Power\r\n")));
pHWHead->fIRMode = FALSE; // Select wired by default
DEBUGMSG(ZONE_INIT, (TEXT("Revision %08x \r\n"), (ULONG)READ_REGISTER_USHORT(pHWHead -> pSMR) ));
DEBUGMSG(ZONE_INIT, (TEXT("%08x \r\n"), (ULONG)READ_REGISTER_UCHAR(pHWHead -> pBRR) ));
DEBUGMSG(ZONE_INIT, (TEXT("%08x \r\n"), (ULONG)READ_REGISTER_USHORT(pHWHead -> pSCR) ));
DEBUGMSG(ZONE_INIT, (TEXT("%08x \r\n"), (ULONG)READ_REGISTER_UCHAR( pHWHead -> pFTDR ) ));
// RETAILMSG(1, (TEXT("%08x \r\n"), (ULONG)READ_REGISTER_ULONG(pHWHead -> pFSR) ));
// RETAILMSG(1, (TEXT("%08x \r\n"), (ULONG)READ_REGISTER_ULONG(pHWHead -> pFRDR) ));
// RETAILMSG(1, (TEXT("%08x \r\n"), (ULONG)READ_REGISTER_ULONG(pHWHead -> pFCR) ));
// RETAILMSG(1, (TEXT("%08x \r\n"), (ULONG)READ_REGISTER_ULONG(pHWHead -> pFDR) ));
// RETAILMSG(1, (TEXT("%08x \r\n"), (ULONG)READ_REGISTER_ULONG(pHWHead -> pSPTR) ));
// RETAILMSG(1, (TEXT("%08x \r\n"), (ULONG)READ_REGISTER_ULONG(pHWHead -> pLSR) ));
// RETAILMSG(1, (TEXT("%08x \r\n"), (ULONG)READ_REGISTER_ULONG(pHWHead -> pBRGDL) ));
// RETAILMSG(1, (TEXT("%08x \r\n"), (ULONG)READ_REGISTER_ULONG(pHWHead -> pBRGCKS) ));
// WRITE_REGISTER_USHORT((pHWHead -> pSMR),
// (READ_REGISTER_USHORT(pHWHead -> pSMR) | 0x00000011));
// WRITE_REGISTER_USHORT((pHWHead -> pSCR),
// (READ_REGISTER_USHORT(pHWHead -> pSCR) | 0x00000011));
return pHWHead;
ALLOCFAILED:
if ( pHWHead -> pBaseAddress )
VirtualFree((PVOID)pHWHead -> pBaseAddress, 0, MEM_RELEASE);
if ( pHWHead -> FlushDone )
CloseHandle( pHWHead -> FlushDone );
if ( pHWHead -> pTxBuff )
VirtualFree((PVOID)pHWHead -> pTxBuff, 0, MEM_RELEASE);
if ( pHWHead -> pRxBuff )
VirtualFree((PVOID)pHWHead -> pRxBuff, 0, MEM_RELEASE);
LocalFree( pHWHead );
return NULL;
}
/*
@doc OEM
@func BOOL | SerOpen | This routine is called when the port is opened.
* Not exported to users, only to driver.
*
@rdesc Returns TRUE if successful, FALSEotherwise.
*/
static
BOOL
SCIF0Open(
PVOID pHead /*@parm PVOID returned by Serinit. */
)
{
PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
DWORD dcr_value;
// Disallow multiple simultaneous opens
if( pHWHead->OpenCount )
return FALSE;
pHWHead->OpenCount++;
DEBUGMSG (ZONE_OPEN,
(TEXT("SCIF0_Open - Selecting Non IR Mode\r\n")));
pHWHead->fIRMode = FALSE; // Select wired by default
pHWHead->SMR = 0;
pHWHead->FCR = 0;
pHWHead->BRR = 0;
pHWHead->SCR = 0;
pHWHead->BRGDL = 0;
pHWHead->BRGCKS = 0;
pHWHead->DroppedBytes = 0;
pHWHead->CTSFlowOff = FALSE; // Not flowed off yet
pHWHead->DSRFlowOff = FALSE; // Not flowed off yet
pHWHead->CommErrors = 0;
pHWHead->ModemStatus = 0;
WRITE_REGISTER_USHORT(pHWHead -> pSCR, 0);
WRITE_REGISTER_USHORT(pHWHead -> pFSR, 0);
WRITE_REGISTER_UCHAR(pHWHead -> pBRR, 0);
WRITE_REGISTER_USHORT(pHWHead -> pSPTR, SCIF_SPTR_RTSIO);
pHWHead->ulReceiveDmaBufferPointer = 0;
WRITE_REGISTER_USHORT(pHWHead -> pFCR, SCIF_FCR_TFRST | SCIF_FCR_RFRST);
WRITE_REGISTER_USHORT(pHWHead -> pSMR, SCIF_SMR_ASYNC|SCIF_SMR_CKS_1|SCIF_SMR_8BIT|SCIF_SMR_1STOP);
// Set Default Value
pHWHead->dcb.BaudRate = 9600;
pHWHead->dcb.ByteSize = DATABITS_8;
pHWHead->dcb.StopBits = ONESTOPBIT;
pHWHead->dcb.Parity = NOPARITY;
SCIF_SetBaudRate(pHWHead, pHWHead -> dcb.BaudRate);
SCIF_SetByteSize(pHWHead, pHWHead -> dcb.ByteSize);
SCIF_SetStopBits(pHWHead, pHWHead -> dcb.StopBits);
SCIF_SetParity( pHWHead, pHWHead -> dcb.Parity);
WRITE_REGISTER_USHORT(pHWHead -> pFCR, SCIF_FCR_RSTRG_15 | SCIF_FCR_RTRG_14 | SCIF_FCR_TTRG_0);
WRITE_REGISTER_USHORT(pHWHead -> pSCR, SCIF_SCR_CKE_2);
dcr_value = DCR_DPDS_8BIT |
DCR_DDRMD_MODULE |
DCR_DPDAM_FIX |
DCR_DMDL_MEMORY |
DCR_SPDS_8BIT |
DCR_SDRMD_MODULE |
DCR_SPDAM_FIX |
DCR_SMDL_PERIPHERAL |
DCR_DIP_2PAGE |
DCR_ACMD_ENABLE |
DCR_CT_ENABLE |
DCR_PKMD_DISABLE |
DCR_BTMD_DISABLE |
DCR_DTAU_BYTE |
DCR_DTAC_DISABLE ;
dma_SetPage(pHWHead -> pRxDma, 0, pHWHead -> ulRxDmaRegBase,
pHWHead -> ulRxDmaBuffBase1, pHWHead -> ulRxDmaBuffSize);
dma_SetPage(pHWHead -> pRxDma, 1, pHWHead -> ulRxDmaRegBase,
pHWHead -> ulRxDmaBuffBase2, pHWHead -> ulRxDmaBuffSize);
dma_SetPort(pHWHead -> pRxDma, pHWHead -> dwRxDmaPort);
dma_SetControl(pHWHead -> pRxDma, dcr_value);
dma_SetCommand(pHWHead -> pRxDma, DCMDR_DMEN);
#if (SH7770_REVISION == SH7770_1STCUT)
WRITE_REGISTER_USHORT(pHWHead -> pSCR,
SCIF_SCR_TOIE|SCIF_SCR_TE|SCIF_SCR_RE|SCIF_SCR_REIE|SCIF_SCR_CKE_2|SCIF_SCR_RIE);
#else
WRITE_REGISTER_USHORT(pHWHead -> pSCR,
SCIF_SCR_TOIE|SCIF_SCR_TE|SCIF_SCR_RE|SCIF_SCR_REIE|SCIF_SCR_CKE_2);
#endif
dma_InterruptEnable(pHWHead -> pRxDma);
ReadModemStatus( pHWHead );
return TRUE;
}
//
// @doc OEM
// @func VOID | SCIF_ClearRTS | This routine clears RTS.
//
// @rdesc None.
//
VOID
SCIF0ClearRTS(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
DEBUGMSG (ZONE_FUNCTION, (TEXT("+SerClearRTS, 0x%X\r\n"), pHead));
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
// Clear RTS
USHORT SPR = READ_REGISTER_USHORT(pHWHead -> pSPTR);
SPR &= ~SCIF_SPTR_RTS;
WRITE_REGISTER_USHORT(pHWHead -> pSPTR, SPR);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
DEBUGMSG (ZONE_FUNCTION, (TEXT("-SerClearRTS, 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func VOID | SCIF_SetRTS | This routine sets RTS.
//
// @rdesc None.
//
VOID
SCIF0SetRTS(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
DEBUGMSG (ZONE_FUNCTION, (TEXT("+SetSetRTS, 0x%X\r\n"), pHead));
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
// Set RTS
USHORT SPR = READ_REGISTER_USHORT(pHWHead -> pSPTR);
SPR |= SCIF_SPTR_RTS;
WRITE_REGISTER_USHORT(pHWHead -> pSPTR, SPR);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
DEBUGMSG (ZONE_FUNCTION, (TEXT("-SetSetRTS, 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func ULONG | SCIF_GetGetInterruptType | This function is called
// by the MDD whenever an interrupt occurs. The return code
// is then checked by the MDD to determine which of the four
// interrupt handling routines are to be called.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -