From a2a13689fd103af153fed02f9497f9c230567cfa Mon Sep 17 00:00:00 2001 From: thorpej Date: Mon, 25 Aug 1997 18:56:46 +0000 Subject: [PATCH] Merge with 970703 snapshot of Matt Thomas's de driver. --- sys/dev/pci/if_de.c | 808 ++++++++++++++++++++++++----------------- sys/dev/pci/if_devar.h | 103 +++++- 2 files changed, 559 insertions(+), 352 deletions(-) diff --git a/sys/dev/pci/if_de.c b/sys/dev/pci/if_de.c index 2a2d291ee9de..6ddff710261c 100644 --- a/sys/dev/pci/if_de.c +++ b/sys/dev/pci/if_de.c @@ -1,5 +1,3 @@ -/* $NetBSD: if_de.c,v 1.46 1997/07/19 09:49:39 cgd Exp $ */ - /*- * Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com) * All rights reserved. @@ -23,7 +21,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Id: if_de.c,v 1.89 1997/06/03 19:19:55 thomas Exp + * Id: if_de.c,v 1.94 1997/07/03 16:55:07 thomas Exp * */ @@ -151,6 +149,10 @@ #define TULIP_DEBUG #endif +#if 0 +#define TULIP_PERFSTATS +#endif + #if 0 #define TULIP_USE_SOFTINTR #endif @@ -169,7 +171,10 @@ static tulip_intrfunc_t tulip_intr_shared(void *arg); static tulip_intrfunc_t tulip_intr_normal(void *arg); static void tulip_init(tulip_softc_t * const sc); static void tulip_reset(tulip_softc_t * const sc); +static ifnet_ret_t tulip_ifstart_one(struct ifnet *ifp); static ifnet_ret_t tulip_ifstart(struct ifnet *ifp); +static struct mbuf *tulip_txput(tulip_softc_t * const sc, struct mbuf *m); +static void tulip_txput_setup(tulip_softc_t * const sc); static void tulip_rx_intr(tulip_softc_t * const sc); static void tulip_addr_filter(tulip_softc_t * const sc); static unsigned tulip_mii_readreg(tulip_softc_t * const sc, unsigned devaddr, unsigned regno); @@ -190,9 +195,13 @@ tulip_timeout_callback( tulip_softc_t * const sc = arg; tulip_spl_t s = TULIP_RAISESPL(); + TULIP_PERFSTART(timeout) + sc->tulip_flags &= ~TULIP_TIMEOUTPENDING; sc->tulip_probe_timeout -= 1000 / TULIP_HZ; (sc->tulip_boardsw->bd_media_poll)(sc, TULIP_MEDIAPOLL_TIMER); + + TULIP_PERFEND(timeout); TULIP_RESTORESPL(s); } @@ -238,7 +247,7 @@ tulip_txprobe( /* * Before we are sure this is the right media we need * to send a small packet to make sure there's carrier. - * Strangely, BNC and AUI will 'see" receive data if + * Strangely, BNC and AUI will "see" receive data if * either is connected so the transmit is the only way * to verify the connectivity. */ @@ -259,10 +268,12 @@ tulip_txprobe( * send it! */ sc->tulip_cmdmode |= TULIP_CMD_TXRUN; + sc->tulip_intrmask |= TULIP_STS_TXINTR; sc->tulip_flags |= TULIP_TXPROBE_ACTIVE; TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode); - IF_PREPEND(&sc->tulip_if.if_snd, m); - tulip_ifstart(&sc->tulip_if); + TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask); + if ((m = tulip_txput(sc, m)) != NULL) + m_freem(m); sc->tulip_probe.probe_txprobes++; return 1; } @@ -1824,7 +1835,7 @@ static void tulip_srom_read( tulip_softc_t * const sc) { - int idx; + unsigned idx; const unsigned bitwidth = SROM_BITWIDTH; const unsigned cmdmask = (SROMCMD_RD << bitwidth); const unsigned msb = 1 << (bitwidth + 3 - 1); @@ -1978,7 +1989,7 @@ tulip_mii_writereg( #define tulip_mchash(mca) (tulip_crc32(mca, 6) & 0x1FF) #define tulip_srom_crcok(databuf) ( \ - ((tulip_crc32(databuf, 126) & 0xFFFF) ^ 0xFFFF)== \ + ((tulip_crc32(databuf, 126) & 0xFFFFU) ^ 0xFFFFU) == \ ((databuf)[126] | ((databuf)[127] << 8))) static unsigned @@ -2119,9 +2130,9 @@ tulip_identify_smc_nic( strcpy(&sc->tulip_boardid[4], "9332DST "); sc->tulip_boardsw = &tulip_21140_smc9332_boardsw; } else if (sc->tulip_features & (TULIP_HAVE_BASEROM|TULIP_HAVE_SLAVEDROM)) { - strcpy(&sc->tulip_boardid[4], "9332BDT "); - } else { strcpy(&sc->tulip_boardid[4], "9334BDT "); + } else { + strcpy(&sc->tulip_boardid[4], "9332BDT "); } return; } @@ -2243,7 +2254,7 @@ static int tulip_srom_decode( tulip_softc_t * const sc) { - int idx1, idx2, idx3; + unsigned idx1, idx2, idx3; const tulip_srom_header_t *shp = (tulip_srom_header_t *) &sc->tulip_rombuf[0]; const tulip_srom_adapter_info_t *saip = (tulip_srom_adapter_info_t *) (shp + 1); @@ -2615,7 +2626,7 @@ static int tulip_read_macaddr( tulip_softc_t * const sc) { - int cksum, rom_cksum, idx; + unsigned cksum, rom_cksum, idx; u_int32_t csr; unsigned char tmpbuf[8]; static const u_char testpat[] = { 0xFF, 0, 0x55, 0xAA, 0xFF, 0, 0x55, 0xAA }; @@ -2918,12 +2929,13 @@ tulip_addr_filter( struct ether_multi *enm; sc->tulip_flags &= ~(TULIP_WANTHASHPERFECT|TULIP_WANTHASHONLY|TULIP_ALLMULTI); - sc->tulip_flags |= TULIP_WANTSETUP; + sc->tulip_flags |= TULIP_WANTSETUP|TULIP_WANTTXSTART; sc->tulip_cmdmode &= ~TULIP_CMD_RXRUN; sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED; #if defined(IFF_ALLMULTI) sc->tulip_if.if_flags &= ~IFF_ALLMULTI; #endif + sc->tulip_if.if_start = tulip_ifstart; /* so the setup packet gets queued */ if (sc->tulip_multicnt > 14) { u_int32_t *sp = sc->tulip_setupdata; unsigned hash; @@ -3103,7 +3115,8 @@ tulip_reset( sc->tulip_intrmask |= TULIP_STS_NORMALINTR|TULIP_STS_RXINTR|TULIP_STS_TXINTR |TULIP_STS_ABNRMLINTR|TULIP_STS_SYSERROR|TULIP_STS_TXSTOPPED - |TULIP_STS_TXBABBLE|TULIP_STS_LINKFAIL|TULIP_STS_RXSTOPPED; + |TULIP_STS_TXUNDERFLOW|TULIP_STS_TXBABBLE|TULIP_STS_LINKFAIL + |TULIP_STS_RXSTOPPED; if ((sc->tulip_flags & TULIP_DEVICEPROBE) == 0) (*sc->tulip_boardsw->bd_media_select)(sc); @@ -3117,7 +3130,7 @@ tulip_reset( TULIP_CSR_WRITE(sc, csr_sia_status, TULIP_CSR_READ(sc, csr_sia_status)); sc->tulip_flags &= ~(TULIP_DOINGSETUP|TULIP_WANTSETUP|TULIP_INRESET - |TULIP_RXACT|TULIP_TXINTPENDING); + |TULIP_RXACT); tulip_addr_filter(sc); } @@ -3134,6 +3147,7 @@ tulip_init( if (sc->tulip_if.if_flags & IFF_PROMISC) { sc->tulip_flags |= TULIP_PROMISC; sc->tulip_cmdmode |= TULIP_CMD_PROMISCUOUS; + sc->tulip_intrmask |= TULIP_STS_TXINTR; } else { sc->tulip_flags &= ~TULIP_PROMISC; sc->tulip_cmdmode &= ~TULIP_CMD_PROMISCUOUS; @@ -3155,7 +3169,8 @@ tulip_init( } TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask); TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode); - tulip_ifstart(&sc->tulip_if); + if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == TULIP_WANTSETUP) + tulip_txput_setup(sc); } else { sc->tulip_if.if_flags &= ~IFF_RUNNING; tulip_reset(sc); @@ -3166,6 +3181,7 @@ static void tulip_rx_intr( tulip_softc_t * const sc) { + TULIP_PERFSTART(rxintr) tulip_ringinfo_t * const ri = &sc->tulip_rxinfo; struct ifnet * const ifp = &sc->tulip_if; int fillok = 1; @@ -3174,6 +3190,7 @@ tulip_rx_intr( #endif for (;;) { + TULIP_PERFSTART(rxget) struct ether_header eh; tulip_desc_t *eop = ri->ri_nextin; int total_len = 0, last_offset = 0; @@ -3221,6 +3238,8 @@ tulip_rx_intr( sc->tulip_dbg.dbg_rxintrs++; sc->tulip_dbg.dbg_rxpktsperintr[cnt]++; #endif + TULIP_PERFEND(rxget); + TULIP_PERFEND(rxintr); return; } total_len++; @@ -3381,6 +3400,7 @@ tulip_rx_intr( #if defined(TULIP_DEBUG) sc->tulip_dbg.dbg_rxlowbufs++; #endif + TULIP_PERFEND(rxget); continue; } /* @@ -3400,18 +3420,21 @@ tulip_rx_intr( if (sc->tulip_rxq.ifq_len >= TULIP_RXQ_TARGET) sc->tulip_flags &= ~TULIP_RXBUFSLOW; + TULIP_PERFEND(rxget); } #if defined(TULIP_DEBUG) sc->tulip_dbg.dbg_rxintrs++; sc->tulip_dbg.dbg_rxpktsperintr[cnt]++; #endif + TULIP_PERFEND(rxintr); } static int tulip_tx_intr( tulip_softc_t * const sc) { + TULIP_PERFSTART(txintr) tulip_ringinfo_t * const ri = &sc->tulip_txinfo; struct mbuf *m; int xmits = 0; @@ -3446,10 +3469,11 @@ tulip_tx_intr( } else { const u_int32_t d_status = ri->ri_nextin->d_status; IF_DEQUEUE(&sc->tulip_txq, m); +#if NBPFILTER > 0 + if (sc->tulip_bpf != NULL) + TULIP_BPF_MTAP(sc, m); +#endif m_freem(m); - if (d_flag & TULIP_DFLAG_TxWANTINTR) { - sc->tulip_flags &= ~TULIP_TXINTPENDING; - } if (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) { tulip_mediapoll_event_t event = TULIP_MEDIAPOLL_TXPROBE_OK; if (d_status & (TULIP_DSTS_TxNOCARR|TULIP_DSTS_TxEXCCOLL)) { @@ -3478,6 +3502,10 @@ tulip_tx_intr( sc->tulip_dot3stats.dot3StatsCarrierSenseErrors++; if (d_status & (TULIP_DSTS_TxUNDERFLOW|TULIP_DSTS_TxBABBLE)) sc->tulip_dot3stats.dot3StatsInternalMacTransmitErrors++; + if (d_status & TULIP_DSTS_TxUNDERFLOW) + sc->tulip_dot3stats.dot3StatsInternalTransmitUnderflows++; + if (d_status & TULIP_DSTS_TxBABBLE) + sc->tulip_dot3stats.dot3StatsInternalTransmitBabbles++; } else { u_int32_t collisions = (d_status & TULIP_DSTS_TxCOLLMASK) @@ -3519,6 +3547,7 @@ tulip_tx_intr( else if (xmits > 0) sc->tulip_txtimer = TULIP_TXTIMER; sc->tulip_if.if_opackets += xmits; + TULIP_PERFEND(txintr); return descs; } @@ -3534,7 +3563,7 @@ tulip_print_abnormal_interrupt( csr &= (1 << (sizeof(tulip_status_bits)/sizeof(tulip_status_bits[0]))) - 1; printf(TULIP_PRINTF_FMT ": abnormal interrupt:", TULIP_PRINTF_ARGS); - for (sep = " ", mask = 1; mask >= csr; mask <<= 1, msgp++) { + for (sep = " ", mask = 1; mask <= csr; mask <<= 1, msgp++) { if ((csr & mask) && *msgp != NULL) { printf("%s%s", sep, *msgp); if (mask == TULIP_STS_TXUNDERFLOW && (sc->tulip_flags & TULIP_NEWTXTHRESH)) { @@ -3557,6 +3586,7 @@ tulip_intr_handler( tulip_softc_t * const sc, int *progress_p) { + TULIP_PERFSTART(intr) u_int32_t csr; while ((csr = TULIP_CSR_READ(sc, csr_status)) & sc->tulip_intrmask) { @@ -3637,7 +3667,7 @@ tulip_intr_handler( } TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode); } - if (sc->tulip_txinfo.ri_free < sc->tulip_txinfo.ri_max) { + if (sc->tulip_flags & (TULIP_WANTTXSTART|TULIP_TXPROBE_ACTIVE|TULIP_DOINGSETUP|TULIP_PROMISC)) { tulip_tx_intr(sc); if ((sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0) tulip_ifstart(&sc->tulip_if); @@ -3647,6 +3677,7 @@ tulip_intr_handler( tulip_reset(sc); tulip_init(sc); } + TULIP_PERFEND(intr); } #if defined(TULIP_USE_SOFTINTR) @@ -3793,6 +3824,336 @@ tulip_intr_normal( return progress; #endif } + +static struct mbuf * +tulip_mbuf_compress( + struct mbuf *m) +{ + struct mbuf *m0; +#if MCLBYTES >= ETHERMTU + 18 && !defined(BIG_PACKET) + MGETHDR(m0, M_DONTWAIT, MT_DATA); + if (m0 != NULL) { + if (m->m_pkthdr.len > MHLEN) { + MCLGET(m0, M_DONTWAIT); + if ((m0->m_flags & M_EXT) == 0) { + m_freem(m); + m_freem(m0); + return NULL; + } + } + m_copydata(m, 0, m->m_pkthdr.len, mtod(m0, caddr_t)); + m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len; + } +#else + int mlen = MHLEN; + int len = m->m_pkthdr.len; + struct mbuf **mp = &m0; + + while (len > 0) { + if (mlen == MHLEN) { + MGETHDR(*mp, M_DONTWAIT, MT_DATA); + } else { + MGET(*mp, M_DONTWAIT, MT_DATA); + } + if (*mp == NULL) { + m_freem(m0); + m0 = NULL; + break; + } + if (len > MLEN) { + MCLGET(*mp, M_DONTWAIT); + if (((*mp)->m_flags & M_EXT) == 0) { + m_freem(m0); + m0 = NULL; + break; + } + (*mp)->m_len = len <= MCLBYTES ? len : MCLBYTES; + } else { + (*mp)->m_len = len <= mlen ? len : mlen; + } + m_copydata(m, m->m_pkthdr.len - len, + (*mp)->m_len, mtod((*mp), caddr_t)); + len -= (*mp)->m_len; + mp = &(*mp)->m_next; + mlen = MLEN; + } +#endif + m_freem(m); + return m0; +} + +static struct mbuf * +tulip_txput( + tulip_softc_t * const sc, + struct mbuf *m) +{ + TULIP_PERFSTART(txput) + tulip_ringinfo_t * const ri = &sc->tulip_txinfo; + tulip_desc_t *eop, *nextout; + int segcnt, free; + u_int32_t d_status; + struct mbuf *m0; + +#if defined(TULIP_DEBUG) + if ((sc->tulip_cmdmode & TULIP_CMD_TXRUN) == 0) { + printf(TULIP_PRINTF_FMT ": txput%s: tx not running\n", + TULIP_PRINTF_ARGS, + (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) ? "(probe)" : ""); + sc->tulip_flags |= TULIP_WANTTXSTART; + goto finish; + } +#endif + + /* + * Now we try to fill in our transmit descriptors. This is + * a bit reminiscent of going on the Ark two by two + * since each descriptor for the TULIP can describe + * two buffers. So we advance through packet filling + * each of the two entries at a time to to fill each + * descriptor. Clear the first and last segment bits + * in each descriptor (actually just clear everything + * but the end-of-ring or chain bits) to make sure + * we don't get messed up by previously sent packets. + * + * We may fail to put the entire packet on the ring if + * there is either not enough ring entries free or if the + * packet has more than MAX_TXSEG segments. In the former + * case we will just wait for the ring to empty. In the + * latter case we have to recopy. + */ + again: + d_status = 0; + eop = nextout = ri->ri_nextout; + m0 = m; + segcnt = 0; + free = ri->ri_free; + do { + int len = m0->m_len; + caddr_t addr = mtod(m0, caddr_t); + unsigned clsize = CLBYTES - (((u_long) addr) & (CLBYTES-1)); + + while (len > 0) { + unsigned slen = min(len, clsize); +#ifdef BIG_PACKET + int partial = 0; + if (slen >= 2048) + slen = 2040, partial = 1; +#endif + segcnt++; + if (segcnt > TULIP_MAX_TXSEG) { + /* + * The packet exceeds the number of transmit buffer + * entries that we can use for one packet, so we have + * recopy it into one mbuf and then try again. + */ + m = tulip_mbuf_compress(m); + if (m == NULL) + goto finish; + goto again; + } + if (segcnt & 1) { + if (--free == 0) { + /* + * See if there's any unclaimed space in the + * transmit ring. + */ + if ((free += tulip_tx_intr(sc)) == 0) { + /* + * There's no more room but since nothing + * has been committed at this point, just + * show output is active, put back the + * mbuf and return. + */ + sc->tulip_flags |= TULIP_WANTTXSTART; + goto finish; + } + } + eop = nextout; + if (++nextout == ri->ri_last) + nextout = ri->ri_first; + eop->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN; + eop->d_status = d_status; + eop->d_addr1 = TULIP_KVATOPHYS(sc, addr); + eop->d_length1 = slen; + } else { + /* + * Fill in second half of descriptor + */ + eop->d_addr2 = TULIP_KVATOPHYS(sc, addr); + eop->d_length2 = slen; + } + d_status = TULIP_DSTS_OWNER; + len -= slen; + addr += slen; +#ifdef BIG_PACKET + if (partial) + continue; +#endif + clsize = CLBYTES; + } + } while ((m0 = m0->m_next) != NULL); + + + /* + * The descriptors have been filled in. Now get ready + * to transmit. + */ + IF_ENQUEUE(&sc->tulip_txq, m); + m = NULL; + + /* + * Make sure the next descriptor after this packet is owned + * by us since it may have been set up above if we ran out + * of room in the ring. + */ + nextout->d_status = 0; + + /* + * If we only used the first segment of the last descriptor, + * make sure the second segment will not be used. + */ + if (segcnt & 1) { + eop->d_addr2 = 0; + eop->d_length2 = 0; + } + + /* + * Mark the last and first segments, indicate we want a transmit + * complete interrupt, and tell it to transmit! + */ + eop->d_flag |= TULIP_DFLAG_TxLASTSEG|TULIP_DFLAG_TxWANTINTR; + + /* + * Note that ri->ri_nextout is still the start of the packet + * and until we set the OWNER bit, we can still back out of + * everything we have done. + */ + ri->ri_nextout->d_flag |= TULIP_DFLAG_TxFIRSTSEG; + ri->ri_nextout->d_status = TULIP_DSTS_OWNER; + + TULIP_CSR_WRITE(sc, csr_txpoll, 1); + + /* + * This advances the ring for us. + */ + ri->ri_nextout = nextout; + ri->ri_free = free; + + TULIP_PERFEND(txput); + + if (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) { + sc->tulip_if.if_flags |= IFF_OACTIVE; + TULIP_PERFEND(txput); + return NULL; + } + + /* + * switch back to the single queueing ifstart. + */ + sc->tulip_flags &= ~TULIP_WANTTXSTART; + sc->tulip_if.if_start = tulip_ifstart_one; + if (sc->tulip_txtimer == 0) + sc->tulip_txtimer = TULIP_TXTIMER; + + /* + * If we want a txstart, there must be not enough space in the + * transmit ring. So we want to enable transmit done interrupts + * so we can immediately reclaim some space. When the transmit + * interrupt is posted, the interrupt handler will call tx_intr + * to reclaim space and then txstart (since WANTTXSTART is set). + * txstart will move the packet into the transmit ring and clear + * WANTTXSTART thereby causing TXINTR to be cleared. + */ + finish: + if (sc->tulip_flags & (TULIP_WANTTXSTART|TULIP_DOINGSETUP)) { + sc->tulip_if.if_flags |= IFF_OACTIVE; + sc->tulip_if.if_start = tulip_ifstart; + if ((sc->tulip_intrmask & TULIP_STS_TXINTR) == 0) { + sc->tulip_intrmask |= TULIP_STS_TXINTR; + TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask); + } + } else if ((sc->tulip_flags & TULIP_PROMISC) == 0) { + if (sc->tulip_intrmask & TULIP_STS_TXINTR) { + sc->tulip_intrmask &= ~TULIP_STS_TXINTR; + TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask); + } + } + TULIP_PERFEND(txput); + return m; +} + +static void +tulip_txput_setup( + tulip_softc_t * const sc) +{ + tulip_ringinfo_t * const ri = &sc->tulip_txinfo; + tulip_desc_t *nextout; + + /* + * We will transmit, at most, one setup packet per call to ifstart. + */ + +#if defined(TULIP_DEBUG) + if ((sc->tulip_cmdmode & TULIP_CMD_TXRUN) == 0) { + printf(TULIP_PRINTF_FMT ": txput_setup: tx not running\n", + TULIP_PRINTF_ARGS); + sc->tulip_flags |= TULIP_WANTTXSTART; + sc->tulip_if.if_start = tulip_ifstart; + return; + } +#endif + /* + * Try to reclaim some free descriptors.. + */ + if (ri->ri_free < 2) + tulip_tx_intr(sc); + if ((sc->tulip_flags & TULIP_DOINGSETUP) || ri->ri_free == 1) { + sc->tulip_flags |= TULIP_WANTTXSTART; + sc->tulip_if.if_start = tulip_ifstart; + return; + } + bcopy(sc->tulip_setupdata, sc->tulip_setupbuf, + sizeof(sc->tulip_setupbuf)); + /* + * Clear WANTSETUP and set DOINGSETUP. Set know that WANTSETUP is + * set and DOINGSETUP is clear doing an XOR of the two will DTRT. + */ + sc->tulip_flags ^= TULIP_WANTSETUP|TULIP_DOINGSETUP; + ri->ri_free--; + nextout = ri->ri_nextout; + nextout->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN; + nextout->d_flag |= TULIP_DFLAG_TxFIRSTSEG|TULIP_DFLAG_TxLASTSEG + |TULIP_DFLAG_TxSETUPPKT|TULIP_DFLAG_TxWANTINTR; + if (sc->tulip_flags & TULIP_WANTHASHPERFECT) + nextout->d_flag |= TULIP_DFLAG_TxHASHFILT; + else if (sc->tulip_flags & TULIP_WANTHASHONLY) + nextout->d_flag |= TULIP_DFLAG_TxHASHFILT|TULIP_DFLAG_TxINVRSFILT; + + nextout->d_length1 = sizeof(sc->tulip_setupbuf); + nextout->d_addr1 = TULIP_KVATOPHYS(sc, sc->tulip_setupbuf); + nextout->d_length2 = 0; + nextout->d_addr2 = 0; + + /* + * Advance the ring for the next transmit packet. + */ + if (++ri->ri_nextout == ri->ri_last) + ri->ri_nextout = ri->ri_first; + + /* + * Make sure the next descriptor is owned by us since it + * may have been set up above if we ran out of room in the + * ring. + */ + ri->ri_nextout->d_status = 0; + nextout->d_status = TULIP_DSTS_OWNER; + TULIP_CSR_WRITE(sc, csr_txpoll, 1); + if ((sc->tulip_intrmask & TULIP_STS_TXINTR) == 0) { + sc->tulip_intrmask |= TULIP_STS_TXINTR; + TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask); + } +} + /* * This routine is entered at splnet() (splsoftnet() on NetBSD) @@ -3801,10 +4162,11 @@ tulip_intr_normal( */ static int tulip_ifioctl( - struct ifnet * const ifp, + struct ifnet * ifp, ioctl_cmd_t cmd, caddr_t data) { + TULIP_PERFSTART(ifioctl) tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp); struct ifaddr *ifa = (struct ifaddr *)data; struct ifreq *ifr = (struct ifreq *) data; @@ -3888,7 +4250,7 @@ tulip_ifioctl( } } if (flags) - printf(TULIP_PRINTF_FMT ": ignored invalid media request\n"); + printf(TULIP_PRINTF_FMT ": ignored invalid media request\n", TULIP_PRINTF_ARGS); } #endif tulip_init(sc); @@ -3965,11 +4327,12 @@ tulip_ifioctl( } TULIP_RESTORESPL(s); + TULIP_PERFEND(ifioctl); return error; } /* - * This routine gets called at device spl (from ether_output). This might + * These routines gets called at device spl (from ether_output). This might * pose a problem for TULIP_USE_SOFTINTR if ether_output is called at * device spl from another driver. */ @@ -3978,295 +4341,42 @@ static ifnet_ret_t tulip_ifstart( struct ifnet * const ifp) { + TULIP_PERFSTART(ifstart) tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp); - struct ifqueue * const ifq = &ifp->if_snd; - tulip_ringinfo_t * const ri = &sc->tulip_txinfo; - if ((ifp->if_flags & IFF_RUNNING) == 0 - && (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0) - return; + if (sc->tulip_if.if_flags & IFF_RUNNING) { - for (;;) { - tulip_desc_t *eop, *nextout; - int segcnt, free, recopy; - u_int32_t d_status; - struct mbuf *m, *m0, *next_m0; + if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == TULIP_WANTSETUP) + tulip_txput_setup(sc); - if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == TULIP_WANTSETUP) { -#if defined(TULIP_DEBUG) - if ((sc->tulip_cmdmode & TULIP_CMD_TXRUN) == 0) { - printf(TULIP_PRINTF_FMT ": ifstart: tx not running\n", - TULIP_PRINTF_ARGS); - ifp->if_flags |= IFF_OACTIVE; - return; - } -#endif - if ((sc->tulip_flags & TULIP_DOINGSETUP) || ri->ri_free == 1) { - ifp->if_flags |= IFF_OACTIVE; - return; - } - bcopy(sc->tulip_setupdata, sc->tulip_setupbuf, - sizeof(sc->tulip_setupbuf)); - sc->tulip_flags &= ~TULIP_WANTSETUP; - sc->tulip_flags |= TULIP_DOINGSETUP; - ri->ri_free--; - nextout = ri->ri_nextout; - nextout->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN; - nextout->d_flag |= TULIP_DFLAG_TxFIRSTSEG|TULIP_DFLAG_TxLASTSEG - |TULIP_DFLAG_TxSETUPPKT|TULIP_DFLAG_TxWANTINTR; - if (sc->tulip_flags & TULIP_WANTHASHPERFECT) - nextout->d_flag |= TULIP_DFLAG_TxHASHFILT; - else if (sc->tulip_flags & TULIP_WANTHASHONLY) - nextout->d_flag |= TULIP_DFLAG_TxHASHFILT|TULIP_DFLAG_TxINVRSFILT; - nextout->d_length1 = sizeof(sc->tulip_setupbuf); - nextout->d_addr1 = TULIP_KVATOPHYS(sc, sc->tulip_setupbuf); - nextout->d_length2 = 0; - nextout->d_addr2 = 0; - /* - * Advance the ring for the next transmit packet. - */ - if (++ri->ri_nextout == ri->ri_last) - ri->ri_nextout = ri->ri_first; - /* - * Make sure the next descriptor is owned by us since it - * may have been set up above if we ran out of room in the - * ring. - */ - ri->ri_nextout->d_status = 0; - nextout->d_status = TULIP_DSTS_OWNER; - TULIP_CSR_WRITE(sc, csr_txpoll, 1); - } - - IF_DEQUEUE(ifq, m); - if (m == NULL) - return; - -#if defined(TULIP_DEBUG) - if ((sc->tulip_cmdmode & TULIP_CMD_TXRUN) == 0) { - printf(TULIP_PRINTF_FMT ": ifstart%s: tx not running\n", - TULIP_PRINTF_ARGS, - (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) ? "(probe)" : ""); - ifp->if_flags |= IFF_OACTIVE; - IF_PREPEND(ifq, m); - return; - } -#endif - - /* - * Now we try to fill in our transmit descriptors. This is - * a bit reminiscent of going on the Ark two by two - * since each descriptor for the TULIP can describe - * two buffers. So we advance through packet filling - * each of the two entries at a time to to fill each - * descriptor. Clear the first and last segment bits - * in each descriptor (actually just clear everything - * but the end-of-ring or chain bits) to make sure - * we don't get messed up by previously sent packets. - * - * We may fail to put the entire packet on the ring if - * there is either not enough ring entries free or if the - * packet has more than MAX_TXSEG segments. In the former - * case we will just wait for the ring to empty. In the - * latter case we have to recopy. - */ - d_status = 0; - recopy = 0; - eop = nextout = ri->ri_nextout; - m0 = m; - segcnt = 0; - free = ri->ri_free; - do { - int len = m0->m_len; - caddr_t addr = mtod(m0, caddr_t); - unsigned clsize = CLBYTES - (((u_long) addr) & (CLBYTES-1)); - - next_m0 = m0->m_next; - while (len > 0) { - unsigned slen = min(len, clsize); -#ifdef BIG_PACKET - int partial = 0; - if (slen >= 2048) - slen = 2040, partial = 1; -#endif - segcnt++; - if (segcnt > TULIP_MAX_TXSEG) { - recopy = 1; - next_m0 = NULL; /* to break out of outside loop */ - break; - } - if (segcnt & 1) { - if (--free == 0) { - /* - * See if there's any unclaimed space in the - * transmit ring. - */ - if ((free += tulip_tx_intr(sc)) == 0) { - /* - * There's no more room but since nothing - * has been committed at this point, just - * show output is active, put back the - * mbuf and return. - */ - IF_PREPEND(ifq, m); - ifp->if_flags |= IFF_OACTIVE; - return; - } - } - eop = nextout; - if (++nextout == ri->ri_last) - nextout = ri->ri_first; - eop->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN; - eop->d_status = d_status; - eop->d_addr1 = TULIP_KVATOPHYS(sc, addr); - eop->d_length1 = slen; - } else { - /* - * Fill in second half of descriptor - */ - eop->d_addr2 = TULIP_KVATOPHYS(sc, addr); - eop->d_length2 = slen; - } - d_status = TULIP_DSTS_OWNER; - len -= slen; - addr += slen; -#ifdef BIG_PACKET - if (partial) - continue; -#endif - clsize = CLBYTES; - } - } while ((m0 = next_m0) != NULL); - - /* - * The packet exceeds the number of transmit buffer - * entries that we can use for one packet, so we have - * recopy it into one mbuf and then try again. - */ - if (recopy) { -#if MCLBYTES >= ETHERMTU + 18 - MGETHDR(m0, M_DONTWAIT, MT_DATA); - if (m0 != NULL) { - if (m->m_pkthdr.len > MHLEN) { - MCLGET(m0, M_DONTWAIT); - if ((m0->m_flags & M_EXT) == 0) { - m_freem(m); - m_freem(m0); - continue; - } - } - m_copydata(m, 0, m->m_pkthdr.len, mtod(m0, caddr_t)); - m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len; - } -#else - int mlen = MHLEN; - int len = m->m_pkthdr.len; - struct mbuf **mp = &m0; - - while (len > 0) { - if (mlen == MHLEN) { - MGETHDR(*mp, M_DONTWAIT, MT_DATA); - } else { - MGET(*mp, M_DONTWAIT, MT_DATA); - } - if (*mp == NULL) { - m_freem(m0); - m0 = NULL; - break; - } - if (len > MLEN) { - MCLGET(*mp, M_DONTWAIT); - if (((*mp)->m_flags & M_EXT) == 0) { - m_freem(m0); - m0 = NULL; - break; - } - (*mp)->m_len = len <= MCLBYTES ? len : MCLBYTES; - } else { - (*mp)->m_len = len <= mlen ? len : mlen; - } - m_copydata(m, m->m_pkthdr.len - len, - (*mp)->m_len, mtod((*mp), caddr_t)); - len -= (*mp)->m_len; - mp = &(*mp)->m_next; - mlen = MLEN; - } -#endif - if (m0 != NULL) - IF_PREPEND(ifq, m0); - m_freem(m); - continue; - } - - /* - * The descriptors have been filled in. Now get ready - * to transmit. - */ -#if NBPFILTER > 0 - if (sc->tulip_bpf != NULL) - TULIP_BPF_MTAP(sc, m); -#endif - IF_ENQUEUE(&sc->tulip_txq, m); - - /* - * Make sure the next descriptor after this packet is owned - * by us since it may have been set up above if we ran out - * of room in the ring. - */ - nextout->d_status = 0; - - /* - * If we only used the first segment of the last descriptor, - * make sure the second segment will not be used. - */ - if (segcnt & 1) { - eop->d_addr2 = 0; - eop->d_length2 = 0; - } - - /* - * Mark the last and first segments, indicate we want a transmit - * complete interrupt if there isn't one queued, give the - * descriptors to the TULIP, and tell it to transmit! - */ - if (sc->tulip_flags & TULIP_TXINTPENDING) { - eop->d_flag |= TULIP_DFLAG_TxLASTSEG; -#if defined(TULIP_DEBUG) - sc->tulip_dbg.dbg_txpipe++; -#endif - } else { - eop->d_flag |= TULIP_DFLAG_TxLASTSEG|TULIP_DFLAG_TxWANTINTR; - if ((sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0) { - sc->tulip_flags |= TULIP_TXINTPENDING; -#if defined(TULIP_DEBUG) - sc->tulip_dbg.dbg_txpipestats[sc->tulip_dbg.dbg_txpipe]++; - sc->tulip_dbg.dbg_txpipe = 0; -#endif + while (sc->tulip_if.if_snd.ifq_head != NULL) { + struct mbuf *m; + IF_DEQUEUE(&sc->tulip_if.if_snd, m); + if ((m = tulip_txput(sc, m)) != NULL) { + IF_PREPEND(&sc->tulip_if.if_snd, m); + break; } } - - /* - * Note that ri->ri_nextout is still the start of the packet - * and until we set the OWNER bit, we can still back out of - * everything we have done. - */ - ri->ri_nextout->d_flag |= TULIP_DFLAG_TxFIRSTSEG; - ri->ri_nextout->d_status = TULIP_DSTS_OWNER; - - /* - * This advances the ring for us. - */ - ri->ri_nextout = nextout; - ri->ri_free = free; - - TULIP_CSR_WRITE(sc, csr_txpoll, 1); - - if (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) { - ifp->if_flags |= IFF_OACTIVE; - return; - } - if (sc->tulip_txtimer == 0) - sc->tulip_txtimer = TULIP_TXTIMER; } + + TULIP_PERFEND(ifstart); +} + +static ifnet_ret_t +tulip_ifstart_one( + struct ifnet * const ifp) +{ + TULIP_PERFSTART(ifstart_one) + tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp); + + if ((sc->tulip_if.if_flags & IFF_RUNNING) + && sc->tulip_if.if_snd.ifq_head != NULL) { + struct mbuf *m; + IF_DEQUEUE(&sc->tulip_if.if_snd, m); + if ((m = tulip_txput(sc, m)) != NULL) + IF_PREPEND(&sc->tulip_if.if_snd, m); + } + TULIP_PERFEND(ifstart_one); } /* @@ -4280,6 +4390,7 @@ static void tulip_ifwatchdog( struct ifnet *ifp) { + TULIP_PERFSTART(ifwatchdog) tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp); #if defined(TULIP_DEBUG) @@ -4326,7 +4437,30 @@ tulip_ifwatchdog( tulip_reset(sc); tulip_init(sc); } + + TULIP_PERFEND(ifwatchdog); + TULIP_PERFMERGE(sc, perf_intr_cycles); + TULIP_PERFMERGE(sc, perf_ifstart_cycles); + TULIP_PERFMERGE(sc, perf_ifioctl_cycles); + TULIP_PERFMERGE(sc, perf_ifwatchdog_cycles); + TULIP_PERFMERGE(sc, perf_timeout_cycles); + TULIP_PERFMERGE(sc, perf_ifstart_one_cycles); + TULIP_PERFMERGE(sc, perf_txput_cycles); + TULIP_PERFMERGE(sc, perf_txintr_cycles); + TULIP_PERFMERGE(sc, perf_rxintr_cycles); + TULIP_PERFMERGE(sc, perf_rxget_cycles); + TULIP_PERFMERGE(sc, perf_intr); + TULIP_PERFMERGE(sc, perf_ifstart); + TULIP_PERFMERGE(sc, perf_ifioctl); + TULIP_PERFMERGE(sc, perf_ifwatchdog); + TULIP_PERFMERGE(sc, perf_timeout); + TULIP_PERFMERGE(sc, perf_ifstart_one); + TULIP_PERFMERGE(sc, perf_txput); + TULIP_PERFMERGE(sc, perf_txintr); + TULIP_PERFMERGE(sc, perf_rxintr); + TULIP_PERFMERGE(sc, perf_rxget); } + #if defined(__bsdi__) || (defined(__FreeBSD__) && BSD < 199506) static ifnet_ret_t tulip_ifwatchdog_wrapper( @@ -4793,9 +4927,6 @@ tulip_pci_attach( tulip_softc_t * const sc = (tulip_softc_t *) self; struct pci_attach_args * const pa = (struct pci_attach_args *) aux; const int unit = sc->tulip_dev.dv_unit; - bus_space_tag_t iot, memt; - bus_space_handle_t ioh, memh; - int ioh_valid, memh_valid; #define PCI_CONF_WRITE(r, v) pci_conf_write(pa->pa_pc, pa->pa_tag, (r), (v)) #define PCI_CONF_READ(r) pci_conf_read(pa->pa_pc, pa->pa_tag, (r)) #define PCI_GETBUSDEVINFO(sc) do { \ @@ -4956,33 +5087,40 @@ tulip_pci_attach( #if defined(__NetBSD__) csr_base = 0; + { + bus_space_tag_t iot, memt; + bus_space_handle_t ioh, memh; + u_int32_t cfcs = PCI_CONF_READ(PCI_CFCS); - ioh_valid = (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0, - &iot, &ioh, NULL, NULL) == 0); - memh_valid = (pci_mapreg_map(pa, PCI_CBMA, - PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, - &memt, &memh, NULL, NULL) == 0); - -#if defined(TULIP_IOMAPPED) - if (ioh_valid) { - sc->tulip_bustag = iot; - sc->tulip_bushandle = ioh; - } else if (memh_valid) { - sc->tulip_bustag = memt; - sc->tulip_bushandle = memh; - } -#else /* defined(TULIP_IOMAPPED) */ - if (memh_valid) { - sc->tulip_bustag = memt; - sc->tulip_bushandle = memh; - } else if (ioh_valid) { - sc->tulip_bustag = iot; - sc->tulip_bushandle = ioh; - } -#endif /* TULIP_IOMAPPED */ - else { - printf(": unable to map device registers\n"); - return; + cfcs &= ~(PCI_COMMAND_IO_ENABLE||PCI_COMMAND_IO_ENABLE); + if (!pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0, + &iot, &ioh, NULL, NULL)) { + cfcs |= PCI_COMMAND_IO_ENABLE; + } + if (!pci_mapreg_map(pa, PCI_CBMA, + PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, + 0, &memt, &memh, NULL, NULL) == 0) { + cfcs |= PCI_COMMAND_MEM_ENABLE; + } + if ((cfcs & (PCI_COMMAND_IO_ENABLE||PCI_COMMAND_IO_ENABLE)) == 0) { + printf(": unable to map device registers\n"); + return; + } + cfcs |= PCI_COMMAND_MASTER_ENABLE; + PCI_CONF_WRITE(PCI_CFCS, cfcs); +#if defined(PCI_PREFER_IOSPACE) + if (cfcs & PCI_COMMAND_IO_ENABLE) { + sc->tulip_bustag = iot, sc->tulip_bushandle = ioh; + } else { + sc->tulip_bustag = memt, sc->tulip_bushandle = memh; + } +#else + if (cfcs & PCI_COMMAND_MEM_ENABLE) { + sc->tulip_bustag = memt, sc->tulip_bushandle = memh; + } else { + sc->tulip_bustag = iot, sc->tulip_bushandle = ioh; + } +#endif /* PCI_PREFER_IOSPACE */ } #endif /* __NetBSD__ */ diff --git a/sys/dev/pci/if_devar.h b/sys/dev/pci/if_devar.h index b2de0894e146..4319b83b10f8 100644 --- a/sys/dev/pci/if_devar.h +++ b/sys/dev/pci/if_devar.h @@ -1,5 +1,3 @@ -/* $NetBSD: if_devar.h,v 1.14 1997/07/19 09:49:45 cgd Exp $ */ - /*- * Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com) * All rights reserved. @@ -23,7 +21,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Id: if_devar.h,v 1.23 1997/06/03 18:51:16 thomas Exp + * Id: if_devar.h,v 1.28 1997/07/03 16:55:07 thomas Exp */ #if !defined(_DEVAR_H) @@ -439,8 +437,10 @@ typedef struct { u_int32_t dot3StatsDeferredTransmissions; u_int32_t dot3StatsLateCollisions; u_int32_t dot3StatsExcessiveCollisions; - u_int32_t dot3StatsInternalMacTransmitErrors; u_int32_t dot3StatsCarrierSenseErrors; + u_int32_t dot3StatsInternalMacTransmitErrors; + u_int32_t dot3StatsInternalTransmitUnderflows; /* not in rfc1650! */ + u_int32_t dot3StatsInternalTransmitBabbles; /* not in rfc1650! */ /* * Receive Statistics */ @@ -476,9 +476,8 @@ struct _tulip_softc_t { struct device tulip_dev; /* base device */ void *tulip_ih; /* intrrupt vectoring */ void *tulip_ats; /* shutdown hook */ - - bus_space_tag_t tulip_bustag; /* tag of CSR region being used */ - bus_space_handle_t tulip_bushandle; /* handle for CSR region being used */ + bus_space_tag_t tulip_bustag; + bus_space_handle_t tulip_bushandle; /* CSR region handle */ pci_chipset_tag_t tulip_pc; struct ethercom tulip_ec; u_int8_t tulip_enaddr[ETHER_ADDR_LEN]; @@ -503,9 +502,9 @@ struct _tulip_softc_t { #define TULIP_INRESET 0x00000200 #define TULIP_NEEDRESET 0x00000400 #define TULIP_SQETEST 0x00000800 -#define TULIP_TXINTPENDING 0x00001000 -#define TULIP_xxxxxx0 0x00002000 -#define TULIP_xxxxxx1 0x00004000 +#define TULIP_xxxxxx0 0x00001000 +#define TULIP_xxxxxx1 0x00002000 +#define TULIP_WANTTXSTART 0x00004000 #define TULIP_NEWTXTHRESH 0x00008000 #define TULIP_NOAUTOSENSE 0x00010000 #define TULIP_PRINTLINKUP 0x00020000 @@ -514,7 +513,7 @@ struct _tulip_softc_t { #define TULIP_NOMESSAGES 0x00100000 #define TULIP_SYSTEMERROR 0x00200000 #define TULIP_TIMEOUTPENDING 0x00400000 -#define TULIP_FASTTIMEOUTPENDING 0x00800000 +#define TULIP_xxxxxx2 0x00800000 #define TULIP_TRYNWAY 0x01000000 #define TULIP_DIDNWAY 0x02000000 #define TULIP_RXIGNORE 0x04000000 @@ -522,7 +521,8 @@ struct _tulip_softc_t { #define TULIP_DEVICEPROBE 0x10000000 #define TULIP_PROMISC 0x20000000 #define TULIP_HASHONLY 0x40000000 - /* only 1 bit left! */ +#define TULIP_xxxxxx3 0x80000000 + /* only 4 bits left! */ u_int32_t tulip_features; /* static bits indicating features of chip */ #define TULIP_HAVE_GPR 0x00000001 /* have gp register (140[A]) */ #define TULIP_HAVE_RXBADOVRFLW 0x00000002 /* RX corrupts on overflow */ @@ -601,9 +601,36 @@ struct _tulip_softc_t { u_int32_t dbg_txprobes_failed[TULIP_MEDIA_MAX]; u_int32_t dbg_events[TULIP_MEDIAPOLL_MAX]; u_int32_t dbg_rxpktsperintr[TULIP_RXDESCS]; - u_int32_t dbg_txpipe; - u_int32_t dbg_txpipestats[TULIP_TXDESCS]; } tulip_dbg; +#endif +#if defined(TULIP_PERFSTATS) +#define TULIP_PERF_CURRENT 0 +#define TULIP_PERF_PREVIOUS 1 +#define TULIP_PERF_TOTAL 2 +#define TULIP_PERF_MAX 3 + struct tulip_perfstats { + u_quad_t perf_intr_cycles; + u_quad_t perf_ifstart_cycles; + u_quad_t perf_ifstart_one_cycles; + u_quad_t perf_ifioctl_cycles; + u_quad_t perf_ifwatchdog_cycles; + u_quad_t perf_timeout_cycles; + u_quad_t perf_txput_cycles; + u_quad_t perf_txintr_cycles; + u_quad_t perf_rxintr_cycles; + u_quad_t perf_rxget_cycles; + unsigned perf_intr; + unsigned perf_ifstart; + unsigned perf_ifstart_one; + unsigned perf_ifioctl; + unsigned perf_ifwatchdog; + unsigned perf_timeout; + unsigned perf_txput; + unsigned perf_txintr; + unsigned perf_rxintr; + unsigned perf_rxget; + } tulip_perfstats[TULIP_PERF_MAX]; +#define tulip_curperfstats tulip_perfstats[TULIP_PERF_CURRENT] #endif struct ifqueue tulip_txq; struct ifqueue tulip_rxq; @@ -620,10 +647,10 @@ struct _tulip_softc_t { u_int32_t tulip_setupdata[192/sizeof(u_int32_t)]; char tulip_boardid[16]; /* buffer for board ID */ u_int8_t tulip_rombuf[128]; -#ifndef __NetBSD__ - u_int8_t tulip_pci_busno; /* needed for multiport boards */ +#if defined(__NetBSD__) + struct device *tulip_pci_busno; /* needed for multiport boards */ #else - struct device *tulip_pci_busno; /* in NetBSD each pci bus is a dev */ + u_int8_t tulip_pci_busno; /* needed for multiport boards */ #endif u_int8_t tulip_pci_devno; /* needed for multiport boards */ u_int8_t tulip_connidx; @@ -835,6 +862,7 @@ typedef u_long ioctl_cmd_t; extern struct cfdriver decd; #define TULIP_UNIT_TO_SOFTC(unit) ((tulip_softc_t *) decd.cd_devs[unit]) #define TULIP_IFP_TO_SOFTC(ifp) (TULIP_UNIT_TO_SOFTC((ifp)->if_unit)) +#define TULIP_ETHER_IFATTACH(sc) ether_attach(&(sc)->tulip_if) #if _BSDI_VERSION >= 199510 #if 0 #define TULIP_BURSTSIZE(unit) log2_burst_size @@ -952,6 +980,47 @@ extern struct cfdriver de_cd; #define TULIP_BPF_ATTACH(sc) bpfattach(&(sc)->tulip_bpf, &(sc)->tulip_if, DLT_EN10MB, sizeof(struct ether_header)) #endif +#if defined(TULIP_PERFSTATS) +#define TULIP_PERFMERGE(sc, member) \ + do { (sc)->tulip_perfstats[TULIP_PERF_TOTAL].member \ + += (sc)->tulip_perfstats[TULIP_PERF_CURRENT].member; \ + (sc)->tulip_perfstats[TULIP_PERF_PREVIOUS].member \ + = (sc)->tulip_perfstats[TULIP_PERF_CURRENT].member; \ + (sc)->tulip_perfstats[TULIP_PERF_CURRENT].member = 0; } while (0) +#define TULIP_PERFSTART(name) const tulip_cycle_t perfstart_ ## name = TULIP_PERFREAD(); +#define TULIP_PERFEND(name) do { \ + (sc)->tulip_curperfstats.perf_ ## name ## _cycles += TULIP_PERFDIFF(perfstart_ ## name, TULIP_PERFREAD()); \ + (sc)->tulip_curperfstats.perf_ ## name ++; \ + } while (0) +#if defined(__i386__) +typedef u_quad_t tulip_cycle_t; +static __inline__ tulip_cycle_t +TULIP_PERFREAD( + void) +{ + tulip_cycle_t x; + __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x)); + return x; +} +#define TULIP_PERFDIFF(s, f) ((f) - (s)) +#elif defined(__alpha__) +typedef unsigned long tulip_cycle_t; +static __inline__ tulip_cycle_t +TULIP_PERFREAD( + void) +{ + tulip_cycle_t x; + __asm__ volatile ("rpcc %0" : "=r" (x)); + return x; +} +#define TULIP_PERFDIFF(s, f) ((unsigned int) ((f) - (s))) +#endif +#else +#define TULIP_PERFSTART(name) +#define TULIP_PERFEND(name) do { } while (0) +#define TULIP_PERFMERGE(s,n) do { } while (0) +#endif /* TULIP_PERFSTATS */ + /* * However, this change to FreeBSD I am much less enamored with. */