📄 serio.c
字号:
/*++
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 + -