📄 pdd.c
字号:
mask = UART_LINECTRL_PE | (3 << 4);
break;
default:
goto cleanUp;
}
EnterCriticalSection(&pPdd->hwCS);
lineCtrl = INP32(&pPdd->pPortBase->linectrl);
lineCtrl = (lineCtrl & ~UART_LINECTRL_ST)|mask;
OUT32(&pPdd->pPortBase->linectrl, lineCtrl);
LeaveCriticalSection(&pPdd->hwCS);
#endif
ok = TRUE;
////cleanUp:
return ok;
}
//------------------------------------------------------------------------------
//
// Function: SetStopBits
//
// Description: This function sets word length.
//
static BOOL SetStopBits(UARTPDD *pPdd, UCHAR stopBits)
{
////UCHAR lineCtrl;
BOOL ok = FALSE;
////UCHAR mask;
#if 0
switch (stopBits) {
case ONESTOPBIT:
mask = 0;
break;
case ONE5STOPBITS:
case TWOSTOPBITS:
mask = UART_LINECTRL_ST;
break;
default:
goto cleanUp;
}
EnterCriticalSection(&pPdd->hwCS);
lineCtrl = INP32(&pPdd->pPortBase->linectrl);
lineCtrl = (lineCtrl & ~UART_LINECTRL_ST)|mask;
OUT32(&pPdd->pPortBase->linectrl, lineCtrl);
LeaveCriticalSection(&pPdd->hwCS);
#endif
ok = TRUE;
////cleanUp:
return ok;
}
//------------------------------------------------------------------------------
//
// Function: GetSerialObject
//
// Description: This function returns a pointer to a HWOBJ structure, which
// contains the correct function pointers and parameters for
// the relevant PDD layer's hardware interface functions.
PHWOBJ GetSerialObject(DWORD index)
{
PHWOBJ pHWObj;
// Allocate space for the HWOBJ.
pHWObj = malloc(sizeof(HWOBJ));
if (pHWObj == NULL) goto cleanUp;
// Fill in the HWObj structure
pHWObj->BindFlags = THREAD_AT_OPEN; // Have MDD create thread when device is first opened.
pHWObj->dwIntID = 0; // SysIntr is filled in at init time
pHWObj->pFuncTbl = &g_pddVTbl; // Return pointer to appropriate functions
cleanUp:
return pHWObj;
}
//------------------------------------------------------------------------------
//
// Function: HWInit
//
// Description: This function initializes a serial device and it returns
// information about device
//
static PVOID HWInit(ULONG context, PVOID pMdd, PHWOBJ pHWObj)
{
BOOL ok = FALSE;
UARTPDD *pPdd = NULL;
PHYSICAL_ADDRESS phBase;
HKEY hKey = NULL;
ULONG UnitIndex;
ULONG Size;
CPLD * pCpld = (CPLD *)CPLD_KSEG1_ADDR;
DEBUGMSG(ZONE_OPEN, (L"+cplduart::HWInit %s 0x%08x 0x%08x\r\n", context, pMdd, pHWObj));
if(pBootArgs->bUartDebugEnable == 0x2c) {
RETAILMSG(1,(L" cplduart::cpld Uart is using debug\r\n"));
goto cleanUp;
}
// Allocate SER_INFO structure
pPdd = malloc(sizeof(UARTPDD));
if (pPdd == NULL) goto cleanUp;
// Clear it
memset(pPdd, 0, sizeof(UARTPDD));
// Open registry
hKey = OpenDeviceKey((LPCTSTR)context);
if (hKey == NULL) {
DEBUGMSG(ZONE_ERROR, (L" cplduart::HWInit - Failed open registry key\r\n"));
goto cleanUp;
}
// Read UnitIndex from the Registry
Size = sizeof(UnitIndex);
if (RegQueryValueEx(hKey, L"UnitIndex", NULL, NULL, (PUCHAR)&UnitIndex, &Size)) {
RETAILMSG(1,(L" cplduart::HWInit - Failed open \"UnitIndex\" registry entry\r\n"));
goto cleanUp;
}
// Check UnitIndex is valid and supported
if (UnitIndex > UART_CONFIG_SIZE || UartConfig[UnitIndex].UartPhysAddr == 0) {
RETAILMSG(1,(L" cplduart::HWInit - UnitIndex %d is invalid\r\n", UnitIndex));
goto cleanUp;
}
// Map physical memory
phBase.QuadPart = UartConfig[UnitIndex].UartPhysAddr;
//pPdd->pPortBase = (AU1X00_UART*)MmMapIoSpace(phBase, sizeof(AU1X00_UART), FALSE);
pPdd->pPortBase = (CPLD*)MmMapIoSpace(phBase, sizeof(CPLD), FALSE);
if (pPdd->pPortBase == NULL) {
DEBUGMSG(ZONE_ERROR, (L" cplduart::HWInit - Failed map physical memory 0x%x\r\n", phBase.LowPart));
goto cleanUp;
}
// Save IRQ
pPdd->irq = UartConfig[UnitIndex].UartIrq;
pPdd->sysIntr = InterruptConnect(Internal,0,pPdd->irq, INTR_MODE_POSITIVE_LOGIC /*| INTR_MODE_NEGATIVE_LOGIC*/ /*| INTR_MODE_EDGE*/ | INTR_MODE_LEVEL);
if (SYSINTR_NOP==pPdd->sysIntr) {
DEBUGMSG(ZONE_ERROR, (L" cplduart::HWInit - Failed map IRQ %d\r\n", pPdd->irq));
goto cleanUp;
}
// Save it to HW object
pHWObj->dwIntID = pPdd->sysIntr;
// Create sync objects
InitializeCriticalSection(&pPdd->hwCS);
InitializeCriticalSection(&pPdd->txCS);
pPdd->txEvent = CreateEvent(0, FALSE, FALSE, NULL);
if (pPdd->txEvent == NULL) {
DEBUGMSG(ZONE_ERROR, (L" cplduart::HWInit - Failed create event\r\n"));
goto cleanUp;
}
// Allow device
//OUT32(&pPdd->pPortBase->enable, 0);
//OUT32(&pPdd->pPortBase->enable, UART_ENABLE_CE);
//OUT32(&pPdd->pPortBase->enable, UART_ENABLE_CE|UART_ENABLE_E);
ResetUart(pPdd);
//EnableRxFifo(pPdd, FALSE); // cpld里写死了一定要使用fifo
EnableUart(pPdd, TRUE);
RETAILMSG(1, (L"CPLD UART CTRL 0x%x\r\n", pPdd->pPortBase->uartCtrl));
//while( !(pCpld->uartStatus & 0x01) ); // if send fifo is empty
//pCpld->uartTxData = 'e';
//while( !(pCpld->uartStatus & 0x01) ); // if send fifo is empty
//pCpld->uartTxData = 'f';
// Disable all interrupts
//OUT32(&pPdd->pPortBase->inten, 0);
//RETAILMSG(1, (L"CPLD UART uartIntEnable 01 0x%x\r\n", pPdd->pPortBase->uartIntEnable));
//pPdd->pPortBase->uartIntEnable &= ~(TX_INT_ENB_BIT| RX_INT_ENB_BIT);
DISABLE_ALL_INT(pPdd->pPortBase);
//RETAILMSG(1, (L"CPLD UART uartIntEnable 02 0x%x\r\n", pPdd->pPortBase->uartIntEnable));
// Save MDD context for callback
pPdd->pMdd = pMdd;
// Initialization succeeded
ok = TRUE;
cleanUp:
if (hKey != NULL) RegCloseKey(hKey);
if (!ok && pPdd != NULL) {
HWDeinit(pPdd);
pPdd = NULL;
}
DEBUGMSG(ZONE_OPEN, (L"-cplduart::HWInit 0x%08x\r\n", pPdd));
return pPdd;
}
//------------------------------------------------------------------------------
//
// Function: HWPostInit
//
// Description: This function is called by the upper layer after hardware
// independent initialization is done (at end of COM_Init).
//
static BOOL HWPostInit(PVOID pContext)
{
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: HWDeinit
//
// Description: This function is called by the upper layer to de-initialize
// the hardware when a device driver is unloaded.
static BOOL HWDeinit(PVOID pContext)
{
UARTPDD *pPdd = (UARTPDD*)pContext;
CPLD * pCpld = (CPLD *)CPLD_KSEG1_ADDR;
DEBUGMSG(ZONE_CLOSE, (L"+cplduart::HWDeinit 0x%08x\r\n", pContext));
// Disable device
if (pPdd->pPortBase != NULL) {
////OUT32(&pPdd->pPortBase->enable, 0);
EnableUart(pPdd, FALSE);
MmUnmapIoSpace((PVOID)pPdd->pPortBase, 0x1000);
}
// Disconnect the interrupt
InterruptDisconnect(pPdd->sysIntr);
// Delete sync objects
DeleteCriticalSection(&pPdd->hwCS);
DeleteCriticalSection(&pPdd->txCS);
if (pPdd->txEvent != NULL) CloseHandle(pPdd->txEvent);
// Free driver object
free(pPdd);
DEBUGMSG(ZONE_CLOSE, (L"-cplduart::HWDeinit\r\n"));
return TRUE;
}
//------------------------------------------------------------------------------
static BOOL HWOpen(PVOID pContext)
{
BOOL ok = FALSE;
UARTPDD *pPdd = (UARTPDD*)pContext;
////UCHAR fifoCtrl;
DEBUGMSG(ZONE_OPEN, (L"+cplduart::HWOpen 0x%x\r\n", pContext));
if (pPdd->open) goto cleanUp;
pPdd->commErrors = 0;
pPdd->overrunCount = 0;
pPdd->flowOffCTS = FALSE;
pPdd->flowOffDSR = FALSE;
pPdd->addTxIntr = FALSE;
pPdd->powerOff = FALSE;
pPdd->open = TRUE;
// Initialize FIFO constant
////pPdd->txFifoLength = 16;
//pPdd->txFifoThresh = 8;
//pPdd->rxFifoLength = 16;
//pPdd->rxFifoThresh = 1;
pPdd->txFifoLength = 15;
pPdd->txFifoThresh = 1;
pPdd->rxFifoLength = 16;
pPdd->rxFifoThresh = 1;
EnterCriticalSection(&pPdd->hwCS);
ResetUart(pPdd); // 这样能使 reset Rx fifo, 同时不影响uart contoller的其它功能
// Set line control register
////OUT32(&pPdd->pPortBase->linectrl, 0);
SetBaudRate(pPdd, pPdd->dcb.BaudRate);
SetWordLength(pPdd, pPdd->dcb.ByteSize);
SetStopBits(pPdd, pPdd->dcb.StopBits);
SetParity(pPdd, pPdd->dcb.Parity);
// Set modem control register
////OUT32(&pPdd->pPortBase->mdmctrl, 0);
// Set FIFO values & enable flags
////fifoCtrl = UART_FIFOCTRL_FE | UART_FIFOCTRL_MS | (0 << 6) | (2 << 4);
// Set reset TX & RX flags
////fifoCtrl |= UART_FIFOCTRL_RR | UART_FIFOCTRL_TR;
// Set fifo control register
////OUT32(&pPdd->pPortBase->fifoctrl, fifoCtrl);
//EnableRxFifo(pPdd, TRUE); // Enable Rx fifo // cpld里写死了一定要使用fifo
// Enable interrupts (no TX interrupt)
////OUT32(&pPdd->pPortBase->inten, UART_INTEN_TX_OFF);
//RETAILMSG(1, (L"HWOpen CPLD UART uartIntEnable 01 0x%x\r\n", pPdd->pPortBase->uartIntEnable));
{
BYTE ch = pPdd->pPortBase->uartIntEnable; //????????????????? 这里很 如果我不读一次这个register,那就不能正确写这个register
}
//pPdd->pPortBase->uartIntEnable = UART_INTEN_TX_OFF; // Enable Rx interrupts, disable Tx interrupt
DISABLE_TX_INT(pPdd->pPortBase);
RETAILMSG(1, (L"HWOpen CPLD UART uartIntEnable 02 0x%x\r\n", pPdd->pPortBase->uartIntEnable));
////ReadLineStat(pPdd);
////ReadModemStat(pPdd);
// SmartOne add
// is com4: for BT //// power on bluetooth module
//if(pPdd->UnitIndex == 4 ){
{
CPLD * pCpld = (CPLD *)pPdd->pPortBase;
// enable BT power
pCpld->ioASet = CP_AIO_BT_PWR_EN_01;
// Reset BT module
pCpld->ioASet = CP_AIO_BT_RESET_00;
StallExecution(1000); //1ms
pCpld->ioAClr = CP_AIO_BT_RESET_00;
RETAILMSG(1, (L"+cplduart::HWOpen power on and reset bluetooth\r\n"));
}
// End SmartOne add
LeaveCriticalSection(&pPdd->hwCS);
ok = TRUE;
cleanUp:
DEBUGMSG(ZONE_OPEN, (L"-cplduart::HWOpen %s\r\n", ok ? L"TRUE" : L"FALSE"));
return ok;
}
//------------------------------------------------------------------------------
static ULONG HWClose(PVOID pContext)
{
ULONG rc = -1;
UARTPDD *pPdd = (UARTPDD*)pContext;
DEBUGMSG(ZONE_CLOSE, (L"+cplduart::HWClose 0x%x\r\n", pContext));
if (!pPdd->open) goto cleanUp;
EnterCriticalSection(&pPdd->hwCS);
// Disable all interrupts and clear modem control register
////OUT32(&pPdd->pPortBase->inten, 0);
////OUT32(&pPdd->pPortBase->mdmctrl, 0);
////pPdd->pPortBase->uartIntEnable &= ~(TX_INT_ENB_BIT | RX_INT_ENB_BIT); // disable Tx and Rx interrupt
DISABLE_ALL_INT(pPdd->pPortBase);
// SmartOne add
// is com4: for BT //// power off bluetooth module
//if(pPdd->UnitIndex == 4 ){
{
CPLD * pCpld = (CPLD *)pPdd->pPortBase;
// power off BT
pCpld->ioAClr = CP_AIO_BT_PWR_EN_01;
// Reset BT module
//pCpld->ioASet = CP_AIO_BT_RESET_00;
//StallExecution(1000); //1ms
//pCpld->ioAClr = CP_AIO_BT_RESET_00;
RETAILMSG(1, (L"+cplduart::HWClose power off bluetooth\r\n"));
}
// End SmartOne add
LeaveCriticalSection(&pPdd->hwCS);
pPdd->open = FALSE;
cleanUp:
DEBUGMSG(ZONE_CLOSE, (L"-cplduart::HWClose %d\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: HWGetInterruptType
//
// Description: This function is called by the upper layer 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.
//
static INTERRUPT_TYPE HWGetInterruptType(PVOID pContext)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -