📄 sc2410_usb_ser.c
字号:
regError = RegQueryValueEx( hKey,
SC2400USB_REG_IOBASE_VAL_NAME,
NULL,
NULL,
(LPBYTE)(&pHWHead->dwIOBase),
&dwDataSize);
}
if (regError == ERROR_SUCCESS)
{
dwDataSize = SC2400USB_REG_DMANUM_VAL_LEN;
regError = RegQueryValueEx( hKey,
SC2400USB_REG_DMANUM_VAL_NAME,
NULL,
NULL,
(LPBYTE)(&pHWHead->dwDMANum),
&dwDataSize);
}
if (regError == ERROR_SUCCESS)
{
dwDataSize = SC2400USB_REG_IOLEN_VAL_LEN;
regError = RegQueryValueEx( hKey,
SC2400USB_REG_IOLEN_VAL_NAME,
NULL,
NULL,
(LPBYTE)(&pHWHead->dwIOLen),
&dwDataSize);
}
RegCloseKey (hKey);
if (regError != ERROR_SUCCESS)
{
SERDMSG(1,(TEXT("Failed to get serial registry values, Error 0x%X\r\n"),
regError));
return (FALSE);
}
SERDMSG(1,(TEXT("****SerInit - Devindex %d, IRQ %d, IOB %X, IOLen %X, DMANum %x \r\n"),
pHWHead->dwDevIndex,
pHWHead->dwIRQ,
pHWHead->dwIOBase,
pHWHead->dwIOLen,
pHWHead->dwDMANum));
SERDMSG(1,(TEXT("SerInit - End\r\n")));
return (TRUE);
}
/*************************************************************************
@doc OEM
@func PVOID | SerInit | Initializes device identified by argument.
* 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.
************************************************************************/
static
PVOID SerInit( ULONG Identifier, // @parm Device identifier.
PVOID pMddHead, // @parm First argument to mdd callbacks.
PHWOBJ pHWObj ) // @parm Pointer to our own HW OBJ for this device
{
PSER_INFO pHWHead;
PHYSICAL_ADDRESS PhysicalAddress = {0,0};
#ifdef DEBUG
dpCurSettings.ulZoneMask = 0;
#endif
SERDMSG (1, (TEXT("++SerInit %X\r\n"), pMddHead ));
// Allocate for our main data structure and one of it's fields.
pHWHead = (PSER_INFO)LocalAlloc( LPTR, sizeof(SER_INFO) );
if ( !pHWHead )
goto ALLOCFAILED;
if (!Ser_GetRegistryData(pHWHead, (LPCTSTR)Identifier))
{
SERDMSG (1,(TEXT("SerInit - Unable to read registry data. Failing Init !!! \r\n")));
goto ALLOCFAILED;
}
SERDMSG(1, (TEXT("Before :pHWHead\r\n")));
// Create our interrupt event.
pHWHead->hSerialEvent = CreateEvent(0,FALSE,FALSE,NULL);
SERDMSG(1, (TEXT("After :pHWHead\r\n")));
// Initialize our critical sections
InitializeCriticalSection(&(pHWHead->TransmitCritSec));
InitializeCriticalSection(&(pHWHead->HwRegCritSec));
SERDMSG(1, (TEXT("Before :SerUSBInternalMapRegisterAddresses\r\n")));
SerUSBInternalMapRegisterAddresses(pHWHead);
SERDMSG(1, (TEXT("Before :InitUsbdDriverGlobals\r\n")));
if(!InitUsbdDriverGlobals(pHWHead)) //:-)
goto ALLOCFAILED;
SERDMSG(1, (TEXT("Before :UsbdAllocateVm\r\n")));
if(!UsbdAllocateVm()) //:-)
goto ALLOCFAILED;
pHWHead->pMddHead = pMddHead;
pHWHead->cOpenCount = 0;
pHWHead->pHWObj = pHWObj;
pHWHead->wSOFStableCnt = 0;
// 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 = 64;
pHWHead->CommProp.dwMaxRxQueue = 64;
pHWHead->CommProp.dwMaxBaud = BAUD_115200;
pHWHead->CommProp.dwProvSubType = PST_RS232;
pHWHead->CommProp.dwProvCapabilities = PCF_RLSD |
PCF_SETXCHAR |
PCF_INTTIMEOUTS |
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_56K | BAUD_128K |
BAUD_115200 | BAUD_57600 | BAUD_USER;
pHWHead->CommProp.dwSettableParams = SP_BAUD | SP_RLSD ;
pHWHead->CommProp.wSettableData = DATABITS_8;
pHWHead->CommProp.wSettableStopParity = STOPBITS_10 | STOPBITS_20 |
PARITY_NONE | PARITY_ODD |
PARITY_EVEN | PARITY_SPACE |
PARITY_MARK;
pHWHead->fIRMode = FALSE; // Select wired by default
pHWHead->State = IDLE;
// Here is where we do any actual init for the hardware. In the case of
// USB function, we mostly just validate the hardware and then enable
// interrupts. When we detect the presence of the bus, GetIntr will take
// care of identify us to the host and kicking things off.
SC2400_USB_Init(pHWHead);
SERDMSG (1, (TEXT("--SerInit - %X\r\n"), pHWHead ));
return (pHWHead);
ALLOCFAILED:
// Unmap any memory areas that we may have mapped.
if ( pHWHead->pUSBCtrlAddr)
VirtualFree((PVOID)pHWHead->pUSBCtrlAddr, 0, MEM_RELEASE);
/*
if ( pHWHead->pCLKPWR)
VirtualFree((PVOID)pHWHead->pCLKPWR, 0, MEM_RELEASE);
*/
LocalFree(pHWHead);
// Free any critical sections we have allocated
DeleteCriticalSection(&(pHWHead->TransmitCritSec));
DeleteCriticalSection(&(pHWHead->HwRegCritSec));
// And free the context data structure
LocalFree(pHWHead);
SERDMSG (1,(TEXT("--SerInit - %X\r\n"), pHWHead ));
return (NULL);
}
/*************************************************************************
@doc OEM
@func PVOID | SerPostInit | Performs final hardware initialization.
************************************************************************/
static
BOOL SerPostInit(PVOID pHead) // @parm PVOID returned by SerInit.
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
SERDMSG(1, (TEXT("+++SerPostInit\r\n")));
// We use a PDD specific thread, rather than the default thread provided
// by the MDD.
StartEventThread( pHWHead );
// Enable interrupts after thread is started - DAL
// ....
return TRUE;
}
/*************************************************************************
@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;
SERDMSG(1, (TEXT("+SerDeinit\r\n")));
// Disable interrupts
// ...
if ( !pHWHead )
return (FALSE);
// Make sure device is closed before doing DeInit
if ( pHWHead->cOpenCount )
SerClose( pHead );
if ( pHWHead->pUSBCtrlAddr)
VirtualFree((PVOID)pHWHead->pUSBCtrlAddr, 0, MEM_RELEASE);
/*
if ( pHWHead->pCLKPWR)
VirtualFree((PVOID)pHWHead->pCLKPWR, 0, MEM_RELEASE);
*/
UsbdDeallocateVm(); //:-)
// Free any critical sections we have allocated
DeleteCriticalSection(&(pHWHead->TransmitCritSec));
DeleteCriticalSection(&(pHWHead->HwRegCritSec));
// Free the HWObj allocated in GetSerialObject
LocalFree(pHWHead->pHWObj);
LocalFree(pHWHead);
SERDMSG(1, (TEXT("-SerDeinit\r\n")));
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;
SERDMSG(1,
(TEXT("SerOpen+\r\n")));
// Disallow multiple simultaneous opens
if (pHWHead->cOpenCount)
return (FALSE);
pHWHead->cOpenCount++;
#ifdef POLL_FOR_DISCONNECT
// Yuck. We want to poll for detaches when the device is open.
// But right now, the IST is in a wait infinite. Spoof an interrupt
// to let him know we have been opened and he needs to start polling.
SetEvent(pHWHead->hSerialEvent);
#endif
return (TRUE);
}
/*************************************************************************
@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;
SERDMSG (1, (TEXT("++SerClose\r\n")));
if (pHWHead->cOpenCount)
{
SERDMSG (1, (TEXT("SerClose, closing device\r\n")));
pHWHead->cOpenCount--;
#ifdef TODO
// Do we need something similar on USB???
// while we are still transmitting, sleep.
uTries = 0;
while ( ((pHWHead->ser16550.IER = READ_PORT_UCHAR(pHWHead->ser16550.pIER))
& SERIAL_IER_THR) && // indicates TX in progress
(uTries++ < 100) && // safety net
// indicates FIFO not yet empty
!(pHWHead->ser16550.LSR & SERIAL_LSR_TEMT))
{
SERDMSG(1, (TEXT("SerClose, TX in progress, IER 0x%X, LSR 0x%X\r\n"),
*pHWHead->ser16550.pIER, pHWHead->ser16550.LSR));
Sleep(10);
}
#endif
// TODO - When the device is closed, should power it down or somehow try to
// let the desktop know that we aren't doing anything with any data that it
// might be sending our way..
}
SERDMSG(1,(TEXT("--SerClose\r\n")));
return (0);
}
/*************************************************************************
@doc OEM
@func ULONG | SerRxIntr | This routine gets several characters from the
hardware receive buffer and puts them in a buffer provided via the se-
cond argument. It returns the number of bytes lost to overrun.
@rdesc The return value indicates the number of overruns detected.
The actual number of dropped characters may be higher.
**************************************************************************/
static
ULONG SerRxIntr(PVOID pHead, // @parm Pointer to hardware head
PUCHAR pRxBuffer, // @parm Pointer to receive buffer
ULONG *pBufflen ) // @parm In = max bytes to read, out = bytes read
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
ULONG RetVal = 0;
ULONG TargetRoom = *pBufflen;
BOOL fRXFlag = FALSE;
BOOL fReplaceparityErrors = FALSE;
BOOL fNull;
UCHAR cEvtChar;
PUCHAR pRxOrig = pRxBuffer;
SERDMSG(1, (TEXT("++SerRxIntr %d\r\n"), *pBufflen));
cEvtChar = pHWHead->dcb.EvtChar;
fNull = pHWHead->dcb.fNull;
if( pHWHead->dcb.fErrorChar && pHWHead->dcb.fParity )
fReplaceparityErrors = TRUE;
// Protect the following from collision on hardware registers.
// In particular, we can't let anyone else do SC2400_USB_ accesses between
// time we set the read address and time we do the actual read in
// the loop below.
EnterCriticalSection(&(pHWHead->HwRegCritSec));
fRXFlag = SC2400_USB_RxIntHandler(pHWHead, pRxBuffer, pBufflen);
LeaveCriticalSection(&(pHWHead->HwRegCritSec));
// if we saw one (or more) EVT chars, then generate an event
if( fRXFlag )
EvaluateEventFlag( pHWHead->pMddHead, EV_RXFLAG );
#ifdef DEBUG
if( ZONE_RXDATA )
CELOGDATA(1, CELID_RAW_UCHAR, pRxOrig, (WORD)*pBufflen, 1, CELZONE_MISC);
#endif
SERDMSG(1, (TEXT("--SerRxIntr - rx %d, drop %d.\r\n"),
*pBufflen,
pHWHead->DroppedBytes));
RetVal = pHWHead->DroppedBytes;
pHWHead->DroppedBytes = 0;
return RetVal;
}
/*************************************************************************
@doc OEM
@func PVOID | SerGetRxStart | This routine returns the start of the
hardware receive buffer. See SerGetRxBufferSize.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -