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

📄 dec21140.c

📁 基于psos操作系统的dec21140驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
  intRESTORE_IEN(ien);

  /*-------------------------------------------------------------------*/
  /* If buffers were attached, issue receive poll demand.              */
  /*-------------------------------------------------------------------*/
  if (attachFlag)
    ioLongWrite(CSR2, 1);
}

/***********************************************************************/
/* RxBufRcv: Process all received packets                              */
/*                                                                     */
/***********************************************************************/
static void RxBufRcv(void)
{
  LAN_RX_BUF *pktAddr;
  mblk_t     *msgBlk;
  frtn_t      frtn;
  ULONG       dataLen, good, status;
  USHORT      type;
  Bool ien;

  for (;;)
  {
    /*-----------------------------------------------------------------*/
    /* Disable Interrupts                                              */
    /*-----------------------------------------------------------------*/
    ien = intCLEAR_IEN();

    /*-----------------------------------------------------------------*/
    /*-----------------------------------------------------------------*/
    INVALIDATE((void *)RxNextBD, 1);

    /*-----------------------------------------------------------------*/
    /* Stop when we hit a descriptor owned by the MAC, or a descriptor */
    /* with a NULL buffer pointer.                                     */
    /*-----------------------------------------------------------------*/
    if ((RxNextBD->status & MAC_OWNS_DESC)
     || (RxNextBD->buffAddr1 == NULL))
    {
      intRESTORE_IEN(ien);
      break;
    }

    /*-----------------------------------------------------------------*/
    /* Per packet initialization.                                      */
    /*-----------------------------------------------------------------*/
    status  = RxNextBD->status;
    dataLen = ((status & LAN_RCVD_FL) >> LAN_RCVD_FLOFF) - 18;
    pktAddr = RxNextBD->buffAddr1;
    good    = TRUE;

    /*-----------------------------------------------------------------*/
    /* Clear buffer address, advance RxNextBD, reenable interrupts.    */
    /*-----------------------------------------------------------------*/
    RxNextBD->buffAddr1 = NULL;
    RxNextBD = RxNextBD->nextDesc;
    intRESTORE_IEN(ien);

    /*-----------------------------------------------------------------*/
    /* Verify received length is legal.                                */
    /*-----------------------------------------------------------------*/
    if (dataLen > 1500)
    {
      dataLen = 1500;
      good = FALSE;
    }

    /*-----------------------------------------------------------------*/
    /* Cache invalidate the received buffer.
    /*-----------------------------------------------------------------*/
    _cache_invalidate((void *)pktAddr, dataLen + 14);

    /*-----------------------------------------------------------------*/
    /* Determine if packet is okay.  Expect to recieve entire packet   */
    /* in one descriptor so first descriptor and last descriptor bits  */
    /* must be set. If so, check for other errors.                     */
    /*-----------------------------------------------------------------*/
    if (RdPciCfg16(CF_STATUS) & (LAN_DS_PER | LAN_DS_SERR | LAN_DS_MA |
                                 LAN_DS_RTA | LAN_DS_STA | LAN_DS_DPAR))
    {
      WrPciCfg16(CF_STATUS, LAN_DS_PER | LAN_DS_SERR | LAN_DS_MA |
                            LAN_DS_RTA | LAN_DS_STA | LAN_DS_DPAR);
      good = FALSE;
    }

    if (((status & LAN_RCVD_FS) == 0) ||
        ((status & LAN_RCVD_LS) == 0) ||
        ((status & (LAN_RCVD_ES | LAN_RCVD_DB | LAN_RCVD_RJ)) != 0))
    {
      good = FALSE;
    }

    /*-----------------------------------------------------------------*/
    /* Update count of packets received with unknown protocol.         */
    /*-----------------------------------------------------------------*/
    type = ntohs(pktAddr->type);
    if ((type != LAN_IP) && (type != LAN_ARP) && (type != LAN_RARP))
      ++InUnknownProtos;

    /*-----------------------------------------------------------------*/
    /* Collect stats for MIB on broadcast and unicast packets.         */
    /*-----------------------------------------------------------------*/
    if ((pktAddr->daddr.word1 == 0xFFFF) &&
        (pktAddr->daddr.word2 == 0xFFFF) &&
        (pktAddr->daddr.word3 == 0xFFFF))
       ++innucastpkts;
    else
       ++InUcastPkts;

    /*-----------------------------------------------------------------*/
    /* If the packet is acceptable, pass it to pNA+.  Otherwise, count */
    /* the receive error and return envelope to the free queue.        */
    /*-----------------------------------------------------------------*/
    if (good == TRUE)
    {
      InOctets += dataLen + 18;

      frtn.free_arg  = (void *)     pktAddr;
      frtn.free_func = (void (*)()) RxBufDetach;

      /*------------------------------------------------------------------*/
      /* Announce packet to pNA if able to create a message block.        */
      /*                                                                  */
      /* NB: the following magic is because both the dec21140 and         */
      /*     pna require longword alignment of their recieve buffers;     */
      /*     after stripping the 14 byte header, the rest of the message  */
      /*     would become unaligned, and therefore the message is shifted */
      /*     over the type field.                                         */
      /*     However, this practice results in copying of all data that   */
      /*     comes in over Ethernet, something we should do without.      */
      /*     Fixing this requires correcting all places in pNA where      */
      /*     longword alignment of incoming packets is assumed.           */
      /*------------------------------------------------------------------*/
      memmove(&pktAddr->type, &pktAddr->data, dataLen);
      msgBlk = NiFuncs.esballoc((void *)&pktAddr->type, dataLen, 0, &frtn);
      if (msgBlk)
      {
        msgBlk->b_wptr += dataLen;
        Announce(type, msgBlk, dataLen, IfNum);
      }
      else
        RxBufDetach(pktAddr);
    }
    else
    {
      ++InErrors;
      RxBufDetach(pktAddr);
    }
  }

  /*-------------------------------------------------------------------*/
  /* Replenish receive descriptor ring's supply of receive buffers.    */
  /*-------------------------------------------------------------------*/
  RxBufAttach();
}

/***********************************************************************/
/* TxBufAttach: Fill transmit descriptor                               */
/*                                                                     */
/* INPUTS: addr = address of buffer 1                                  */
/*         len  = length of buffer 1                                   */
/*         ctrl = control bits for the descriptor                      */
/*         status = status word for descriptor                         */
/*                                                                     */
/* NOTE: Must be called with interrupts disabled                       */
/*                                                                     */
/***********************************************************************/
static void TxBufAttach(void *addr, int len, ULONG ctrl, ULONG status)
{
  /*-------------------------------------------------------------------*/
  /* Flush buffer contents from cache.                                 */
  /*-------------------------------------------------------------------*/
  _cache_copyback(addr, len);

  /*-------------------------------------------------------------------*/
  /* Prepare descriptor and flush contents from cache.                 */
  /*-------------------------------------------------------------------*/
  TxNewBD->buffAddr1 = addr;
  TxNewBD->ctrlNsize = LAN_XMTD_TCH | ctrl | len;
  TxNewBD->status = status;
  COPYBACK((void *)TxNewBD, 1);

  /*-------------------------------------------------------------------*/
  /* Advance transmit descriptor and decrement free descriptor count.  */
  /*-------------------------------------------------------------------*/
  TxNewBD = TxNewBD->nextDesc;
  --TxFreeDesc;
}

/***********************************************************************/
/* TxBufDetach: Reclaim transmit frames that have been transmitted     */
/*                                                                     */
/* OUTPUTS: TxUsedBD is updated                                        */
/*                                                                     */
/* NOTES:   TxUsedBD points to first buffer descriptor of next frame   */
/*          to be reclaimed.                                           */
/*                                                                     */
/***********************************************************************/
static void TxBufDetach(void)
{
  LAN_BUFF_DESC *last_in_frame;
  LAN_TX_HDR    *tx_hdr;
  int i;
  Bool ien;

  ien = intCLEAR_IEN();
  for (;;)
  {
    /*-----------------------------------------------------------------*/
    /* If an ISR came and reclaimed everything already get out!        */
    /*-----------------------------------------------------------------*/
    if ((TxUsedBD == TxNewBD) && (TxFreeDesc == TxNumDesc))
       break;

    /*-----------------------------------------------------------------*/
    /* Find last descriptor used for frame begun at TxUsedBD.          */
    /*-----------------------------------------------------------------*/
    last_in_frame = TxUsedBD;
    INVALIDATE((void *)last_in_frame, 1);
    while ((last_in_frame->ctrlNsize & LAN_XMTD_LS) == 0)
    {
      last_in_frame = last_in_frame->nextDesc;
      INVALIDATE((void *)last_in_frame, 1);
    }

    /*-----------------------------------------------------------------*/
    /* If the last buffer in the current frame has not been sent, we   */
    /* cannot reclaim the buffers and should exit the loop.            */
    /*-----------------------------------------------------------------*/
    if (last_in_frame->status & MAC_OWNS_DESC)
       break;

    /*-----------------------------------------------------------------*/
    /* If an outbound buffer had an error, update MIB statics.         */
    /*-----------------------------------------------------------------*/
    if (last_in_frame->status & LAN_XMTD_ES)
    {
      ++outerrors;

      /*---------------------------------------------------------------*/
      /* If a late collision occurs this could be a sign of problems   */
      /* display an error message.                                     */
      /*---------------------------------------------------------------*/
      if (last_in_frame->status & LAN_XMTD_LC)
        /*Print("Late Collision: %x\n", ++lc_err); */
        ++lc_err;
    }

    /*-----------------------------------------------------------------*/
    /* Frame has been sent.  Set tx_hdr to the transmit header         */
    /* associated with the frame, and return message block triplet.    */
    /*-----------------------------------------------------------------*/
    tx_hdr = TxUsedBD->buffAddr1;
    if (tx_hdr->NoRetFlag == 0)
      NiFuncs.freemsg(tx_hdr->msg_ptr);

    /*-----------------------------------------------------------------*/
    /* Advance TxUsedBD to next descriptor following this frame.       */
    /*-----------------------------------------------------------------*/
    for (i = 0; i < tx_hdr->num_desc; ++i)
    {
      TxUsedBD->buffAddr1 = NULL;
      TxUsedBD = TxUsedBD->nextDesc;
      ++TxFreeDesc;
    }

    /*-----------------------------------------------------------------*/
    /* Finally, return the transmit header to the free list.           */
    /*-----------------------------------------------------------------*/
    tx_hdr->next = TxHdrFreeHead;
    TxHdrFreeHead = tx_hdr;
  }

  intRESTORE_IEN(ien);
}

/***********************************************************************/
/* TxBufThrowAway: Free everything in transmit buffer descriptor ring  */
/*                                                                     */
/***********************************************************************/
static void TxBufThrowAway(void)
{
  Bool ien = intCLEAR_IEN();

  while (TxFreeDesc != TxNumDesc)
  {
    LAN_TX_HDR *tx_hdr;
    int i;

⌨️ 快捷键说明

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