📄 wendyser.c
字号:
{
return (UINT32)NULL;
}
// LAM - Oops, big hole in my MDD. We should have passed the DevIndex or pHWObj pointer
// down into the PDD. But since I didn't, the PDD will have to open up the registry and
// read the DevIndex itself. Oh well, we'll do it right next time.
// See if we have already inited a port on this socket
wCardIndex = MAX_CARDS;
pCardInfo = NULL;
for( i=0; i<MAX_CARDS; i++ )
{
if( CardInfoList[i] )
{
if (CardInfoList[i]->hCardSock.uSocket == hCardSock.uSocket)
{
pCardInfo = CardInfoList[i];
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("Socket 0x%x function x%X already allocated.\r\n"),
pCardInfo->hCardSock.uSocket, pCardInfo->hCardSock.uFunction));
break;
}
}
else
{
// If we found an available slot, remember it.
if( wCardIndex == MAX_CARDS )
wCardIndex = i;
}
}
if( !pCardInfo )
{
if( wCardIndex == MAX_CARDS )
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("Max WendySer card limit reached\r\n")));
return NULL;
}
else
{
// Allocate a new card structure and set up PCMCIA
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("Allocating WendySer card struct at index %d\r\n"),
wCardIndex ));
pCardInfo = (PWENDY_CARD_SER_INFO)LocalAlloc( LMEM_ZEROINIT|LMEM_FIXED ,
sizeof(WENDY_CARD_SER_INFO) );
if ( ! pCardInfo )
return (UINT32)NULL;
CardInfoList[wCardIndex] = pCardInfo;
pCardInfo->dwIndex = wCardIndex; // Remember array index
pCardInfo->hCardSock = hCardSock; // GetCardHandle read this from registry
}
}
// By now, we have either allocated or found our cardInfo struct. Take care of
// all the port specific stuff.
pCardInfo->pMddHead = pMddHead;
pCardInfo->cOpenCount = 0;
pCardInfo->fPowerCycle = FALSE;
// DEBUGMSG (ZONE_INIT ,(TEXT("pHWHead x%X\r\n"), pHWHead));
#pragma message ("should fix this to match capabilities of Wendy")
// Set up our Comm Properties data
pCardInfo->CommProp.wPacketLength = 0xffff;
pCardInfo->CommProp.wPacketVersion = 0xffff;
pCardInfo->CommProp.dwServiceMask = SP_SERIALCOMM;
pCardInfo->CommProp.dwReserved1 = 0;
pCardInfo->CommProp.dwMaxTxQueue = 128;
pCardInfo->CommProp.dwMaxRxQueue = 128;
pCardInfo->CommProp.dwMaxBaud = BAUD_USER;
pCardInfo->CommProp.dwProvSubType = PST_RS232;
pCardInfo->CommProp.dwProvCapabilities =
PCF_DTRDSR | PCF_RLSD | PCF_RTSCTS |
PCF_SETXCHAR |
PCF_INTTIMEOUTS |
PCF_PARITY_CHECK |
PCF_SPECIALCHARS |
PCF_TOTALTIMEOUTS |
PCF_XONXOFF;
pCardInfo->CommProp.dwSettableBaud =
BAUD_300 | BAUD_600 | BAUD_1200 |
BAUD_1800 | BAUD_2400 | BAUD_4800 |
BAUD_7200 | BAUD_9600 | BAUD_14400 |
BAUD_19200 | BAUD_38400 | BAUD_56K |
BAUD_115200 | BAUD_57600 | BAUD_USER;
pCardInfo->CommProp.dwSettableParams =
SP_BAUD | SP_DATABITS | SP_HANDSHAKING | SP_PARITY |
SP_PARITY_CHECK | SP_RLSD | SP_STOPBITS;
pCardInfo->CommProp.wSettableData =
DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8;
pCardInfo->CommProp.wSettableStopParity =
STOPBITS_10 | STOPBITS_20 |
PARITY_NONE | PARITY_ODD | PARITY_EVEN | PARITY_SPACE |
PARITY_MARK;
#if 0
// This is now done on CF_Open
// Lets do the rest of the card initialization
if( !InitPCMCIACard( pCardInfo ) )
{
DEBUGMSG (ZONE_OPEN|ZONE_ERROR, (TEXT("CF_Init - Failed to init card\r\n")));
return (UINT32)NULL;
}
SL_Init( pCardInfo, pCardInfo->pCardIOWin, pCardInfo->IO_Granularity,
EvaluateEventFlag, pCardInfo->pMddHead, NULL);
#endif
DEBUGMSG (ZONE_FUNCTION, (TEXT("-CF_INIT\r\n") ));
return pCardInfo;
}
//
// @doc OEM
// @func ULONG | CF_Close | This routine closes the device identified
// by pHead.
//
// @rdesc The return value is 0 if successful, -1 if failed.
//
ULONG
CF_Close(
PVOID pHead // @parm PVOID returned by CF_Init.
)
{
PWENDY_CARD_SER_INFO pCardInfo = (PWENDY_CARD_SER_INFO)pHead;
ULONG uTries;
ULONG retval = 0;
DEBUGMSG (ZONE_FUNCTION, (TEXT("+CF_CLOSE\r\n") ));
if( pCardInfo->cOpenCount )
{
pCardInfo->cOpenCount--;
if( ! pCardInfo->cOpenCount )
{
// Note: We can not call SL_Close when PCMCIA closes the driver after power cycle.
// because SL_Close accesses IO to mask all the interrupts. Of course at this point
// IO space have disappeared.
// It is OK not to call SL_Close here. Only thing is wrong is OpenCount..
// But we always call SL_Init & SL_Open or SL_Close & SL_Deinit together. And
// SL_Deinit does not check cOpenCount So cOpenCount will be initialed to zero in SL_Init.
if (! pCardInfo->fPowerCycle)
{
// while we are still transmitting, sleep.
uTries = 0;
while ( (uTries++ < 100) &&
!(pCardInfo->ser16950.LSR & SERIAL_LSR_TEMT) )
{
Sleep(10);
}
SL_Close( pCardInfo );
}
// Let ser16550 lib free any resources it may have created.
SL_Deinit( pCardInfo );
// Free up all PCMCIA objects/handles by deregistering
CallCardServices(CardDeregisterClient) (pCardInfo->hCardClient);
}
else
{
// If someone else still has device open, we don't do anything.
DEBUGMSG (ZONE_CLOSE|ZONE_ERROR, (TEXT("CF_CLOSE : Open Count > 1, do nothing\r\n")) );
}
}
else
{
DEBUGMSG (ZONE_CLOSE|ZONE_ERROR, (TEXT("CF_CLOSE : Open Count == 0, not performing close\r\n")) );
retval = (ULONG)-1;
}
DEBUGMSG (ZONE_FUNCTION, (TEXT("+CF_CLOSE\r\n") ));
return retval;
}
//
// @doc OEM
// @func VOID | CF_GetCommProperties | Retrieves Comm Properties.
//
// @rdesc None.
//
VOID
CF_GetCommProperties(
PVOID pHead, // @parm PVOID returned by CF_Init.
LPCOMMPROP pCommProp // @parm Pointer to receive COMMPROP structure.
)
{
PWENDY_CARD_SER_INFO pCardInfo = (PWENDY_CARD_SER_INFO)pHead;
memcpy(pCommProp, &pCardInfo->CommProp, sizeof(COMMPROP));
return;
}
//
// @doc OEM
// @func BOOL | CF_PowerOff |
// Called by driver to turn off power to serial port.
//
// @rdesc TRUE if success, FALSE if fail.
//
BOOL
CF_PowerOff(
PVOID pHead // @parm PVOID returned by CF_Init.
)
{
return TRUE;
}
//
// @doc OEM
// @func BOOL | CF_PowerOn |
// Called by driver to turn on power to serial port.
//
// @rdesc TRUE if success, FALSE if fail.
//
BOOL
CF_PowerOn(
PVOID pHead // @parm PVOID returned by CF_Init.
)
{
PWENDY_CARD_SER_INFO pCardInfo = (PWENDY_CARD_SER_INFO)pHead;
pCardInfo->fPowerCycle = TRUE;
return TRUE;
}
//
// @doc OEM
// @func BOOL | CF_EnableIR | This routine enables the ir.
//
// @rdesc Returns FALSE since IR not supported on PCMCIA.
//
BOOL
CF_EnableIR(
PVOID pHead, // @parm PVOID returned by CF_init.
ULONG BaudRate // @parm BaudRate
)
{
return FALSE;
}
//
// @doc OEM
// @func BOOL | CF_DisableIR | This routine disables the ir.
//
// @rdesc Returns TRUE if successful, FALSE if failed.
//
BOOL
CF_DisableIR(
PVOID pHead // @parm PVOID returned by CF_init.
)
{
return TRUE;
}
//
// @doc OEM
// @func BOOL | CF_Deinit | This routine disables the ir.
//
// @rdesc Returns TRUE if successful, FALSE if failure.
//
BOOL
CF_Deinit(
PVOID pHead // @parm PVOID returned by CF_init.
)
{
PWENDY_CARD_SER_INFO pCardInfo = (PWENDY_CARD_SER_INFO)pHead;
if ( !pCardInfo )
return FALSE;
// Make sure device is closed before doing DeInit
while( pCardInfo->cOpenCount )
CF_Close( pCardInfo );
// Let ser16550 lib free any resources it may have created.
// These next 2 calls are now done in CF_Close, to match the SL_Init in CF_Open
// SL_Deinit( pCardInfo );
// Free up all PCMCIA objects/handles by deregistering
// CallCardServices(CardDeregisterClient) (pCardInfo->hCardClient);
CardInfoList[pCardInfo->dwIndex] = NULL;
LocalFree(pCardInfo);
return TRUE;
}
//
// @doc OEM
// @func BOOL | CF_Open | This routine opens the port.
//
// @rdesc Returns TRUE if successful, FALSE otherwise.
//
BOOL
CF_Open(
PVOID pHead // @parm PVOID returned by I_init.
)
{
PWENDY_CARD_SER_INFO pCardInfo = (PWENDY_CARD_SER_INFO)pHead;
STATUS status;
DEBUGMSG (ZONE_OPEN|ZONE_FUNCTION, (TEXT("+CF_OPEN - port\r\n")));
// Lets do the rest of the card initialization
if( !InitPCMCIACard( pCardInfo ) )
{
DEBUGMSG (ZONE_OPEN|ZONE_ERROR, (TEXT("CF_OPEN - Failed to init card\r\n")));
return FALSE;
}
// Init 16550 info. Note that we do both SL_INIT and SL_OPEN
// This is an unfortunate side effect of PCMCIA. As soon as
// I do a CardRequestConfig, I start sucking power. So we postpone
// that till here (in the open). But, SL_INIT needs our card
// address space in his init routine, and we don't get the address
// till after the request config. So till we come up with a better
// idea for power enable/disable on PCMCIA, we will have to couple
// SL_INIT and SL_OPEN.
SL_Init( pCardInfo, pCardInfo->pCardIOWin, (UINT8)(pCardInfo->IO_Granularity),
EvaluateEventFlag, pCardInfo->pMddHead, NULL);
DEBUGMSG (ZONE_INIT, (TEXT("CF_OPEN - Init 16550 data (addr x%X)\r\n"),
pCardInfo->pCardIOWin ));
// This will be set by ser16550.c in SL_Open() to ID_16550 or ID_16950
//pCardInfo->ser16550.ChipID = CHIP_ID_16550;
// This is kind of interesting....SL_Open will enable the RDA, RLS and MS interrupts.
// Since power to the UART is not cycled between CF_Open/CF_Close calls, it is possible
// for the UART to have some pending interrupt state, such as characters to be read.
// If the UART INTs are enabled before we have registered for CardService interrupts,
// the LAN driver gets the interrupt but never clears it and the H/PC is hung.
// This code will make an attempt to clear any pending interrupt state in the uart, then
// register to get interrupts before calling SL_OPEN.
// Additionally, we should reset the uart. LLO
//ResetUart(pCardInfo);
#if 0
{
PSER16950_INFO pHWHead = (PSER16950_INFO)pCardInfo;
BYTE value;
try
{
OUTB(pHWHead, pIIR_FCR, SERIAL_FCR_RCVR_RESET | SERIAL_FCR_TXMT_RESET);
value = INB(pHWHead, pMSR);
value = INB(pHWHead, pData);
value = INB(pHWHead, pLSR);
#if 1
value = INB(pHWHead, pIIR_FCR);
while ((value = INB(pHWHead, pLSR)) & 1)
{
value = INB(pHWHead, pData);
}
value = INB(pHWHead, pData);
#endif
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just get out of here.
}
}
#endif
// Register to receive PCMCIA interrupts for this card
status = CallCardServices(CardRequestIRQ) (pCardInfo->hCardClient,
pCardInfo->hCardSock,
(CARD_ISR)WendySerialEventHandler,
(UINT32)pCardInfo);
DEBUGMSG (ZONE_INIT, (TEXT("RequestIRQ returned 0x%X\r\n"),
status ));
// OK, the device is open, so increment the counter.
pCardInfo->cOpenCount++;
SL_Open( pCardInfo );
if (!(pCardInfo->cOpenCount)) { // If it it first open. Clean the flag
pCardInfo->fPowerCycle = FALSE;
}
return TRUE;
}
const
HW_VTBL CFIoVTbl = {
CF_Init, /* (*HWInit) */
CF_Deinit, /* (*HWDeinit) */
CF_Open, /* (*HWOpen) */
CF_Close, /* (*HWClose) */
SL_RxIntr, /* (*HWGetBytes) */
SL_GetRxStart, /* (*HWGetRxStart) */
SL_GetInterruptType, /* (*HWGetIntrType) */
SL_OtherIntr, /* (*HWOtherIntrHandler) */ /* this one gets calles when DSR,CTS,DCD,RING change */
SL_LineIntr, /* (*HWLineIntrHandler) */
SL_GetRxBufferSize, /* (*HWGetRxBufferSize) */
SL_TxIntr, /* (*HWTxIntrHandler) */
SL_PutBytes, /* (*HWPutBytes) */
CF_PowerOff, /* (*HWPowerOff) */
CF_PowerOn, /* (*HWPowerOn) */
SL_ClearDTR, /* (*HWClearDTR) */
SL_SetDTR, /* (*HWSetDTR) */
SL_ClearRTS, /* (*HWClearRTS) */
SL_SetRTS, /* (*HWSetRTS) */
CF_EnableIR, /* (*HWEnableIR) */
CF_DisableIR, /* (*HWDisableIR) */
SL_ClearBreak, /* (*HWClearBreak) */
SL_SetBreak, /* (*HWSetBreak) */
SL_XmitComChar, /* (*HWXmitComChar) */
SL_GetStatus, /* (*HWGetStatus) */
SL_Reset, /* (*HWReset) */
SL_GetModemStatus, /* (*HWGetModemStatus) */
CF_GetCommProperties, /* (*HWGetCommProperties) */
SL_PurgeComm, /* (*HWPurgeComm) */
SL_SetDCB, /* (*HWSetDCB) */
SL_SetCommTimeouts, /* (*HWSetCommTimeouts) */
SL_Ioctl}; /* (*HWIoctl) */
extern const
DEVICE_LIST CFIoDL; // forward reference, declared below
HWOBJ CFIoObj = { (PDEVICE_LIST) &CFIoDL,
THREAD_IN_PDD, // Actually a callback for PCMCIA, no thread
0, // No SYSINTR for MDD to worry about.
NULL,
(PHW_VTBL) &CFIoVTbl};
const
PHWOBJ rgpHWObjects[1] = { &CFIoObj };
const
DEVICE_LIST CFIoDL = {"WendySer.dll", 1, (PHWOBJ *) rgpHWObjects};
PDEVICE_LIST
GetSerialObject(
VOID
)
{
#ifdef XDEBUG
extern DBGPARAM dpCurSettings;
dpCurSettings.ulZoneMask = 0xc0c3;
#endif
return ( (PDEVICE_LIST) &CFIoDL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -