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

📄 net_3c59x.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 4 页
字号:
      continue;    }    if (ni->updateStats != UpdateStatistics) {      continue;    }    ni_Attach(ni);  }  return true;}#define SUPER_SLOW_MOstatic voidHydrant(Timer* t){  NetInterface *ni = (NetInterface *) t->client_ptr;  SetWindow(ni, 1);#if 0#ifdef BOOMERANG  MsgLog::dprintf(false, "%s: UpStatus 0x%08x DnStatus 0x%08x\n",		  ni->name,		  in32(ni->ioAddr + Wn1UpStatus),		  in32(ni->ioAddr + Wn1DnStatus));#endif  MsgLog::dprintf(false, "%s: elink (xmit?) timeout. TxStatus: 0x%02x"		  " Status 0x%04x\n txFifo room %d rxStatus 0x%x curInts 0x%x\n",		  ni->name,		  in8(ni->ioAddr + Wn1TxStatus),		  in16(ni->ioAddr + El3Status),		  in16(ni->ioAddr + Wn1TxFree),		  in16(ni->ioAddr + Wn1RxStatus),		  ni->curInts);#endif  OutCmd(ni, ReqIntr);	/* long-running cmd */  ni->stats.txWatchdog++;  OutCmd(ni, TxReset, true);	/* long-running cmd */  OutCmd(ni, TxEnable);  ni->wrQ.WakeAll();}inline static voidClearTxStatusStack(NetInterface *ni){  uint16_t tx_status = 0;  int i = 4;  while (--i > 0  && (tx_status = in8(ni->ioAddr + Wn1TxStatus)) > 0) {#if 1    if (tx_status & 0x3C) {		/* A Tx-disabling error occurred.  */      if (vortex_debug > 2)	MsgLog::dprintf(true, "%s: Tx error, status 0x%2x.\n",			ni->name, tx_status);      if (tx_status & 0x04) {#if 0	ni->stats.txFifoErrors++;#endif	vortex_private *vp = (vortex_private *) ni->private;	vp->txStartThresh += 16;	MsgLog::printf("!!Growing start threshold\n");	OutCmd(ni, SetTxStartThresh | vp->txStartThresh);      }      if (tx_status & 0x38)	ni->stats.txAbort++;      if (tx_status & 0x34)	OutCmd(ni, TxReset, true);      OutCmd(ni, TxEnable);    }#else    /* This generates printfs on collisions, which happens with acks.     * MsgLog::printf("3c509: tx_status = 0x%08x\n", tx_status);     */    if (tx_status & (TxsJabber | TxsUnderrun | TxsCollisions))      ni->stats.txAbort++;    if (tx_status & (TxsJabber|TxsUnderrun))      OutCmd(ni, TxReset, true);    if (tx_status & (TxsJabber|TxsUnderrun|TxsCollisions|TxsStatusOverflow))      OutCmd(ni, TxEnable);#endif    /* Pop the status stack. */    out8(0x00, ni->ioAddr + Wn1TxStatus);   }}inline voidIoWrPkt(NetInterface *ni, uint8_t *buf, uint32_t len){  /* Begin sending the packet, but be careful about send buffer   * alignment:   */  assert (((uint32_t)buf&3) == 0);  /* sndBufPtr is now word aligned.  Send as many words as we can: */  outs32(ni->ioAddr + Wn1TxFifo, buf, (len+3) >> 2);}static voidWritePacket(NetInterface * ni, Invocation& inv){  uint64_t dw = rdtsc();    ClearTxStatusStack(ni);#ifdef SUPER_SLOW_MO  /* I/O version -- do this first to get something running quickly. */    /* See if the TX Fifo has room for the outbound packet: */  uint16_t txFree = in16(ni->ioAddr + Wn1TxFree);#if 0  MsgLog::printf("inv.entry.len=%d\n", inv.entry.len);#endif  bool haveRoom = (txFree >= inv.entry.len);    if (inv.entry.len < MIN_ENET_PACKET_SZ ||      inv.entry.len > MAX_ENET_PACKET_SZ) {    /* input buffer not aligned properly. */    inv.exit.code = RC_RequestError;    return;  }  if (haveRoom) {    /* Put out the doubleword header... */    out32(inv.entry.len, ni->ioAddr + Wn1TxFifo);    IoWrPkt(ni, inv.entry.data, inv.entry.len);    inv.exit.code = RC_OK;    uint64_t ew = rdtsc();    ew -= dw;    ni->stats.txCpuCycles += ew;  }#else#endif  /* Sleep if we are supposed to: */  if (!haveRoom) {#ifdef ENET_DEBUG    MsgLog::printf("net_wr: txFree: %d, pkt-len %d, sleeping\n",		   txFree, inv.entry.len);#endif    /* Wake us up when there is sufficient room in the TX FIFO for a     * complete enet packet:     */    ni->stats.wrStall++;    ni->watchDog.Disarm();    ni->watchDog.WakeupIn(500, Hydrant);    assert (ni->curInts & TxAvail);    OutCmd(ni, SetTxAvailThresh + TX_FIFO_THRESH);    Thread::Current()->SleepOn(ni->wrQ);    Thread::Current()->Yield();  }}static voidSkipBadRxPackets(NetInterface* ni){  /* The uppermost bit of the rx_status register indicates an   * incomplete packet.  Since we don't use early RX notification,   * this means a runt packet, which should simply be discarded.   */  for (;;) {    uint16_t rx_status = in16(ni->ioAddr + Wn1RxStatus);      if (rx_status & RxsIncomplete)      return;#ifdef DEBUG    MsgLog::printf("rxskip: rx_status: 0x%04x curint 0x%x\n",		   rx_status, ni->curInts);#endif    /* Keep tossing packets until we find a good one. */    if ((rx_status & RxsError) == 0)      break;    uint8_t rx_error = inb(ni->ioAddr + Wn1RxErrors);    if (rx_error & 0x01) ni->stats.rxOverrun++;    if (rx_error & 0x02) ni->stats.rxLengthErrors++;    if (rx_error & 0x04) ni->stats.rxFrameErrors++;    if (rx_error & 0x08) ni->stats.rxCrcErrors++;    if (rx_error & 0x10) ni->stats.rxLengthErrors++;    ni->stats.rxDropped++;    OutCmd(ni, RxDiscard, true);  }}static voidRxPacket(NetInterface *ni){#ifdef DEBUG  MsgLog::dprintf(false, "Call to RxPacket()\n");#endif    SkipBadRxPackets(ni);    uint16_t rx_status = in16(ni->ioAddr + Wn1RxStatus);    if ( (rx_status & RxsIncomplete) == 0 ) {    /* Disable receive completion interrupts */    ni->curInts &= ~RxComplete;    /* MsgLog::printf("Disable RxComplete interrupt\n"); */    OutCmd(ni, SetIntrMask | ni->curInts);    ni->rdQ.WakeAll(0, true);  }  /* Finally, ack this interrupt: */  OutCmd(ni, AckIntr | RxComplete | RxEarly);}#define INPUT_ALIGN 0x7/* ReadPacket logic: *  *   1. Skip past all bad packets in the FIFO. *   2. See if there are any remaining packets. *      if so, read them *      if not, set the RxComplete interrupt bit. *  */static voidReadPacket(NetInterface *ni, Invocation& inv){  uint64_t dw = rdtsc();  #ifdef DEBUG  MsgLog::dprintf(false, "ReadPacket() on %s\n", ni->name);#endif  if ((uint32_t)inv.exit.data & INPUT_ALIGN  || inv.validLen < MAX_ENET_PACKET_SZ) {    /* input buffer not aligned properly. */    inv.exit.code = RC_RequestError;    MsgLog::printf("  Bad format - inv.exit.data=0x%x inv.validLen=%d\n",		   (uint32_t)inv.exit.data, inv.validLen);    return;  }  SkipBadRxPackets(ni);  uint16_t rx_status = in16(ni->ioAddr + Wn1RxStatus);  #ifdef DEBUG  MsgLog::printf("rdpkt() rxskip: rx_status: 0x%04x curint 0x%x\n",		 rx_status, ni->curInts);#endif  /* MsgLog::printf("Call to ReadPacket()\n"); */    /* The next packet is either good or incomplete: */  if ( (rx_status & RxsIncomplete) == 0 ) {    uint16_t len = rx_status & 0x1fff;    ins32(ni->ioAddr + Wn1RxFifo, inv.exit.data, (len + 3) >> 2);    inv.exit.len = len;    inv.exit.code = RC_OK;    ni->stats.rxPackets++;          OutCmd(ni, RxDiscard, true);    rx_status = in16(ni->ioAddr + Wn1RxStatus);    if ((rx_status & RxsIncomplete) == 0 && ((rx_status & RxsError) == 0))      ni->stats.rxMore++;#ifdef DEBUG    MsgLog::printf("  Got packet on %s, irq %d\n",		   ni->name, ni->irq);#endif    uint64_t ew = rdtsc();    ew -= dw;    ni->stats.rxCpuCycles += ew;    return;  }#ifdef DEBUG  MsgLog::printf("reader queues...\n");#endif#if 0  ni->rdStall++;  ni->watchDog.Disarm();  ni->watchDog.WakeupIn(500, Hydrant);#endif  Thread::Current()->SleepOn(ni->rdQ);  /* MsgLog::printf("  Enable RxComplete interrupt\n"); */  ni->curInts |= RxComplete;  OutCmd(ni, SetIntrMask | ni->curInts);  Thread::Current()->Yield();}inline boolValidIoVec(IoVec* iov, uint32_t n, uint32_t limit){  for (uint32_t i = 0; i < n; i++, iov++) {    if (iov->len && (iov->len + iov->offset > limit)) {      MsgLog::printf("iov [%d] offset 0x%08x len %d sum 0x%08x limit 0x%08x\n",		     i,		     iov->offset, iov->len,		     iov->offset + iov->len, limit);      return false;    }    /* First entry describes IOV, so don't check that! */    if (i && (iov->len < MAX_ENET_PACKET_SZ)) {      MsgLog::printf("iov [%d] offset 0x%08x len %d sum 0x%08x limit 0x%08x\n",		     i,		     iov->offset, iov->len,		     iov->offset + iov->len, limit);      return false;    }    if (iov->offset & INPUT_ALIGN)	{      /* require word aligned start addr --       * buffer known to be word aligned already       */      MsgLog::printf("iov [%d] offset 0x%08x len %d sum 0x%08x limit 0x%08x\n",		     i,		     iov->offset, iov->len,		     iov->offset + iov->len, limit);      return false;    }  }  return true;}#ifdef NET_MULTIREAD/* MultiReadPacket almost never wins on 3c509.  It's here just for * compatibility with 100Mbit cards. */static voidMultiReadPacket(NetInterface *ni, Invocation& inv){  uint64_t dw = rdtsc();  IoVec *entryVec = (IoVec *) inv.entry.data;    if (inv.entry.len < sizeof(IoVec)) {    inv.exit.code = RC_RequestError;    MsgLog::dprintf(true, "  No Send IoVec!!!\n");    return;  }    uint32_t nEntryVec = entryVec->len / sizeof(IoVec);  if ( (entryVec->len % sizeof(IoVec)) || nEntryVec > MAX_IOVEC ||       (nEntryVec == 0) ) {    inv.exit.code = RC_RequestError;    MsgLog::dprintf(true, "  Bad Send IoVec len %d\n", entryVec->len);    return;  }    if (! ValidIoVec(entryVec, nEntryVec, inv.validLen) ) {    inv.exit.code = RC_RequestError;    MsgLog::dprintf(true, "  Bad Send IoVec (ranges)\n");    return;  }    IoVec *exitVec = (IoVec *) (entryVec->offset + inv.exit.data);  uint32_t nExitVec = entryVec->len / sizeof(IoVec);  if ( (uint32_t)inv.exit.data & INPUT_ALIGN ) {    /* input buffer not aligned properly. */    inv.exit.code = RC_RequestError;    MsgLog::dprintf(true, "  misaligned rcv buffer\n");    return;  }  assert (nExitVec == nEntryVec);  IoVec tmpExitVec[MAX_IOVEC];  #define exitVec foobar  /* Careful -- must not overwrite if user entryvec == user exitvec.   * Don't dork entry 0.   */  for (uint32_t i = 1; i < nExitVec; i++) {    tmpExitVec[i].offset = entryVec[i].offset;    tmpExitVec[i].len = 0;  }  IoVec *lastEntryVec = entryVec + nEntryVec;  /* Exit block descriptor[0] entry block descriptor[0] */  tmpExitVec[0].len = entryVec->len;  tmpExitVec[0].offset = entryVec->offset;    /* Process starting with slot 1: */  IoVec *curExitVec = tmpExitVec + 1;  IoVec *curEntryVec = entryVec + 1;  bool haveData = false;    /* If we return rather than yield, it will be with ok status from   * now on.   */    inv.exit.code = RC_OK;  inv.exit.len = inv.validLen;  uint16_t rx_status;    for ( ; curEntryVec != lastEntryVec; curEntryVec++, curExitVec++) {    do {      rx_status = in16(ni->ioAddr + Wn1RxStatus);      if (rx_status & RxsIncomplete) {	if (haveData) {#undef exitVec	  int count = curExitVec - tmpExitVec;	  count--;#ifdef VERBOSE	  MsgLog::dprintf(true, "Return w/ %d pkts\n", count);#endif	  /* Copy out to the REAL exit vec: */	  bcopy(&tmpExitVec, exitVec, tmpExitVec[0].len);

⌨️ 快捷键说明

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