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

📄 xrcom16550.c

📁 wince 5.0下 实现PCI8串口卡驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
        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 + -