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

📄 sc2440_usb_ser.c

📁 wince 下的bsp测试wince_bspSMDK2440_L35T32.rar
💻 C
📖 第 1 页 / 共 3 页
字号:
	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.

	SC2440_USB_Init(pHWHead);			

	DEBUGMSG (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->pIrqCtrlAddr)
		VirtualFree((PVOID)pHWHead->pIrqCtrlAddr, 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);

	DEBUGMSG (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;

	DEBUGMSG(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;

	DEBUGMSG(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->pIrqCtrlAddr)
		VirtualFree((PVOID)pHWHead->pIrqCtrlAddr, 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);

	DEBUGMSG(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;

	DEBUGMSG(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;

	DEBUGMSG (1, (TEXT("++SerClose\r\n")));

	if (pHWHead->cOpenCount) 
	{
		DEBUGMSG (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)) 
		{

				DEBUGMSG(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..
    
		// Mask interrupts? - No, we wont see any more traffic - MBE.
		//pHWHead->pIrqCtrlAddr->icmr.sp0 = 0;
	}

	DEBUGMSG(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;

	DEBUGMSG(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 SC2440_USB_ accesses between
	// time we set the read address and time we do the actual read in 
	// the loop below.
	EnterCriticalSection(&(pHWHead->HwRegCritSec));
	
	fRXFlag = SC2440_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

	DEBUGMSG(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.
 
	@rdesc The return value is a pointer to the start of the device 
			receive buffer.
*************************************************************************/ 
static
PVOID SerGetRxStart( PVOID   pHead )	// @parm PVOID returned by Serinit.
{
	DEBUGMSG(1, (TEXT("SerGetRxStart\r\n")));   

	return  NULL;
}

/*************************************************************************
	@doc OEM
	@func ULONG | SerGetInterruptType | This function is called
			by the MDD whenever an interrupt occurs.  The return code
			is then checked by the MDD to determine which of the four
			interrupt handling routines are to be called.

	@rdesc This routine returns a bitmask indicating which interrupts
			are currently pending.
*************************************************************************/ 
static
INTERRUPT_TYPE SerGetInterruptType( PVOID pHead ) // Pointer to hardware head
{
	PSER_INFO	pHWHead		= (PSER_INFO)pHead;
	INTERRUPT_TYPE	interrupts=0;
    
	DEBUGMSG(1, (TEXT("++SerGetInterruptType 0x%X\r\n"), pHead));	

	interrupts = SC2440_USB_GetInterruptType(pHWHead);

	if (INTR_LINE & interrupts)
	{
		pHWHead->dConfIdx = 0;
		SignalRemoval(pHWHead);
	}

#ifdef POLL_FOR_DISCONNECT

	//interrupts = HW_GetInterruptType(pHWHead);

	//RETAILMSG(1, (TEXT("interrupts = 0x%x\r\n"), interrupts));

	if (interrupts) 
	{
		pHWHead->wSOFStableCnt = 0;
		//RETAILMSG(1, (TEXT("pHWHead->wSOFStableCnt = 0x%x\r\n"), pHWHead->wSOFStableCnt));
	} 
	else if (pHWHead->dConfIdx && (pHWHead->wPrevSOF == pHWHead->wSOF))
	{
		if (++pHWHead->wSOFStableCnt > SOF_STABLE_MAX)
		{
			//RETAILMSG(1, (TEXT("DCD Dropped due to: wSOFStableCnt: %u\r\n"), pHWHead->wSOFStableCnt));
			pHWHead->dConfIdx = 0;
			SignalRemoval(pHWHead);
		}
	}

#endif

	DEBUGMSG (1, (TEXT("--SerGetInterruptType 0x%X, 0x%X\r\n"),
					pHead, interrupts));
	return interrupts;
}

/*************************************************************************
	@doc OEM
	@func ULONG | SerModemIntr | This routine is called from the MDD
			whenever INTR_MODEM is returned by SerGetInterruptType.

	@rdesc None
*************************************************************************/
static
VOID SerModemIntr( PVOID pHead )               // Hardware Head
{
	PSER_INFO	pHWHead = (PSER_INFO)pHead;
	DWORD		dwModemStatus;

	dwModemStatus = pHWHead->ModemStatus;

	DEBUGMSG(1, (TEXT("+++SerModemIntr\r\n")));  
    
	SC2440_USB_DoEndpoint0(pHWHead, &dwModemStatus);

	if ( pHWHead->dConfIdx ) 
	{
		if ( pHWHead->cOpenCount) 
		{
			// If open, notify app of any control line changes.
			DEBUGMSG(1, (TEXT("Modem Status %2.2X <> %2.2X\r\n"),
					pHWHead->ModemStatus, dwModemStatus));

			if( (pHWHead->ModemStatus & MS_DSR_ON) != (dwModemStatus & MS_DSR_ON) )
				EvaluateEventFlag(pHWHead->pMddHead, EV_DSR);

			if( (pHWHead->ModemStatus & MS_CTS_ON) != (dwModemStatus & MS_CTS_ON) )
				EvaluateEventFlag(pHWHead->pMddHead, EV_CTS);

			if( (pHWHead->ModemStatus & MS_RLSD_ON) != (dwModemStatus & MS_RLSD_ON) )
				EvaluateEventFlag(pHWHead->pMddHead, EV_RLSD);
	
		} else {
			// If RLSD transitioned to active, we need to generate event.
			if( (dwModemStatus & MS_RLSD_ON) && !(pHWHead->ModemStatus & MS_RLSD_ON) ) 
			{

				if ( IsAPIReady(SH_WMGR) ) 
				{
						CeEventHasOccurred (NOTIFICATION_EVENT_RS232_DETECTED, NULL);
				}
				DEBUGMSG (0, (TEXT("Indicated RS232 Cable Event\r\n")));
			}
		}
  	}
  	pHWHead->ModemStatus = dwModemStatus;

	DEBUGMSG(1, (TEXT("---SerModemIntr\r\n")));   
}

/*************************************************************************
	@doc OEM
	@func ULONG | SerLineIntr | This routine is called from the MDD
			whenever INTR_LINE is returned by SerGetInterruptType.

	@rdesc None
*************************************************************************/
static
VOID SerLineIntr( PVOID pHead )               // Hardware Head
{
	PSER_INFO pHWHead = (PSER_INFO)pHead;

	DEBUGMSG(1, (TEXT("SerLineIntr\r\n")));

 	// USB serial doesn't have a concept of anything like the LSR.
	// But since a bus reset is what we sort of equate to DCD, I use
	// this routine to handle USB reset conditions.

	// Note that by the time we get here with an SC2440_USB , we are actually
	//plugged back into the bus. I added some polling code to try and detect
	// detaches sooner
	SC2440_USB_LineIntHandler(pHWHead);  // Re-initialize the hardware    
}

/*************************************************************************
	@doc OEM
	@func ULONG | SerGetRxBufferSize | This function returns
			the size of the hardware buffer passed to the interrupt
			initialize function.  It would be used only for devices
			which share a buffer between the MDD/PDD and an ISR.

	@rdesc This routine always returns 0 for 16550 UARTS.
**************************************************************************/
static
ULONG SerGetRxBufferSize( PVOID pHead )
{
	DEBUGMSG(1, (TEXT("SerGetRxBufferSize\r\n")));  
	return 10280;
}

/*************************************************************************
	@doc OEM
	@func ULONG | SerTXIntr | This routine is called from the new MDD
			whenever INTR_TX is returned by SerGetInterruptType.  It is 
			responsible for loading up the TX FIFO with next block of data.

	@rdesc None
**************************************************************************/
static
VOID SerTxIntr(	PVOID pHead,            // Hardware Head
				PUCHAR pTxBuffer,       // @parm Pointer to receive buffer
				ULONG *pBuffLen	)		// @parm In = max bytes to transmit,
							            //       out = bytes transmitted
{
	PSER_INFO pHWHead = (PSER_INFO)pHead;

	DEBUGMSG(1, (TEXT("SerTxIntr+\r\n")));

	pHWHead->CommErrors &= ~CE_TXFULL;

	SC2440_USB_TxIntHandler(pHWHead, pTxBuffer, pBuffLen);

	DEBUGMSG(1, (TEXT("SerTxIntr-, %d bytes\r\n"), *pBuffLen));  
}

/*************************************************************************
	@doc OEM
	@func BOOL | SerPowerOff | Called by driver to turn off power to 
			serial port.
			Not exported to users, only to driver.
 
	@rdesc This routine returns a status.
 ************************************************************************/
static
BOOL SerPowerOff( PVOID   pHead )      // @parm	PVOID returned by SerInit.
{
	PSER_INFO pHWHead = (PSER_INFO)pHead;
	pHWHead->cOpenCount = 0;

	//RETAILMSG(1,(TEXT("USB : SerPowerOff \r\n")));

/*	
	if ( pHWHead->cOpenCount )
	{
		EvaluateEventFlag( pHWHead->pMddHead, EV_RXFLAG );
	}
	
	return (TRUE);
*/
    return HW_PowerOff(pHead);
	
}

/*************************************************************************
	@doc OEM
	@func BOOL | SerPowerOn | 
			Called by driver to turn on power to serial port.
			Not exported to users, only to driver.
 
	@rdesc This routine returns a status.
 ************************************************************************/
static
BOOL SerPowerOn( PVOID   pHead )      // @parm	PVOID returned by SerInit.
{
	PSER_INFO pHWHead = (PSER_INFO)pHead;

	//RETAILMSG(1,(TEXT("USB : SerPowerOn \r\n")));

    return HW_PowerOn(pHead);
}

/*************************************************************************
	@doc OEM
	@func void | SerClearDtr | This routine clears DTR.

	@rdesc None.
**************************************************************************/
static
VOID SerClearDTR( PVOID   pHead )		// @parm PVOID returned by HWinit.
{
	DEBUGMSG(1, (TEXT("SerClearDTR, 0x%X\r\n"), pHead));
	
	// We don't support DTR emulation.
}

/*************************************************************************
	@doc OEM
	@func VOID | SerSetDTR | This routine sets DTR.
 
	@rdesc None.
**************************************************************************/
static
VOID SerSetDTR( PVOID   pHead )			// @parm PVOID returned by HWinit.
{    
	DEBUGMSG(1, (TEXT("SerSetDTR, 0x%X\r\n"), pHead));

	// We don't support DTR emulation.
}

/*************************************************************************

⌨️ 快捷键说明

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