📄 scif.c
字号:
/* Reset the FIFOs */
WRITE_REGISTER_USHORT(pHWHead->pFCR, (READ_REGISTER_USHORT(pHWHead->pFCR) |
(SCIF_SCFCR_TFRST | SCIF_SCFCR_RFRST)));
/* Get defaults from the DCB structure */
SCIF_SetBaudRate( pHead, pHWHead->dcb.BaudRate );
SCIF_SetByteSize( pHead, pHWHead->dcb.ByteSize );
SCIF_SetStopBits( pHead, pHWHead->dcb.StopBits );
SCIF_SetParity( pHead, pHWHead->dcb.Parity );
/* We now need to wait for the time it takes one bit to transfer */
BusyWait(AdjustMicroSecondsToLoopCount((1000000/pHWHead->dcb.BaudRate)+1));
/*
* enable the FIFOs and set the trigger values, we are accepting
* the defaults for the receive trigger (1) and the transmit
* trigger (8).
* Also, enable the Modem Control Signals. This allows for handshaking
* and for breaks.
*/
WRITE_REGISTER_USHORT(pHWHead->pFCR, ( SCIF_SCFCR_RTRG_14 | SCIF_SCFCR_TTRG_8));
/*
* Enable Line Error and Receive Interrupts
*/
WRITE_REGISTER_USHORT(pHWHead->pSCR, ((READ_REGISTER_USHORT(pHWHead->pSCR) &
~SCIF_SCSCR_TIE) | SCIF_SCSCR_RIE));
/* Here we enable the transmit bit as well */
WRITE_REGISTER_USHORT(pHWHead->pSCR, (READ_REGISTER_USHORT(pHWHead->pSCR) |
( SCIF_SCSCR_TE | SCIF_SCSCR_RE)));
/* we need to setup the clock source, this makes it choice 0 */
WRITE_REGISTER_USHORT(pHWHead->pSCR, (READ_REGISTER_USHORT(pHWHead->pSCR) &
~SCIF_SCSCR_CKE_2));
}
//
/////////////////// Start of exported entrypoints ////////////////
//
/*****************************************************************************
* FUNCTION : SCIF_Open
* DESCRIPTION : configures SCIF for default behavior
* INPUTS : The pointer to the hardware struct
* OUTPUTS : None
* DESIGN NOTES :
* CAUTIONS :
*****************************************************************************/
BOOL SCIF_Open(
PVOID pHead) /* PVOID returned by SCIF_init */
{
PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
DEBUGMSG(ZONE_FUNCTION,(TEXT("SERIAL : +SCIF_Open 0x%X\r\n"), pHead));
/* If the device is already open, all we do is increment count */
if( pHWHead->OpenCount++ )
{
DEBUGMSG (ZONE_OPEN,
(TEXT("-SCIF_Open 0x%X (%d opens)\r\n"),
pHead, pHWHead->OpenCount));
return (FALSE);
}
pHWHead->DroppedBytes = 0;
pHWHead->DSRFlowOff = FALSE; // Not flowed off yet
pHWHead->CTSFlowOff = FALSE;
pHWHead->CommErrors = 0;
pHWHead->LSR = 0x0000;
InitPort(pHead);
// Now we are ready
SCIF_SetRTS((PVOID)pHWHead);
SCIF_SetDTR((PVOID)pHWHead);
DEBUGMSG(ZONE_OPEN, (TEXT("SERIAL : The serial device is open\r\n")));
DEBUGMSG (ZONE_FUNCTION,
(TEXT("SERIAL : -SCIF_Open 0x%X\r\n"), pHead));
return(TRUE);
}
/*****************************************************************************
* FUNCTION : SCIF_Close
* DESCRIPTION : just keeps track of the open count
* INPUTS : The pointer to the hardware struct
* OUTPUTS : None
* DESIGN NOTES :
* CAUTIONS :
*****************************************************************************/
ULONG SCIF_Close(PVOID pHead )
{
PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+SCIF_Close 0x%X\r\n"), pHead));
if( pHWHead->OpenCount )
pHWHead->OpenCount--;
if (pHWHead->OpenCount <= 0)
{
/* First we need to disable transmit and receive */
/* DH- leave TE enabled-floating line can cause spurious transmission */
WRITE_REGISTER_USHORT(pHWHead->pSCR, (READ_REGISTER_USHORT(pHWHead->pSCR) &
(~SCIF_SCSCR_RE & ~SCIF_SCSCR_RIE & ~SCIF_SCSCR_TIE)));
DEBUGMSG (ZONE_CLOSE,
(TEXT("SERIAL : The Serial device has been closed\r\n")));
}
pHWHead->LastClose = GetTickCount();
pHWHead->CTSFlowOff = FALSE;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("SERIAL : -SCIF_Close 0x%X\r\n"), pHead));
return(TRUE);
}
/*****************************************************************************
* FUNCTION : SCIF_Init
* DESCRIPTION : Initialize the SCIF port (mainly addresses, not port)
* INPUTS : The registry ID and the pointer to the top of MDD
* OUTPUTS : Pointer to HW SCIF structure
* DESIGN NOTES : The HW struct is based loosely on the 16550 struct
* because they have similar functionality
* CAUTIONS :
*****************************************************************************/
PVOID SCIF_Init(
ULONG Identifier, /* Registry Identifier */
PVOID pMddHead) /* Serial Port Structure */
{
PSCIF_INFO pHWHead = NULL; /* Pointer to SCIF info */
PVBYTE pRegBase = NULL; /* Base reg pointer */
PVBYTE pPortBase = NULL; /* Base Port reg */
PVBYTE pIntArea1 = NULL; /* Base Port reg */
BOOL ret; /* return value */
DEBUGMSG (ZONE_FUNCTION,(TEXT("SERIAL : +SCIF_INIT, 0x%X\r\n"), pHWHead));
dwClockFreq = GetClockFrequency(CPUPeripheralClock) ;
pHWHead = VirtualAlloc(NULL, /* any location */
sizeof(SCIF_INFO), /* big enough for SCIF struct */
MEM_COMMIT, /* commit the memory */
PAGE_READWRITE); /* It is for rd/wr use */
if (pHWHead == NULL)
{
goto error_handler;
}
pRegBase = (PVBYTE)VirtualAlloc(NULL, /* any location */
SCIF_REGSIZE, /* all SCIF regs */
MEM_RESERVE, /* reserve the memory */
PAGE_NOACCESS); /* Cannot be used */
if (pRegBase == NULL)
{
DEBUGMSG(ZONE_INIT, (TEXT("SERIAL : Failed to Allocate RegBase in SCIF module\r\n")));
goto error_handler;
}
ret = VirtualCopy((PVOID)pRegBase, /* mem adress */
(BYTE*)SCIF_REGBASE, /* addr to bind to */
SCIF_REGSIZE, /* length */
PAGE_READWRITE | PAGE_NOCACHE); /* options */
if (ret != TRUE)
{
DEBUGMSG(ZONE_INIT, (TEXT("SERIAL : Failed to Bind RegBase in SCIF module\r\n")));
goto error_handler;
}
pPortBase = (PVBYTE)VirtualAlloc(NULL, /* any location */
PORTREG_SIZE, /* all SCIF regs */
MEM_RESERVE, /* reserve the memory */
PAGE_NOACCESS); /* Cannot be used */
if (pPortBase == NULL)
{
DEBUGMSG(ZONE_INIT, (TEXT("SERIAL : Failed to Allocate PortBase in SCIF module\r\n")));
goto error_handler;
}
ret = VirtualCopy((PVOID)pPortBase, /* mem adress */
(BYTE*)PORT_BASE, /* addr to bind to */
PORTREG_SIZE, /* length */
PAGE_READWRITE | PAGE_NOCACHE); /* options */
if (ret != TRUE)
{
DEBUGMSG(ZONE_INIT, (TEXT("SERIAL : Failed to Bind PortBase in SCIF module\r\n")));
goto error_handler;
}
pIntArea1 = (PVBYTE)VirtualAlloc(NULL, /* any location */
INTC_AREA_7_REGSIZE, /* all SCIF regs */
MEM_RESERVE, /* reserve the memory */
PAGE_NOACCESS); /* Cannot be used */
if (pIntArea1 == NULL)
{
DEBUGMSG(ZONE_INIT, (TEXT("SERIAL : Failed to Allocate pIntArea1 in SCIF module\r\n")));
goto error_handler;
}
ret = VirtualCopy((PVOID)pIntArea1, /* mem adress */
(BYTE*)INTC_AREA_7_REGBASE, /* addr to bind to */
INTC_AREA_7_REGSIZE, /* length */
PAGE_READWRITE | PAGE_NOCACHE); /* options */
if (ret != TRUE)
{
DEBUGMSG(ZONE_INIT, (TEXT("SERIAL : Failed to Bind PortBase in SCIF module\r\n")));
goto error_handler;
}
DEBUGMSG(ZONE_INIT, (TEXT("SERIAL : SCIF_Init:All addresses Allocated and Bound\r\n")));
/* Set up pointers to SCIF registers */
pHWHead->pSMR = (PVSHORT)((PVBYTE)pRegBase + SCIF_SCSMR2_OFFSET);
pHWHead->pBRR = pRegBase + SCIF_SCBRR2_OFFSET;
pHWHead->pSCR = (PVSHORT)((PVBYTE)pRegBase + SCIF_SCSCR2_OFFSET);
pHWHead->pFTDR = (PVBYTE)((PVBYTE)pRegBase + SCIF_SCFTDR2_OFFSET);
pHWHead->pSSR = (PVSHORT)((PVBYTE)pRegBase + SCIF_SCFSR2_OFFSET);
pHWHead->pFDR = (PVSHORT)((PVBYTE)pRegBase + SCIF_SCFDR2_OFFSET);
pHWHead->pFCR = (PVSHORT)((PVBYTE)pRegBase + SCIF_SCFCR2_OFFSET);
pHWHead->pLSR = (PVSHORT)((PVBYTE)pRegBase + SCIF_SCLSR2_OFFSET);
pHWHead->pFRDR = pRegBase + SCIF_SCFRDR2_OFFSET;
pHWHead->pSCSPTR = (PVSHORT)((PVBYTE)pPortBase + SCIF_SCSPTR2_OFFSET);
pHWHead->pRegBase = pRegBase;
pHWHead->pPortBase = pPortBase;
pHWHead->pIntArea1 = (PVSHORT)pIntArea1;
/*Store info for speaking to the MDD callback function */
pHWHead->pMddHead = pMddHead;
/* Now set up remaining fields */
/*
* we need to assign the initial values for the the modem signals.
* as all of the modem signals are active-low, so... we will set these
* values to 1, so we will know if they go low
*/
if ((pHWHead->FlushDone = CreateEvent(0, FALSE, FALSE, NULL)) == NULL)
{
DEBUGMSG(ZONE_INIT, (TEXT("SERIAL : Failed to create FlushDone event\r\n")));
goto error_handler;
}
pHWHead->OpenCount = 0;
/* Initialize Critical Section that is used to check the Modem control signals */
InitializeCriticalSection(&(pHWHead->ModemCritSect));
/* Initialize the critical sections that will guard the parts of
* the transmit buffer.
*/
InitializeCriticalSection(&(pHWHead->TransmitCritSec));
/* we need to setup the structure to report our properties */
pHWHead->CommProp.wPacketLength = 0xffff;
pHWHead->CommProp.wPacketVersion = 0xffff;
pHWHead->CommProp.dwServiceMask = SP_SERIALCOMM;
pHWHead->CommProp.dwReserved1 = 0;
pHWHead->CommProp.dwMaxTxQueue = FIFO_SIZE;
pHWHead->CommProp.dwMaxRxQueue = FIFO_SIZE;
pHWHead->CommProp.dwMaxBaud = BAUD_57600;
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_075 | BAUD_110 | BAUD_150 | BAUD_300 | BAUD_600 |
BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
BAUD_7200 | BAUD_9600 | BAUD_14400 |
BAUD_19200 | BAUD_38400 |
BAUD_57600;
pHWHead->CommProp.dwSettableParams =
SP_BAUD | SP_DATABITS | SP_HANDSHAKING | SP_PARITY |
SP_PARITY_CHECK | SP_RLSD | SP_STOPBITS;
pHWHead->CommProp.wSettableData =
DATABITS_7 | DATABITS_8;
pHWHead->CommProp.wSettableStopParity =
STOPBITS_10 | STOPBITS_20 | PARITY_NONE | PARITY_ODD |
PARITY_EVEN;
pHWHead->CommProp.dwCurrentTxQueue = FIFO_SIZE;
pHWHead->CommProp.dwCurrentRxQueue = FIFO_SIZE;
/*
* we need to setup the SC port so that we can read the
* signals.
*/
WRITE_REGISTER_USHORT(pHWHead->pSCSPTR, SCSPTR_RTS_EN|SCSPTR_BEN|SCSPTR_BDATAH);
WRITE_REGISTER_USHORT(pHWHead->pLSR, 0x0000);
/* we need to ensure that the serial port is turned off, all ints disabled */
WRITE_REGISTER_USHORT(pHWHead->pSCR, SCIF_SCSCR_CKE_0); /* turns everything off */
/* Now we need to set the DTR and RTS so that there is nothing until rewuested*/
SCIF_SetRTS((PVOID)pHWHead);
SCIF_SetDTR((PVOID)pHWHead);
/* DH- always have TE enabled-floating line can cause spurious transmission */
WRITE_REGISTER_USHORT(pHWHead->pSCR,
(READ_REGISTER_USHORT(pHWHead->pSCR) | SCIF_SCSCR_TE));
DEBUGMSG (ZONE_CLOSE,(TEXT("SERIAL : -SCIF_INIT, 0x%X\r\n"), pHWHead));
// Event Object for Polling
pHWHead->hModemLinePollingEvent = CreateEvent(0, FALSE, FALSE, NULL);
if(pHWHead->hModemLinePollingEvent == NULL) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (TEXT("SCIF_INIT: Failed to create hModemLinePollingEvent event.\r\n")));
goto error_handler;
}
// Event Object for Polling for concerning of stop of LinePollingThread
pHWHead->hKillOKEvent = CreateEvent(0, FALSE, FALSE, NULL);
if(pHWHead->hKillOKEvent == NULL) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (TEXT("SCIF_INIT: Failed to create hKillOKEvent event.\r\n")));
goto error_handler;
}
// Create ModemLinePollingThread
ret = InitPollingThread(pHWHead);
if(ret == FALSE) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (TEXT("SCIF_INIT : Fail to create ModemLinePollingThread.\r\n")));
goto error_handler;
}
return (pHWHead);
error_handler:
/* this will handle us bailing on this routine */
if (pHWHead != NULL)
{
if (pHWHead->FlushDone)
CloseHandle(pHWHead->FlushDone);
if(pHWHead->hModemLinePollingEvent)
CloseHandle(pHWHead->hModemLinePollingEvent);
if(pHWHead->hKillOKEvent)
CloseHandle(pHWHead->hKillOKEvent);
VirtualFree(pHWHead, sizeof(SCIF_INFO), MEM_DECOMMIT);
}
if (pRegBase != NULL)
{
VirtualFree((BYTE*)pRegBase, 0, MEM_RELEASE);
}
if (pPortBase != NULL)
{
VirtualFree((BYTE*)pPortBase, 0, MEM_RELEASE);
}
if (pIntArea1 != NULL)
{
VirtualFree((BYTE*)pIntArea1, 0, MEM_RELEASE);
}
return (NULL);
}
/*****************************************************************************
* FUNCTION : SCIF_Deinit()
* DESCRIPTION : Releasees memory for port
* INPUTS : The pointer to the HW struct
* OUTPUTS : none
* DESIGN NOTES :
* CAUTIONS :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -