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

📄 bdihdlc.c

📁 BDI2000 FOR PPC860 固件程序
💻 C
📖 第 1 页 / 共 2 页
字号:
  /* initialize each transmit buffer descriptor */
  for (frame = 0; frame < sccChan.hdlc.txBdNum; frame++) {
    sccChan.hdlc.txBdBase[frame].statusMode  = SCC_HDLC_TX_BD_L | SCC_HDLC_TX_BD_TC;
    sccChan.hdlc.txBdBase[frame].dataLength  = 0;
    sccChan.hdlc.txBdBase[frame].dataPointer = sccChan.hdlc.txBufBase + (frame * SCC_TX_BUFF_SIZE);
  } /* for */

  /* set the last BD to wrap to the first */
  sccChan.hdlc.txBdBase[(frame - 1)].statusMode |= SCC_HDLC_TX_BD_WRAP;

  /* set up receive buffer descriptors */
  sccChan.hdlc.rxBdNum   = SCC_RBD_NUM;
  sccChan.hdlc.rxBdBase  = (SCC_HDLC_BD*)(immrVal + SCC_RBD_OFF);
  sccChan.hdlc.rxBufBase = (u_char*)(SCC_RX_BUFF_ADDR);
  sccChan.hdlc.rxBdNext  = 0;

  /* initialize each receive buffer descriptor */
  for (frame = 0; frame < sccChan.hdlc.rxBdNum; frame++) {
    sccChan.hdlc.rxBdBase[frame].statusMode  = SCC_HDLC_RX_BD_EMPTY | SCC_HDLC_RX_BD_INT;
    sccChan.hdlc.rxBdBase[frame].dataLength  = SCC_RX_BUFF_SIZE;
    sccChan.hdlc.rxBdBase[frame].dataPointer = sccChan.hdlc.rxBufBase + (frame * SCC_RX_BUFF_SIZE);
  } /* for */

  /* set the last BD to wrap to the first */
  sccChan.hdlc.rxBdBase[(frame - 1)].statusMode |= SCC_HDLC_RX_BD_WRAP;

  /* initialize parameter RAM area for this SCC */
  *pRBASE  = SCC_RBD_OFF;
  *pTBASE  = SCC_TBD_OFF;
  *pRFCR   = 0x18;	/* supervisor data access */
  *pTFCR   = 0x18;	/* supervisor data access */
  *pMRBLR  = SCC_RX_BUFF_SIZE;

  *pCMASK  = 0x0000F0B8;
  *pCPRES  = 0x0000FFFF;
  *pDISFC  = 0;
  *pCRCEC  = 0;
  *pABTSC  = 0;
  *pNMARC  = 0;
  *pRETRC  = 0;
  *pMFLR   = SCC_RX_BUFF_SIZE;
  *pRFTHR  = 1;
  *pHMASK  = 0x0000;
  *pHADDR1 = 0x0000;
  *pHADDR2 = 0x0000;
  *pHADDR3 = 0x0000;
  *pHADDR4 = 0x0000;

  /* program the three SCC mode registers: gsmrl, gsmrh, and psmr */
  *pGSMR_L =   M8260_SCC_GSMRL_TPL_16
             | M8260_SCC_GSMRL_TPP_01
             | M8260_SCC_GSMRL_TDCR_X16
             | M8260_SCC_GSMRL_RDCR_X16
             | (4L<<11) | (4L<<8)     /* Manchester encoding */
             | M8260_SCC_GSMRL_HDLC;;
  *pGSMR_H = 0;
  *pPSMR   = SCC_HDLC_PSMR_NOF_0 | SCC_HDLC_PSMR_CRC16;

  /* wait until the CP is clear */
  do {
    M8260_SCC_32_RD((M8260_CPCR (immrVal)), cpcrVal);
  } while (cpcrVal & M8260_CPCR_FLG) ;

  /* Tell CP to initialize tx and rx parameters for SCC */
  cpcrVal = (  M8260_CPCR_OP (M8260_CPCR_RT_INIT)
             | M8260_CPCR_SBC (M8260_CPCR_SBC_SCC1 | (scc * 0x1))
             | M8260_CPCR_PAGE (M8260_CPCR_PAGE_SCC1 | (scc * 0x1))
             | M8260_CPCR_FLG);
  M8260_SCC_32_WR (M8260_CPCR (immrVal), cpcrVal);

  /* clear all events */
  *pSCCE = 0xFFFF; 

  /* enables the transmitter and receiver  */
  *pGSMR_L |= (M8260_SCC_GSMRL_ENT | M8260_SCC_GSMRL_ENR);

  /* unmask interrupt */
  *pSCCM |= SCC_HDLC_SCCX_RXF;

  /* enable SCC interrupts at the SIU Interrupt Controller */
  if      (SCC_NUM == 1) m8260IntEnable(INUM_SCC1);
  else if (SCC_NUM == 2) m8260IntEnable(INUM_SCC2);
  else if (SCC_NUM == 3) m8260IntEnable(INUM_SCC3);
  else if (SCC_NUM == 4) m8260IntEnable(INUM_SCC4);

  intUnlock (oldlevel);	/* UNLOCK INTERRUPTS */
} /* sccInit */


/*******************************************************************************
*
* sccInterrupt - handle an SCC interrupt
*
* This routine is called to handle SCC interrupts.
*/

static void sccInterrupt(WDB_HDLC_PKT_DEV *pPktDev)
{
  UINT16        sccEvent;
  UINT16        rxCount;
  FAST char*	pChar;
  FAST char     rxChar;
  SCC_HDLC_BD*  pBD;


  /* read and clear events */
  sccEvent = *sccChan.pSCCE;
  *sccChan.pSCCE = sccEvent;

  /* handle receive event */
  if (sccEvent & SCC_HDLC_SCCX_RXF) {

    /* process all filled receive buffers */
    pBD = sccChan.hdlc.rxBdBase + sccChan.hdlc.rxBdNext;
    while (    ((pBD->statusMode & SCC_HDLC_RX_BD_EMPTY) == 0)
            && ((pBD->statusMode & SCC_HDLC_RX_BD_INT)   != 0)
          ) {

      /* a valid receive frame */
      if ((pBD->statusMode & HDLC_RX_ERRORS) == 0) {
        struct mbuf* pMbuf = wdbMbufAlloc();;
        if (pMbuf) {
          pBD->statusMode &= ~SCC_HDLC_RX_BD_INT;
          pPktDev->pBD = (void*)pBD;
          wdbMbufClusterInit (pMbuf,
                              pBD->dataPointer,
                              (pBD->dataLength - 2), /* discard CRC */
		              (int (*)())wdbPktFree,
                              (int)pPktDev);
	  (*pPktDev->wdbDrvIf.stackRcv) (pMbuf);  /* invoke callback */
        } /* if */
      } /* if */

      /* discard frame and release buffer */
      if (pBD->statusMode & SCC_HDLC_RX_BD_INT) {
        pBD->dataLength  = 0;
        pBD->statusMode &= SCC_HDLC_RX_BD_WRAP;
        pBD->statusMode |= (SCC_HDLC_RX_BD_EMPTY | SCC_HDLC_RX_BD_INT);
      } /* else */

      /* switch to next buffer */
      pBD->statusMode |= SCC_HDLC_RX_BD_EMPTY;
      sccChan.hdlc.rxBdNext = (sccChan.hdlc.rxBdNext + 1) % sccChan.hdlc.rxBdNum;
      pBD = sccChan.hdlc.rxBdBase + sccChan.hdlc.rxBdNext;

    } /* while */
  } /* if */

} /* sccInterrupt */


/*******************************************************************************
*
* wdbHdlcPktDevInit - init the fast SLIP paket driver
*
* This routine init the WDB agents paket driver.
*
* RETURNS: initialized WDB_SLIP_PKT_DEV structure
*
*/
void wdbHdlcPktDevInit
    (
    WDB_HDLC_PKT_DEV *pPktDev,
    void             (*stackRcv)()
    )
{
  VOIDFUNCPTR*	ivec;

  /* setup driver interface structure */
  pPktDev->wdbDrvIf.mode       = WDB_COMM_MODE_INT;
  pPktDev->wdbDrvIf.mtu        = WDB_HDLC_PKT_MTU;
  pPktDev->wdbDrvIf.stackRcv   = stackRcv;
  pPktDev->wdbDrvIf.devId      = (WDB_HDLC_PKT_DEV *)pPktDev;
  pPktDev->wdbDrvIf.pollRtn    = wdbPktPoll;
  pPktDev->wdbDrvIf.pktTxRtn   = wdbPktTx;
  pPktDev->wdbDrvIf.modeSetRtn = wdbPktModeSet;

  /* init SCC channel in CPM */
  sccInit();

  /* connect interrupt service */
  if      (SCC_NUM == 1) ivec = INUM_TO_IVEC(INUM_SCC1);
  else if (SCC_NUM == 2) ivec = INUM_TO_IVEC(INUM_SCC2);
  else if (SCC_NUM == 3) ivec = INUM_TO_IVEC(INUM_SCC3);
  else if (SCC_NUM == 4) ivec = INUM_TO_IVEC(INUM_SCC4);
  (void)intConnect (ivec, (VOIDFUNCPTR) sccInterrupt, (int)pPktDev);
} /* wdbHdlcPktDevInit */


/******************************************************************************
*
* wdbPktTx - transmit a packet
*
* This routine can only be called by the WDB agent.
*
* RETURNS: OK, or ERROR if a packet is currently being transmitted, or
* the packet is too large to send.
*/

static STATUS wdbPktTx
    (
    void * pDev,
    struct mbuf * pMbuf
    )
{
  int		pktSize;
  u_char        txChar;
  SCC_HDLC_BD*  pTxBD;

  /* copy transmit data to local buffer */
  pTxBD = sccChan.hdlc.txBdBase + sccChan.hdlc.txBdNext;
  if (pTxBD->statusMode & SCC_HDLC_TX_BD_READY) return (ERROR);
  wdbMbufDataGet(pMbuf, pTxBD->dataPointer, WDB_HDLC_PKT_MTU, &pktSize);
  wdbMbufChainFree(pMbuf);

  /* start transmitting */
  pTxBD->dataLength = pktSize;
  sccChan.hdlc.txBdNext = (sccChan.hdlc.txBdNext + 1) % sccChan.hdlc.txBdNum;
  pTxBD->statusMode |= SCC_HDLC_TX_BD_READY;

  return (OK);
} /* wdbPktTx */


/******************************************************************************
*
* wdbPktFree - free the input buffer
*
* This is the callback used to let us know the agent is done with the
* input buffer we loaded it.
*
* RETURNS: N/A
*/

static void wdbPktFree
    (
    void *	pDev
    )
    {
    SCC_HDLC_BD * pBD = ((WDB_HDLC_PKT_DEV*)pDev)->pBD;

    pBD->dataLength  = 0;
    pBD->statusMode &= SCC_HDLC_RX_BD_WRAP;
    pBD->statusMode |= (SCC_HDLC_RX_BD_EMPTY | SCC_HDLC_RX_BD_INT);

    }

/******************************************************************************
*
* wdbPktModeSet - switch driver modes
*
* RETURNS: OK for a supported mode, else ERROR
*/

static STATUS wdbPktModeSet
    (
    void *	pDev,
    uint_t	newMode
    )
    {
    WDB_HDLC_PKT_DEV * pPktDev = pDev;

    if (newMode == WDB_COMM_MODE_INT)
	pPktDev->wdbDrvIf.mode = WDB_COMM_MODE_INT;
    else if (newMode == WDB_COMM_MODE_POLL)
	pPktDev->wdbDrvIf.mode = WDB_COMM_MODE_POLL;
    else
	return (ERROR);

    return (OK);
    }

/******************************************************************************
*
* wdbPktPoll - poll for a packet
*
* This routine polls for a packet. If a packet has arrived it invokes
* the agents callback.
*
* RETURNS: OK if a packet has arrived, else ERROR.
*/

static STATUS wdbPktPoll
    (
    void *	pDev
    )
    {
    WDB_HDLC_PKT_DEV *	pPktDev = pDev;
    struct mbuf * 	pMbuf;

    return (ERROR);
    }



⌨️ 快捷键说明

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