📄 net_3c59x.cxx
字号:
#define exitVec foobar uint64_t ew = rdtsc(); ew -= dw; ni->stats.rxCpuCycles += ew; return; } /* Else wait for at least one packet. */ ni->stats.rdStall++; Thread::Current()->SleepOn(ni->rdQ); ni->curInts |= RxComplete; OutCmd(ni, SetIntrMask | ni->curInts); Thread::Current()->Yield(); } if (rx_status & RxsError) SkipBadRxPackets(ni); } while (rx_status & RxsError); uint16_t len = rx_status & Rxsuint8_ts; curExitVec->len = len; /* We know that the input buffer is aligned and also that it is * of sufficient size: */ ins32(ni->ioAddr + Wn1RxFifo, inv.exit.data + curExitVec->offset, (len+3) >> 2); ni->stats.rxPackets++; haveData = true; OutCmd(ni, RxDiscard, true); } rx_status = in16(ni->ioAddr + Wn1RxStatus); if ((rx_status & RxsIncomplete) == 0 && ((rx_status & RxsError) == 0)) ni->stats.rxMore++;#undef exitVec#ifdef VERBOSE MsgLog::dprintf(true, "%s (3c59x): Drop out w/ %d pkts\n", ni->name, curExitVec - &tmpExitVec[1]);#endif /* Copy out to the REAL exit vec: */ bcopy(&tmpExitVec, exitVec, tmpExitVec->len); uint64_t ew = rdtsc(); ew -= dw; ni->stats.rxCpuCycles += ew;}#endifstatic inline voidHandleInterrupt(NetInterface * ni){ uint16_t status; /* Status is accessable from every window */ for (;;) { status = in16(ni->ioAddr + El3Status);#if 0 MsgLog::printf("HI: status = 0x%04x\n", status);#endif if ( (status & (IntLatch | (RxComplete&ni->curInts) | UpdateStats)) == 0) break; /* Only run RxPacket if we are supposed to be accepting RX interrupts: */ if (status & RxComplete & ni->curInts) RxPacket(ni); if (status & TxAvail) { ni->watchDog.Disarm(); ni->wrQ.WakeAll();#ifdef ENET_DEBUG MsgLog::printf("Got txAvail intr\n");#endif OutCmd(ni, AckIntr | TxAvail); }#if 0 if ( status & DownComplete ) { } if ( status & DmaDone ) { } if (status & UpComplete) { }#endif if ( status & (AdapterFail | RxEarly | UpdateStats) ) { if (status & UpdateStats) UpdateStatistics(ni); if (status & RxEarly) MsgLog::fatal("RxEarly interrupt\n"); if (status & AdapterFail) { /* Reset receiver and re-init the adapter: */ OutCmd(ni, RxReset, true); /* Reset the RX filter to current settings: */ OutCmd(ni, SetRxFilter | ni->rxFilter); /* Re-enable the RX FIFO: */ OutCmd(ni, RxEnable); /* Ack this part of the interrupt: */ OutCmd(ni, AckIntr | AdapterFail); } } /* Acknowledge the interrupt: */ OutCmd(ni, AckIntr | IntRequested | IntLatch); }}static voidHandleInterrupt(IntAction *ia){ /* Previous interrupt architecture line. Left in for reference. * EL3Type *elink = EL3Type::FindCard(interfaces[0]->irq); */ NetInterface* ni = (NetInterface*) ia->drvr_ptr; HandleInterrupt(ni);}static voidEnable(NetInterface * ni){ if (ni->info.niStatus & NI_ENABLED) return; if ( (ni->info.niStatus & NI_ATTACHED) == 0 ) return; vortex_private *vp = (vortex_private *) ni->private; wn3_config config; SetWindow(ni, 3); if (vp->fullDuplex) out8(MacFullDuplex, ni->ioAddr + Wn3MacCtrl); /* FIX enum value */ config.i = in32(ni->ioAddr + Wn3Config); if (vp->mediaOverride != 7) { MsgLog::dprintf(false, "%s: Media override to xcvr %d (%s).\n", ni->name, vp->mediaOverride, media_tbl[vp->mediaOverride].name); ni->xcvr = vp->mediaOverride; } else if (vp->autoSelect) {#if 0 /* Start with 100baseTx */ ni->xcvr = 4; while (! (vp->availableMedia & media_tble[ni->xcvr].mask) ) ni->xcvr = media_tvle[ni->xcvr].next; MsgLog::dprintf("%s: Initial media type %s.\n", ni->name, media_tbl[ni->xcvr].name); mediaTimer.client_ptr = ni; mediaTimer.WakupIn(media_tbl[ni->xcvr].wait, VortexTimer);#else MsgLog::dprintf(true, "Autoconfig not yet supported\n");#endif } else ni->xcvr = vp->defaultMedia; config.u.xcvr = ni->xcvr; out32(config.i, ni->ioAddr + Wn3Config); MsgLog::dprintf(false,"Enable(): config was 0x%x\n", config.i); OutCmd(ni, TxReset, true); OutCmd(ni, RxReset, true); /* need to wait? */ OutCmd(ni, SetStatusMask | 0x0); /* DISABLES INTERRUPTS */ IRQ::Enable(ni->irq); if (vortex_debug > 1){ SetWindow(ni, 4); MsgLog::printf("%s: Enable() irq %d media status 0x%4x.\n", ni->name, ni->irq, in16(ni->ioAddr + Wn4MediaType)); } /* Set the station address and mask in window 2 each time opened. */ SetWindow(ni, 2); { int i; for (i = 0; i < 6; i++) out8(ni->info.niAddr[i], ni->ioAddr + i); for (; i < 12; i+=2) /* why rewrite eeprom? */ out16(0, ni->ioAddr + i); } if (ni->xcvr == 3) { OutCmd(ni, StartCoax); /* In theory, we ought to delay here, but the lost packets are * okay on an ethernet... */ } SetWindow(ni, 4); out16((in16(ni->ioAddr + Wn4MediaType) & ~(Media_10TP|Media_SQE)) | media_tbl[ni->xcvr].media_bits, ni->ioAddr + Wn4MediaType); /* Clear out the statistics buffers: */ OutCmd(ni, StatsDisable); SetWindow(ni, 6); for (int i = 0; i < 10; i++) in8(ni->ioAddr + i); in16(ni->ioAddr + 10); in16(ni->ioAddr + 12); /* On Vortex, also clear BadSSD counter: */ SetWindow(ni, 4); inb(ni->ioAddr + 12); /* And enable yet more stats on the boomerang: */ out16(0x0040, ni->ioAddr + Wn4NetDiag); /* Back to Window 7 for normal activity */ SetWindow(ni, 7); if (vp->fullBusMasterRX) {#ifdef USE_RX_RING /* FIX -- initialize the ring structures */ out32(&vp->rx_ring[0], ni->ioAddr + UpListPtr);#endif MsgLog::dprintf(false, "Ring buffer RX init not yet implemented\n"); } if (vp->fullBusMasterTX) { /* vp->curTx = vp->dirtyTx = 0; * Suitably set TxFreeThresh * Clear out TX ring * out32(0, ni->ioAddr + DownListPtr); */ MsgLog::dprintf(false, "Ring buffer TX init not yet implemented\n"); } ni->rxFilter = RxIndividual | RxBroadcast; ni->info.niStatus |= NI_BROADCAST | NI_STATION; OutCmd(ni, SetRxFilter | ni->rxFilter); OutCmd(ni, StatsEnable); /* Let transmissions start early, since we know we can keep up once we get some headroom to make up for intervening timer interrupts. */ OutCmd(ni, SetTxStartThresh | vp->txStartThresh); OutCmd(ni, RxEnable); OutCmd(ni, TxEnable); /* Allow status bits to be seen. */#if 0 OutCmd(ni, SetStatusMask | AdapterFail|IntRequested|UpdateStats | (vp->fullBusMasterTX ? DownComplete : TxAvail) | (vp->fullBusMasterRX ? UpComplete : RxComplete) | (vp->busMaster ? DmaDone : 0));#else OutCmd(ni, SetStatusMask | 0x1ff);#endif uint16_t status = in16(ni->ioAddr + El3Status); MsgLog::dprintf(false, "status prior to ackintr = 0x%04x\n", status); /* Ack all pending events, and set active indicator mask. */ OutCmd(ni, AckIntr | IntLatch | TxAvail | RxEarly | IntRequested);#if 1 /* FIX: Don't really want RxComplete here! */ ni->curInts = IntLatch | TxAvail | UpdateStats; ni->curInts = 0x01ff;#else /* FIX: Don't really want RxComplete here! */ ni->curInts = IntLatch | TxAvail | RxComplete | UpdateStats | (vp->busMaster ? DmaDone : 0) | UpComplete | DownComplete;#endif OutCmd(ni, SetIntrMask | ni->curInts);}#if 0static voidDisable(NetInterface *ni){ OutCmd(ni, StatsDisable); OutCmd(ni, RxDisable); OutCmd(ni, TxDisable); if (ni->xcvr == 3) OutCmd(ni, StopCoax); /* turn off thin-net power */ IRQ::Disable(ni->irq); OutCmd(ni, SetIntrMask | 0x0000); UpdateStatistics(ni);#if 0 vortex_private *vp = (vortex_private *) ni->private; if (vp->fullBusMasterRX) { /* Free Boomerang bus master Rx buffers. */ out32(0, ni->ioAddr + UpListPtr); for (i = 0; i < RX_RING_SIZE; i++) if (vp->rx_skbuff[i]) { vp->rx_skbuff[i]->free = 1; dev_kfree_skb (vp->rx_skbuff[i], FREE_WRITE); vp->rx_skbuff[i] = 0; } } if (vp->fullBusMasterTX) { /* Free Boomerang bus master Tx buffers. */ out32(0, ni->ioAddr + DownListPtr); for (i = 0; i < TX_RING_SIZE; i++) if (vp->tx_skbuff[i]) { dev_kfree_skb(vp->tx_skbuff[i], FREE_WRITE); vp->tx_skbuff[i] = 0; } }#endif}#endifstatic voidUpdateStatistics(NetInterface *ni){#if 0 vortex_private *vp = (vortex_private *) ni->private;#endif#if 0 OutCmd(ni, StatsDisable);#endif /* Switch to the stats window, and read everything. */ SetWindow(ni,6); /* Note that the sequential read of registers 6 and 9 can cause * rollover if stats get updated at the wrong instant! */ ni->stats.txCarrierErrors += in8(ni->ioAddr + 0); ni->stats.txHeartbeatErrors += in8(ni->ioAddr + 1); /* multiple collisions */ (void) in8(ni->ioAddr + 2); ni->stats.collisions += in8(ni->ioAddr + 3); ni->stats.txWindowErrors += in8(ni->ioAddr + 4); ni->stats.rxFifoErrors += in8(ni->ioAddr + 5); ni->stats.txPackets += in8(ni->ioAddr + 6); ni->stats.txPackets += (in8(ni->ioAddr + 9)&0x30)<<4; /* rxPackets */ (void) in8(ni->ioAddr + 7); /* txDeferrals */ (void) in8(ni->ioAddr + 8); /* total RX octets */ (void) in16(ni->ioAddr + 10); /* total TX octets */ (void) in16(ni->ioAddr + 12); /* New: On the Vortex we must also clear the BadSSD counter. */ SetWindow(ni, 4); (void) in8(ni->ioAddr + 12); /* We change back to window 7 (not 1) with the Vortex. */ SetWindow(ni, 7);#if 0 OutCmd(ni, StatsEnable);#endif}static voidInvoke(NetInterface *ni, Invocation& inv){#ifndef OPTION_PURE_ENTRY_STRINGS Thread::CurContext()->SetupEntryString(inv);#endif#ifndef OPTION_PURE_EXIT_STRINGS inv.invokee->SetupExitString(inv, inv.validLen);#endif COMMIT_POINT(); switch (inv.entry.code) { case OC_NI_Read: { ReadPacket(ni, inv); break; } case OC_NI_Write: { if (inv.entry.len >= MIN_ENET_PACKET_SZ && inv.entry.len <= MAX_ENET_PACKET_SZ) WritePacket(ni, inv); else inv.exit.code = RC_RequestError; break; }#ifdef NET_MULTIREAD case OC_NI_MultiRead: { MultiReadPacket(ni, inv); break; }#endif case OC_NI_MultiWrite: { inv.exit.code = RC_UnknownRequest; return; } case OC_NI_GetInfo: { inv.CopyOut(sizeof(ni->info), &ni->info); return; } case OC_NI_GetStats: { inv.CopyOut(sizeof(ni->stats), &ni->stats); return; } case OC_NI_Reset: { inv.exit.code = RC_UnknownRequest; return; } default: inv.exit.code = RC_UnknownRequest; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -