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

📄 bvd_udc_ser.c

📁 Xcale270Bsp包,wince平台
💻 C
📖 第 1 页 / 共 3 页
字号:
    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
    
  // 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 identifying us to the host and kicking things off.

  SA_USB_Init(pHWHead);			

  DEBUGMSG (ZONE_INIT|ZONE_FUNCTION,
	    (TEXT("-SerInit - %X\r\n"), 
	     pHWHead ));

  return (pHWHead);

 ALLOCFAILED:
  // Unmap any memory areas that we may have mapped.
  if ( pHWHead->pUDCRegs)
    VirtualFree((PVOID)pHWHead->pUDCRegs, 0, MEM_RELEASE);
  if ( pHWHead->pINTCRegs)
    VirtualFree((PVOID)pHWHead->pINTCRegs, 0, MEM_RELEASE);
  LocalFree(pHWHead);

  //RETAILMSG(1, (TEXT("SerInit - Exiting with ERROR\r\n")))

  // Free any critical sections we have allocated
  DeleteCriticalSection(&(pHWHead->TransmitCritSec));
  DeleteCriticalSection(&(pHWHead->HwRegCritSec));

  // And free the context data structure
  LocalFree(pHWHead);

  DEBUGMSG (ZONE_INIT|ZONE_FUNCTION,
	    (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( ZONE_INIT|ZONE_FUNCTION,
	    (TEXT("SerPostInit+\r\n")));

  // We use a PDD specific thread, rather than the default thread provided
  // by the MDD.
  StartEventThread( pHWHead );

  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( ZONE_INIT|ZONE_FUNCTION,
	    (TEXT("+SerDeinit\r\n")));

  if ( !pHWHead )
    return (FALSE);

  // Make sure device is closed before doing DeInit
  if ( pHWHead->cOpenCount )
    SerClose( pHead );

  SA_USB_DeInit(pHWHead);

  if ( pHWHead->pUDCRegs)
    VirtualFree((PVOID)pHWHead->pUDCRegs, 0, MEM_RELEASE);
  if ( pHWHead->pINTCRegs)
    VirtualFree((PVOID)pHWHead->pINTCRegs, 0, MEM_RELEASE);

  // 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( ZONE_INIT|ZONE_FUNCTION,
	    (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( ZONE_INIT | ZONE_FUNCTION,
	    (TEXT("SerOpen+\r\n")));

  // Disallow multiple simultaneous opens
  if ( pHWHead->cOpenCount )
    return (FALSE);
    
  pHWHead->cOpenCount++;


  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 (ZONE_CLOSE | ZONE_FUNCTION,
	    (TEXT("+SerClose\r\n")));

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

    // NOTE - Depending on your chipset, you may need to power down the 
    // USB chipset here.  Check your datasheets.

    // Do we want to disable the UDC (UDE=0) at this point?
    // or is it enough on Cable Disconnect?  Not sure how Com_Open relates with
    // USB Serial Host driver...
    //
    
  }

  DEBUGMSG (ZONE_CLOSE | ZONE_FUNCTION,
	    (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 second 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
    )
{
//    PSER16550_INFO   pHWHead	= (PSER16550_INFO)pHead;
  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 (ZONE_FUNCTION,
	    (TEXT("+SerRxIntr %d\r\n"),
	     *pBufflen));

  cEvtChar = pHWHead->dcb.EvtChar;
  fNull = pHWHead->dcb.fNull;
  if( pHWHead->dcb.fErrorChar && pHWHead->dcb.fParity )
    fReplaceparityErrors = TRUE;
  
//NKDbgPrintfW(TEXT("LenInRx: %02d\r\n"), *pBufflen);

  // Protect the following from collision on hardware registers.
  // In particular, we can't let anyone else do SA_USB_ accesses between
  // time we set the read address and time we do the actual read in 
  // the loop below.
  EnterCriticalSection(&(pHWHead->HwRegCritSec));
	
  fRXFlag = SA_USB_RxIntHandler(pHWHead, pRxBuffer, pBufflen);

  LeaveCriticalSection(&(pHWHead->HwRegCritSec));

//NKDbgPrintfW(TEXT("LenOutRx: %02d\r\n"), *pBufflen);

  // if we saw one (or more) EVT chars, then generate an event
  if( fRXFlag )
  {
//	NKDbgPrintfW(TEXT("EvCh: %02x\r\n"), pHWHead->dcb.EvtChar);
    EvaluateEventFlag( pHWHead->pMddHead, EV_RXFLAG );
  }	

#ifdef DEBUG
  if( ZONE_RXDATA )
    CELOGDATA(1, CELID_RAW_UCHAR, pRxOrig, (WORD)*pBufflen, 1, CELZONE_MISC);
#endif

  DEBUGMSG (ZONE_WARN|ZONE_READ,
	    (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 (ZONE_FUNCTION,
	    (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 (ZONE_FUNCTION,
	    (TEXT("+SerGetInterruptType 0x%X\r\n"), pHead));

  DEBUGMSG( ZONE_THREAD, (TEXT("Stat %X, Addr %X, dConfIdx %X\r\n"), 
			  pHWHead->cIntStat,
			  pHWHead->dAddress,
			  pHWHead->dConfIdx));	

  interrupts = SA_USB_GetInterruptType(pHWHead);

  DEBUGMSG (ZONE_FUNCTION,
	    (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 (ZONE_FUNCTION,
	    (TEXT("SerModemIntr+\r\n")));   
    
  ServiceEP0(pHWHead, &dwModemStatus);

  if ( pHWHead->dConfIdx ) {
    if ( pHWHead->cOpenCount) {
      // If open, notify app of any control line changes.
      DEBUGMSG (ZONE_EVENTS,
		(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 (1|ZONE_EVENTS,
		  (TEXT("Indicated RS232 Cable Event\r\n")));
      }
    }
  }
  pHWHead->ModemStatus = dwModemStatus;
}

//
// @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 (ZONE_FUNCTION,
	    (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 SA_USB , we are actually
  // plugged back into the bus.
  //
  SA_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 (ZONE_FUNCTION,
	    (TEXT("SerGetRxBufferSize\r\n")));
  
  //Change default buffer size
  return 0x2000;
  //return 0;
}

//
// @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 (ZONE_WRITE|ZONE_FUNCTION,
	    (TEXT("SerTxIntr+\r\n")));

  pHWHead->CommErrors &= ~CE_TXFULL;
  
  // Go send the data.
  SA_USB_TxIntHandler(pHWHead, pTxBuffer, pBuffLen);

  DEBUGMSG (ZONE_WRITE|ZONE_FUNCTION,
	    (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;

  /* Note:  No debug messages in power handlers!  */

  SA_USB_PowerOff(pHWHead);

  return (TRUE);
}

/*
 @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;

  /* Note:  No debug messages in power handlers!  */

  SA_USB_PowerOn(pHWHead);

  return (TRUE);
}

//
// @doc OEM
// @func void | SerClearDtr | This routine clears DTR.
//
// @rdesc None.
//
static
VOID SerClearDTR(
    PVOID   pHead // @parm PVOID returned by HWinit.
    )
{
  DEBUGMSG (ZONE_FUNCTION,
	    (TEXT("SerClearDTR, 0x%X\r\n"),
	     pHead));

  // We don't support DTR emulation.

⌨️ 快捷键说明

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