📄 xrcom16550.c
字号:
VirtualFree(pHWHead->pBaseAddress, 0, MEM_RELEASE);
LocalFree(pHWHead);
return (NULL);
}
/*
@doc OEM
@func ULONG | SerClose | This routine closes the device identified by the PVOID returned by SerInit.
* Not exported to users, only to driver.
*
@rdesc The return value is 0.
*/
static
ULONG
SerClose(
PVOID pHead // @parm PVOID returned by SerInit.
)
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
ULONG uTries;
DEBUGMSG (ZONE_CLOSE,(TEXT("+SerClose\r\n")));
if ( pHWHead->cOpenCount ) {
DEBUGMSG (ZONE_CLOSE,
(TEXT("SerClose, closing device\r\n")));
pHWHead->cOpenCount--;
// while we are still transmitting, sleep.
uTries = 0;
while ( ((pHWHead->ser16550.IER = READ_REGISTER_UCHAR(pHWHead->ser16550.pIER))
& SERIAL_IER_THR) && // indicates TX in progress
(uTries++ < 100) && // safety net
!(pHWHead->ser16550.LSR & SERIAL_LSR_TEMT) // indicates FIFO not yet empty
) {
DEBUGMSG (ZONE_CLOSE,
(TEXT("SerClose, TX in progress, IER 0x%X, LSR 0x%X\r\n"),
*pHWHead->ser16550.pIER, pHWHead->ser16550.LSR));
Sleep(10);
}
// When the device is closed, we power it down.
DEBUGMSG (ZONE_CLOSE,
(TEXT("SerClose - Powering down UART\r\n")));
pHWHead->fIRMode = FALSE;
SerSetOutputMode(pHWHead, FALSE, FALSE );
DEBUGMSG (ZONE_CLOSE, (TEXT("SerClose - Calling XRXRSL_Close\r\n")));
XRSL_Close( pHWHead );
}
DEBUGMSG (ZONE_CLOSE,(TEXT("-SerClose\r\n")));
return (0);
}
/*
@doc OEM
@func PVOID | SerDeinit | Deinitializes device identified by argument.
* This routine frees any memory allocated by SerInit.
*
*/
static
BOOL
SerDeinit(
PVOID pHead // @parm PVOID returned by SerInit.
)
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
if ( !pHWHead )
return (FALSE);
// Make sure device is closed before doing DeInit
if ( pHWHead->cOpenCount )
SerClose( pHead );
if ( pHWHead->pBaseAddress )
VirtualFree(pHWHead->pBaseAddress, 0, MEM_RELEASE);
// Free the HWObj
LocalFree(pHWHead->pHWObj);
// And now free the SER_INFO structure.
LocalFree(pHWHead);
return (TRUE);
}
/*
@doc OEM
@func VOID | SerGetCommProperties | Retrieves Comm Properties.
*
@rdesc None.
*/
static
VOID
SerGetCommProperties(
PVOID pHead, // @parm PVOID returned by SerInit.
LPCOMMPROP pCommProp // @parm Pointer to receive COMMPROP structure.
)
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
*pCommProp = pHWHead->CommProp;
return;
}
/*
@doc OEM
@func VOID | SerSetBaudRate |
* This routine sets the baud rate of the device.
* Not exported to users, only to driver.
*
@rdesc None.
*/
static
BOOL
SerSetBaudRate(
PVOID pHead, // @parm PVOID returned by SerInit
ULONG BaudRate // @parm ULONG representing decimal baud rate.
)
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
// If we are running in IR mode, try to set the IR baud
// first, since it supports a subset of the rates supported
// by the UART. If we fail setting the IR rate, then
// return an error and leave the UART alone.
if ( pHWHead->fIRMode ) {
if ( ! SerSetIRBaudRate( pHWHead, BaudRate ) ) {
DEBUGMSG (ZONE_ERROR,
(TEXT("Unsupported IR BaudRate\r\n")));
// We should return an error, but vtbl doesn't expect one
return (FALSE);
}
}
// Now set buadrate on the UART
return ( XRSL_SetBaudRate( pHead, BaudRate ) );
}
/*
@doc OEM
@func BOOL | SerPowerOff |
* Called by driver to turn off power to serial port.
* Not exported to users, only to driver.
*
@rdesc This routine returns a status.
*/
static
BOOL
SerPowerOff(
PVOID pHead // @parm PVOID returned by SerInit.
)
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
// First, power down the UART
XRSL_PowerOff( pHWHead );
// And then disable our IR and 9 Pin interface
#ifdef WAKEUPONTHISDEVICE
if (pHWHead->LastDx != D3) // If we are wakeup sources do not turn it off.
SerSetOutputMode( pHWHead, FALSE, FALSE );
#else
SerSetOutputMode( pHWHead, FALSE, FALSE );
#endif
return (TRUE);
}
/*
@doc OEM
@func BOOL | SerPowerOn |
* Called by driver to turn on power to serial port.
* Not exported to users, only to driver.
*
@rdesc This routine returns a status.
*/
static
BOOL
SerPowerOn(
PVOID pHead // @parm PVOID returned by SerInit.
)
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
// First, power up the UART
XRSL_PowerOn( pHWHead );
// And then enable our IR interface (if needed)
SerSetOutputMode( pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
return (TRUE);
}
/*
@doc OEM
@func BOOL | SerEnableIR | This routine enables ir.
* Not exported to users, only to driver.
*
@rdesc Returns TRUE if successful, FALSEotherwise.
*/
static
BOOL
SerEnableIR(
PVOID pHead, // @parm PVOID returned by Serinit.
ULONG BaudRate // @parm PVOID returned by HWinit.
)
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
pHWHead->fIRMode = TRUE;
SerSetOutputMode( pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
return (TRUE);
}
/*
@doc OEM
@func BOOL | SerDisableIR | This routine disable the ir.
* Not exported to users, only to driver.
*
@rdesc Returns TRUE if successful, FALSEotherwise.
*/
static
BOOL
SerDisableIR(
PVOID pHead /*@parm PVOID returned by Serinit. */
)
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
pHWHead->fIRMode = FALSE;
SerSetOutputMode( pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
return (TRUE);
}
/*
@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
SerOpen(
PVOID pHead /*@parm PVOID returned by Serinit. */
)
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
// Disallow multiple simultaneous opens
if ( pHWHead->cOpenCount )
return (FALSE);
pHWHead->cOpenCount++;
DEBUGMSG (ZONE_OPEN,
(TEXT("SerOpen - Selecting Non IR Mode\r\n")));
pHWHead->fIRMode = FALSE; // Select wired by default
SerSetOutputMode(pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
// NOTE: - If we wanted to support 16450s, we'll could dynamically
// identify them here.
pHWHead->ser16550.ChipID = CHIP_ID_16550;
// Init 16550 info
DEBUGMSG (ZONE_OPEN, (TEXT("SerOpen - Calling XRXRSL_Open\r\n")));
XRSL_Open( pHWHead );
return (TRUE);
}
BOOL
Ser_Ioctl(PVOID pHead, DWORD dwCode,PBYTE pBufIn,DWORD dwLenIn,
PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut)
{
BOOL RetVal=FALSE;
PSER_INFO pHWHead = (PSER_INFO)pHead;
switch ( dwCode ) {
case IOCTL_POWER_CAPABILITIES:
if (!pBufOut || dwLenOut < sizeof(POWER_CAPABILITIES) || !pdwActualOut) {
SetLastError(ERROR_INVALID_PARAMETER);
RetVal = FALSE;
} else {
PPOWER_CAPABILITIES ppc = (PPOWER_CAPABILITIES)pBufOut;
memset(ppc, 0, sizeof(POWER_CAPABILITIES));
// TODO: get these from the PDD.
ppc->DeviceDx = 0x11; // D0, D4
#ifdef WAKEUPONTHISDEVICE
ppc->DeviceDx |= 0x08; // add D3
#endif // WAKEUPONTHISDEVICE
ppc->WakeFromDx = 0x8; // Wakeup from D3
if (pdwActualOut)
*pdwActualOut = sizeof(POWER_CAPABILITIES);
RetVal = TRUE;
}
break;
case IOCTL_POWER_QUERY:
if (!pBufOut || dwLenOut < sizeof(CEDEVICE_POWER_STATE) || !pdwActualOut) {
SetLastError(ERROR_INVALID_PARAMETER);
RetVal = FALSE;
} else {
*(PCEDEVICE_POWER_STATE)pBufOut = pHWHead->LastDx;
DEBUGMSG(1, (TEXT("COM: IOCTL_POWER_QUERY: D%d\r\n"), pHWHead->LastDx));
// return PwrDeviceUnspecified if the device needs to reject the query
if (pdwActualOut)
*pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
RetVal = TRUE;
}
break;
case IOCTL_POWER_SET:
if (!pBufOut || dwLenOut < sizeof(CEDEVICE_POWER_STATE) || !pdwActualOut) {
SetLastError(ERROR_INVALID_PARAMETER);
RetVal = FALSE;
} else {
CEDEVICE_POWER_STATE newDx = *(PCEDEVICE_POWER_STATE) pBufOut;
DEBUGMSG(1, (TEXT("COM: IOCTL_POWER_SET: D%d\r\n"), newDx));
switch (newDx){
case D0:
pHWHead->LastDx = D0;
SerPowerOn(pHWHead);
#ifdef WAKEUPONTHISDEVICE
KernelIoControl(IOCTL_HAL_DISABLE_WAKE, &pHWHead->dwSysIntr,
sizeof(pHWHead->dwSysIntr), NULL, 0, NULL);
#endif
RetVal= TRUE;
break;
case D1:
case D2:
case D3:
#ifdef WAKEUPONTHISDEVICE
pHWHead->LastDx = D3;
XRXRSL_PowerOff(pHWHead);
KernelIoControl(IOCTL_HAL_ENABLE_WAKE, &pHWHead->dwSysIntr,
sizeof(pHWHead->dwSysIntr), NULL, 0, NULL);
RetVal= TRUE;
break;
#endif // WAKEUPONTHISDEVICE
case D4:
pHWHead->LastDx = D4;
SerPowerOff(pHWHead);
#ifdef WAKEUPONTHISDEVICE
KernelIoControl(IOCTL_HAL_DISABLE_WAKE, &pHWHead->dwSysIntr,
sizeof(pHWHead->dwSysIntr), NULL, 0, NULL);
#endif
RetVal= TRUE;
break;
default:
SetLastError(ERROR_INVALID_PARAMETER);
RetVal = FALSE;
break;
}
// did we set the device power?
if(RetVal == TRUE) {
*(PCEDEVICE_POWER_STATE)pBufOut = newDx;
if (pdwActualOut) {
*pdwActualOut = sizeof(pHWHead->LastDx);
}
}
}
break;
default: // check whether there are any XR17c15x PCI UART specific IOCTLs
RetVal = XRSL_Ioctl(pHead,dwCode,pBufIn,dwLenIn,
pBufOut,dwLenOut,pdwActualOut);
break;
};
return RetVal;
}
const
HW_VTBL IoVTbl = {
SerInit,
XRSL_PostInit,
SerDeinit,
SerOpen,
SerClose,
XRSL_GetInterruptType,
XRSL_RxIntr,
XRSL_TxIntrEx,
XRSL_ModemIntr,
XRSL_LineIntr,
XRSL_GetRxBufferSize,
SerPowerOff,
SerPowerOn,
XRSL_ClearDTR,
XRSL_SetDTR,
XRSL_ClearRTS,
XRSL_SetRTS,
SerEnableIR,
SerDisableIR,
XRSL_ClearBreak,
XRSL_SetBreak,
XRSL_XmitComChar,
XRSL_GetStatus,
XRSL_Reset,
XRSL_GetModemStatus,
SerGetCommProperties,
XRSL_PurgeComm,
XRSL_SetDCB,
XRSL_SetCommTimeouts,
Ser_Ioctl
};
extern const HW_VTBL SerCardIoVTbl;
//#ifdef NO_REDEF
// GetSerialObj : The purpose of this function is to allow multiple PDDs to be
// linked with a single MDD creating a multiport driver. In such a driver, the
// MDD must be able to determine the correct vtbl and associated parameters for
// each PDD. Immediately prior to calling HWInit, the MDD calls GetSerialObject
// to get the correct function pointers and parameters.
//
PHWOBJ
GetSerialObject(
DWORD DeviceArrayIndex
)
{
PHWOBJ pSerObj;
// Unlike many other serial samples, we do not have a statically allocated
// array of HWObjs. Instead, we allocate a new HWObj for each instance
// of the driver. The MDD will always call GetSerialObj/HWInit/HWDeinit in
// that order, so we can do the alloc here and do any subsequent free in
// HWDeInit.
// Allocate space for the HWOBJ.
pSerObj = (PHWOBJ)LocalAlloc( LMEM_ZEROINIT|LMEM_FIXED ,
sizeof(HWOBJ) );
if ( !pSerObj )
return (NULL);
// Fill in the HWObj structure that we just allocated.
pSerObj->BindFlags = THREAD_AT_OPEN; // Have MDD create thread when device is first opened.
pSerObj->dwIntID = 0; // SysIntr is filled in at init time
pSerObj->pFuncTbl = (HW_VTBL *) &IoVTbl; // Return pointer to appropriate functions
// Now return this structure to the MDD.
return (pSerObj);
}
//#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -