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

📄 serio.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 4 页
字号:
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995, 1996, 1997  Microsoft Corporation
Copyright (c) NEC Electronics Inc. 1998.

Module Name:  

Serio.c

Abstract:  

    VR41xx Ev-board Serial/Ir port lowlevel driver.
  
Functions:

  HWInit_
  HWInitSerial
  HWInitIR
  HWClearDTR
  HWSetDTR
  HWClearRTS
  HWSetRTS
  HWEnableIR
  HWDisableIR
  HWClearBreak
  HWSetBreak
  HWGetRxStart
  HWGetBytes
  HWClose
  HWTxIntrHandler
  HWGetRxBufferSize
  HWSetDCB
  HWSetCommTimeouts
  HWClearOtherIntr
  HWClearLineIntr
  HWSetBaudRate
  HWSetLineControl
  HWPutBytes
  HWPowerOff
  HWPowerOn
  HWSetParity
  HWGetIntrType
  HWXmitComChar
  HWOpen
  HWDeinit
  HWIoctl
  GetSerialObject
  
Notes:


--*/

#include <windows.h>
#include <types.h>
#include <serhw.h>
#include <serfw.h>
#include <hw16550.h>
#include <memory.h>
#include <nkintr.h>
#include <serdbg.h>
#include <windev.h>
#include <drvlib.h>
#include <vr4122io.h>

#include "serio.h"

extern DWORD dwIntrId;
// ****************************************************************
//
//  @doc OEM
//
//  @func PVOID | HWInit | Initializes device identified by argument.
//
//  @parm   ULONG | Identifier  | This is actually a LPCTSTR that
//              contains the registry key of the active device.
//  @parm   PVOID | pMDDContext | Context to pass to mdd on all function
//              calls.
//
//  @remark 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.
// ***************************************************************
PVOID
HWInit(ULONG Identifier, PVOID pMddHead)
{
    PPERP_IO_SER_INFO pHWHead;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWInit\r\n")));

    /* Now map the ASIC registers. */
    if (HWMapRegisterAddresses() == FALSE){
        DEBUGMSG(ZONE_FUNCTION, (TEXT("HWMapRegisterAddresses() NG!!\r\n")));

        return NULL;
    }
    DEBUGMSG(ZONE_FUNCTION, (TEXT("HWMapRegisterAddresses() OK!!\r\n")));

    // Enable SIU clock
    InterlockedAndOr16(pVRIO+CMUCLKMSK, 0xFFFF, MSKSIU | MSKSSIU);

    /* Check VR41xx Serial unit */
    REG8(ASICSiuRegs.siusc) = 0x5A;
    DEBUGMSG(ZONE_FUNCTION, (TEXT("0x%x\r\n"), REG8(ASICSiuRegs.siusc)));

    if (REG8(ASICSiuRegs.siusc) != 0x5A) {
        return NULL;
    }

    /* Allocate hardware specific structure. */
    pHWHead = LocalAlloc(LPTR, sizeof(PERP_IO_SER_INFO));

    if (!pHWHead){
        HWUnmapRegisterAddress();
        DEBUGMSG(ZONE_FUNCTION, (TEXT("pHWHead Alloc Error!!\r\n")));

        return NULL;
    }
    DEBUGMSG(ZONE_FUNCTION, (TEXT("pHWHead Alloc Adr = 0x%x\r\n"), pHWHead));

    InitializeCriticalSection (&(pHWHead->CS));

        pHWHead->FlushDone      = CreateEvent(0, FALSE, FALSE, NULL);
        pHWHead->PortOpen       = FALSE;
        pHWHead->DroppedBytes   = 0;
        pHWHead->CommErrors     = 0;
        pHWHead->ModemStatus    = 0;
        pHWHead->fPowerOff      = FALSE;
        pHWHead->pMddHead       = pMddHead;
        pHWHead->dwCloseTicks   = GetTickCount();

    memset(&(pHWHead->Status), 0, sizeof(COMSTAT));

        // 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_DTRDSR | PCF_RLSD | 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_115200 | BAUD_57600 | BAUD_USER;
        pHWHead->CommProp.dwSettableParams  =
            SP_BAUD | SP_DATABITS | SP_HANDSHAKING | SP_PARITY |
            SP_PARITY_CHECK | SP_RLSD | SP_STOPBITS;
        pHWHead->CommProp.wSettableData     =
            DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8;
        pHWHead->CommProp.wSettableStopParity =
            STOPBITS_10 | STOPBITS_20 | PARITY_NONE | PARITY_ODD |
            PARITY_EVEN | PARITY_SPACE | PARITY_MARK;

    /* Reset 16550 UART. */
    HWReset( pHWHead );

    /* Then set default baud rate. */
    HWSetBaudRate(pHWHead, BAUDRATE_INIT);     // 9600 bps

    /* Initialize hardware abstraction structure.*/
    HWSetByteSize(pHWHead, BYTESIZE_INIT);   // 0x08
    HWSetStopBits(pHWHead, STOPBITS_INIT);   // One stop bit
    HWSetParity(pHWHead, PARITY_INIT);       // No parity bit

    REG8(ASICSiuRegs.siumc) &= ~(SERIAL_MCR_DTR | SERIAL_MCR_RTS);

    InterlockedAndOr16(pVRIO+GIUPIODL, ~IRPWR, 0);

    REG8(ASICSiuRegs.siuirsel) &= ~SIRSEL;

    // Disable SIU clock
    InterlockedAndOr16(pVRIO+CMUCLKMSK, ~MSKSSIU, 0);

    DEBUGMSG(ZONE_FUNCTION, (TEXT("pHWHead Alloc Adr = 0x%x\r\n"), pHWHead));
    DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Leave HWInit\r\n")));

    return pHWHead;
}

//***********************************************************************
//
//  @doc OEM
//
//  @func BOOL | HWDeinit |
//      Called by driver to unload the driver.
//
//  @parm PVOID | pHead | PDD device context (returned from HWInit())
//
//  @rdesc  Returns TRUE for success, FALSE if error
//
//  @remark This is called when the device is no longer needed.  This is
//          never called for built-in devices, for PCMCIA devices it is
//          called when the card is removed.
//***********************************************************************
ULONG
HWDeinit(PVOID pHead)
{
    PPERP_IO_SER_INFO   pHWHead = (PPERP_IO_SER_INFO)pHead;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWDeinit\r\n")));

    if(!pHWHead){
        
        return FALSE;
    }

    if(pHWHead->PortOpen){
        
        HWClose( pHead );
    }

    // Free the flushdone event
    if( pHWHead->FlushDone ){

        CloseHandle( pHWHead->FlushDone );
    }

    DeleteCriticalSection(&(pHWHead->CS));

    InterlockedAndOr16(pVRIO+CMUCLKMSK, ~MSKSSIU, 0);

    HWUnmapRegisterAddress();
    
    LocalFree(pHWHead);

    return TRUE;
}

// *******************************************************************
//
//  @doc OEM
//
//  @func BOOL | HWOpen |
//      Called by MDD layer to turn open the serial port.
//
//  @parm PVOID | pHead | PDD device context (returned from HWInit())
//
//  @rdesc  Returns TRUE for success, FALSE if error
//********************************************************************
BOOL
HWOpen( PVOID pHead ){

    PPERP_IO_SER_INFO   pHWHead = (PPERP_IO_SER_INFO)pHead;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWOpen\r\n")));

    if(pHWHead->PortOpen){
    
            return FALSE;
    }
    
        pHWHead->IrMode = FALSE;
        pHWHead->PortOpen = TRUE;

    InterlockedAndOr16(pVRIO+CMUCLKMSK, 0xFFFF, MSKSIU | MSKSSIU);

        pHWHead->FCR = 0;
        pHWHead->IER = 0;
        pHWHead->IIR = 0;
        pHWHead->LSR = 0;
        pHWHead->MSR = 0;
        pHWHead->DroppedBytes = 0;
        pHWHead->CTSFlowOff = FALSE;  // Not flowed off yet
        pHWHead->DSRFlowOff = FALSE;  // Not flowed off yet
        pHWHead->CommErrors   = 0;
        pHWHead->ModemStatus  = 0;

    REG8(ASICSiuRegs.siuie) |= SERIAL_IER_RDA | SERIAL_IER_RLS | SERIAL_IER_MS;

    REG8(ASICSiuRegs.siumc) |= SERIAL_MCR_IRQ_ENABLE;

    REG8(ASICSiuRegs.siulc) |= SERIAL_8_DATA | SERIAL_1_STOP | SERIAL_NONE_PARITY;

    // Get defaults from the DCB structure
    HWSetBaudRate(pHead, pHWHead->dcb.BaudRate);
    HWSetByteSize(pHead, pHWHead->dcb.ByteSize);
    HWSetStopBits(pHead, pHWHead->dcb.StopBits);
    HWSetParity(pHead, pHWHead->dcb.Parity);

    pHWHead->FCR = ( SERIAL_FCR_ENABLE | SERIAL_8_BYTE_HIGH_WATER |
            SERIAL_FCR_RCVR_RESET | SERIAL_FCR_TXMT_RESET);

    ENABLE_BITS8(ASICSiuRegs.siuiid_fc, pHWHead->FCR);
    DEBUGMSG(ZONE_FUNCTION, (TEXT("FCR = 0x%x\r\n"), pHWHead->FCR));

    pHWHead->IIR = *((volatile UCHAR *)ASICSiuRegs.siuiid_fc);
    DEBUGMSG(ZONE_FUNCTION, (TEXT("IIR = 0x%x\r\n"), pHWHead->IIR));

    DISABLE_BITS8(ASICSiuRegs.siuirsel, SIRSEL);

    DISABLE_BITS16(VRGiuRegs.giupiod, IRPWR);

    //ENABLE_BITS8(ASICSiuRegs.siuie, SERIAL_IER_RDA | SERIAL_IER_RLS | SERIAL_IER_MS);

    return TRUE;
}

// ********************************************************************
//
//  @doc OEM
//
//  @func ULONG | HWClose | This routine closes the device
//          identified by the PVOID returned by HWInit.
//
//  @parm PVOID | pHead | PDD device context (returned from HWInit())
//
//  @rdesc The return value is 0 for success.
//*********************************************************************
ULONG
HWClose( PVOID pHead ){

    PPERP_IO_SER_INFO   pHWHead = (PPERP_IO_SER_INFO)pHead;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWClose\r\n")));

    DISABLE_BITS8(ASICSiuRegs.siumc, SERIAL_MCR_DTR | SERIAL_MCR_RTS);

    DISABLE_BITS8(ASICSiuRegs.siuie, SERIAL_IER_RDA | SERIAL_IER_RLS | SERIAL_IER_MS | SERIAL_IER_THR);

    ENABLE_BITS8(ASICSiuRegs.siuiid_fc, SERIAL_FCR_RCVR_RESET | SERIAL_FCR_TXMT_RESET);

    pHWHead->PortOpen = FALSE;

    DISABLE_BITS16(VRGiuRegs.giupiod, IRPWR);

    // Set close tick count.
    pHWHead->dwCloseTicks = GetTickCount();

//  DISABLE_BITS16(VRCmuRegs.cmuclkmsk, MSKSIU | MSKSSIU);
    DISABLE_BITS16(VRCmuRegs.cmuclkmsk, MSKSSIU);

    return 0;
}

// ***************************************************************************
//
//  @doc OEM
//
//  @func ULONG | HWGetBytes | Get bytes from the device
//
//  @parm PVOID | pHead | PDD device context (returned from HWInit())
//  @parm PUCHAR | pTargetBuffer | Where to put the data.
//  @parm PULONG | pByteNumber | On entry the max number of bytes to read,
//          on exit filled with the number of bytes read.
//
//  @rdesc  The return value is the number of bytes dropped, by the hardware.
//
//  @remark This routine gets a several characters from the hardware
//          receive buffer and puts them into the location pointed to by
//          the second argument.
//****************************************************************************
ULONG
HWGetBytes(
    PVOID pHead,
    PUCHAR pTargetBuffer,
    PULONG pByteNumber
    )
{
    PPERP_IO_SER_INFO pHWHead   = (PPERP_IO_SER_INFO)pHead;
    ULONG       RetVal  = 0;
    ULONG       TargetRoom  = *pByteNumber;
    INT         Delay;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWGetBytes\r\n")));

    *pByteNumber = 0;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("TargetRoom = %d"), TargetRoom));
    DEBUGMSG(ZONE_FUNCTION, (TEXT("Recv DATA:\r\n")));
    
    EnterCriticalSection(&(pHWHead->CS));
    
    while (TargetRoom ){
    
        // See if there is another byte to be read.
        HWReadLSR(pHWHead);
        
        if (pHWHead->LSR & SERIAL_LSR_DR){

            for(Delay=0; Delay<180; Delay++);

            // Read the byte
            *pTargetBuffer = REG8(ASICSiuRegs.siurb_th);
            DEBUGMSG(ZONE_FUNCTION, (TEXT("%02x"), *pTargetBuffer));

            // But we may want to discard it.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -