📄 if_xdssonic.c
字号:
/* update statistics for this packet */ sn->sn_sum.ss_tpacks++; sn->sn_if.if_opackets++; if (status & TSR_DEF) { sn->sn_sum.ss_tdef++; } if (status & TSR_OWC) { sn->sn_sum.ss_tlcol++; sn->sn_if.if_oerrors++; log (LOG_NOTICE, "%s%d: late collision (noisy network?)\n", sn->sn_if.if_name, sn->sn_if.if_unit); } if (status & (TSR_NCRS|TSR_CRSL)) { sn->sn_sum.ss_tlcar++; sn->sn_if.if_oerrors++; log (LOG_NOTICE, "%s%d: no carrier (check cables?)\n", sn->sn_if.if_name, sn->sn_if.if_unit); } if (ncol = (status & TSR_NC) >> TSR_NCSHFT) { sn->sn_if.if_collisions += ncol; if (ncol == 1) sn->sn_sum.ss_tone++; else sn->sn_sum.ss_tmore++; } } else { /* tx failed: CTDA still points at failing packet */ sn->sn_if.if_oerrors++; if (status & (TSR_EXD|TSR_EXC)) { sn->sn_sum.ss_cerr++; log (LOG_NOTICE, "%s%d: excessive %s (network jammed?)\n", sn->sn_if.if_name, sn->sn_if.if_unit, (status & TSR_EXD) ? "deferrals" : "collisions"); status &= ~TSR_BCM; /* ignore bcm error */ } if (status & TSR_FU) { sn->sn_sum.ss_tuflo++; log (LOG_INFO, "%s%d: tx fifo underflow\n", sn->sn_if.if_name, sn->sn_if.if_unit); if (sn->sn_if.if_flags & IFF_DEBUG) sntxdump (txp); } if (status & TSR_BCM) { int fr, frag_total; sn->sn_sum.ss_tbuff++; for (fr = 0, frag_total = 0; fr < txp->frag_count; fr++) frag_total += txp->frags[fr].frag_size; if ((sn->sn_if.if_flags & IFF_DEBUG) || frag_total != txp->pkt_size) { log (LOG_WARNING, "%s%d: tx byte count mismatch, psz=%d, %d in %d frags\n", sn->sn_if.if_name, sn->sn_if.if_unit, txp->pkt_size, frag_total, txp->frag_count); sntxdump (txp); } /* pointless attempt to fix error! */ txp->pkt_size = frag_total; } if (sn->sn_retries++ >= SNRETRIES) { /* give up on this packet */ log (LOG_INFO, "%s%d: tx retry count exceeded\n", sn->sn_if.if_name, sn->sn_if.if_unit); sntxdone (sn, mtd); /* manually advance to next packet: * strictly we only need to set CTDA here, but we are * paranoid and reset it for all errors, below. */ } if (mtdhead) { /* restart transmission */ register volatile struct sn_reg *csr = sn->sn_csr; csr->s_ctda = LOWER(mtdhead->mtd_txp); wbflush(); csr->s_cr = CR_TXP; wbflush(); break; } } } /* dequeue some new packets, if possible */ if (!(sn->sn_if.if_flags & IFF_OACTIVE)) snifstart (&sn->sn_if);}static voidsntxdone (struct sn_softc *sn, struct mtd *mtd){ sn->sn_if.if_flags &= ~IFF_OACTIVE; sn->sn_retries = 0; if (mtd->mtd_mbuf) { m_freem (mtd->mtd_mbuf); mtd->mtd_mbuf = 0; } mtdhead = mtd->mtd_link; if (mtdhead == mtdnext) mtdhead = 0; mtd_free (mtd);}static voidsntxdump (volatile struct TXpkt *txp){ int fr; printf (" frags:"); for (fr = 0; fr < MASK(txp->frag_count); fr++) printf (" %d", MASK(txp->frags[fr].frag_size)); printf ("\n");}/* * Receive interrupt routine */static voidsnrxint (struct sn_softc *sn){ volatile struct sn_reg *csr = sn->sn_csr; volatile struct RXpkt *rxp; rxp = &rda[sn->sn_rxmark]; while (MASK(rxp->in_use) == 0) { if ((MASK(rxp->status) & RCR_LPKT) == 0) log (LOG_WARNING, "%s%d: more than one packet in RBA\n", sn->sn_if.if_name, sn->sn_if.if_unit); #ifdef DEBUG if (SEQNO_PKT (MASK(rxp->seqno)) != 0) log (LOG_WARNING, "%s%d: bad psn sequence no. %d\n", sn->sn_if.if_name, sn->sn_if.if_unit, SEQNO_PKT (MASK(rxp->seqno)));#endif if (MASK(rxp->status) & RCR_PRX) { if (snread (sn, rxp)) { sn->sn_if.if_ipackets++; sn->sn_sum.ss_rpacks++; } } else { log (LOG_INFO, "%s%d: rx packet error 0x%x\n", MASK(rxp->status)); sn->sn_if.if_ierrors++; } /* give receive buffer area back to chip * XXX what buffer did the sonic use for this descriptor * answer look at the rba sequence number !! */ { int orra = SEQNO_RBA (MASK(rxp->seqno)) & RRAMASK; volatile struct RXrsrc *orr = &rra[orra]; #ifdef DEBUG if (MASK(rxp->pkt_ptrhi) != MASK(orr->buff_ptrhi) || MASK(rxp->pkt_ptrlo) != MASK(orr->buff_ptrlo) || MASK(orr->buff_wclo) == 0) log (LOG_WARNING, "%s%d: bad rx pkt pointers\n", sn->sn_if.if_name, sn->sn_if.if_unit);#endif /* orra is now empty of packets and can be freed * (if snread didnt copy it out, but instead passed * pointers around then we would have to wait for * higher levels to free it up) * * (dont bother add it back in again straight away) */ if (IS_K0SEG (rba)) /* hand data buffer over to Sonic */ clean_dcache (PHYS_TO_K0 ((MASK(orr->buff_ptrhi) << 16) | orr->buff_ptrlo), RBASIZE); rra[sn->sn_rramark] = *orr; /* zap old rra */ orr->buff_wchi = orr->buff_wclo = 0; sn->sn_rramark = (sn->sn_rramark + 1) & RRAMASK; csr->s_rwp = LOWER(&rra[sn->sn_rramark]); wbflush (); } /* * give receive descriptor back to chip * simple list is circular */ rxp->in_use = ~0; rxp->rlink |= EOL; sn->sn_lrxp->rlink &= ~EOL; sn->sn_lrxp = rxp; if (++sn->sn_rxmark >= NRDA) sn->sn_rxmark = 0; rxp = &rda[sn->sn_rxmark]; }}/* * snread -- pull packet off interface and forward to appropriate * protocol handler */static intsnread (struct sn_softc *sn, volatile struct RXpkt *rxp){ struct ifqueue *inq; extern char *ether_sprintf(); struct ether_header *eh; caddr_t addr; struct mbuf *m; int len, i; int toff, tlen; /* * Get input data length. * Get pointer to ethernet header (in input buffer). * Deal with trailer protocol: if type is PUP trailer * get true type from first 16-bit word past data. * Remember that type was trailer by setting off. */ len = MASK(rxp->byte_count) - FCSSIZE; addr = (caddr_t) ((MASK(rxp->pkt_ptrhi) << 16) | MASK(rxp->pkt_ptrlo));#ifdef XDSSONICBUG addr = (caddr_t) ((unsigned int)addr << 1);#endif if (IS_K0SEG (rba)) addr = (caddr_t) PHYS_TO_K0 (addr); else addr = (caddr_t) PHYS_TO_K1 (addr);#ifdef XDSSONICBUG xds_compress_buffer (addr, len);#endif#ifdef MIPSEL snswapb (addr, addr, len);#endif#ifdef XDS { static struct ether_header ehdr; copy_data_to_host (addr, (caddr_t)&ehdr, sizeof (ehdr)); eh = &ehdr; eh->ether_type = ntohs((u_short)eh->ether_type); }#else eh = (struct ether_header *)addr; eh->ether_type = ntohs((u_short)eh->ether_type);#endif addr += sizeof (struct ether_header); len -= sizeof (struct ether_header); if (len < ETHERMIN || len > ETHERMTU) { log (LOG_WARNING, "%s%d: bad packet length received: %d bytes\n", sn->sn_if.if_name, sn->sn_if.if_unit, len); return 0; } if (eh->ether_type >= ETHERTYPE_TRAIL && eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { toff = (eh->ether_type - ETHERTYPE_TRAIL) * 512; if (toff >= ETHERMTU) { log (LOG_WARNING, "%s%d: trailer offset %d >= ETHERMTU\n", sn->sn_if.if_name, sn->sn_if.if_unit, toff); return 0; }#ifdef XDS { struct { u_short ttype; u_short tlen; } trailer; copy_data_to_host (addr + toff, (caddr_t)&trailer, sizeof (trailer)); eh->ether_type = ntohs(trailer.ttype); tlen = ntohs(trailer.tlen); }#else eh->ether_type = ntohs(*(u_short *)(addr + toff)); tlen = ntohs(*(u_short *)(addr + toff + sizeof(u_short)));#endif if (toff + tlen > len) { log (LOG_WARNING, "%s%d: bad trailer toff=%d tlen=%d plen=%d\n", sn->sn_if.if_name, sn->sn_if.if_unit, toff, tlen, len); return 0; } len = toff; /* sizeof data only */ toff += 2*sizeof(u_short); tlen -= 2*sizeof(u_short); } else { toff = tlen = 0; } if (T_rxp) { printf("rcvd 0x%x status=0x%x len=%d type=0x%x from %s", addr, MASK(rxp->status), len, eh->ether_type, ether_sprintf (eh->ether_shost)); printf(" (to %s)\n", ether_sprintf (eh->ether_dhost)); } /* * Pull packet off interface. Off is nonzero if packet * has trailing header; sonic_get will then force this header * information to be at the front, but we still have to drop * the type and length which are at the front of any trailer data. */ m = snget (sn, addr, len, toff, tlen); if (!m) return 0; ether_input (&sn->sn_if, eh, m); return 1;}/* * munge the received packet into an mbuf chain * because we are using stupid buffer management this * is slow. */static struct mbuf *snget (struct sn_softc *sn, caddr_t addr, int dlen, int toff, int tlen){ struct mbuf *top = 0; struct mbuf **mp = ⊤ register struct mbuf *m; register int len; caddr_t sp; if (dlen + tlen == 0) return 0; MGETHDR (m, M_DONTWAIT, MT_DATA); if (!m) return 0; m->m_pkthdr.rcvif = &sn->sn_if; m->m_pkthdr.len = dlen + tlen; m->m_len = MHLEN; sp = addr + toff; len = tlen; while (1) { if (len == 0) { if (dlen == 0) return top; /* all done */ sp = addr; len = dlen; dlen = 0; } if (top) { /* get next mbuf */ MGET (m, M_DONTWAIT, MT_DATA); if (!m) { m_freem (top); return 0; } m->m_len = MLEN; } if (len >= MINCLSIZE) { MCLGET (m, M_DONTWAIT); if (m->m_flags & M_EXT) m->m_len = MCLBYTES; } else if (top == 0 && len + max_linkhdr <= m->m_len) { /* place initial small packet/header at end of mbuf */ m->m_data += max_linkhdr; } if (m->m_len > len) m->m_len = len; copy_data_to_host (sp, mtod(m, caddr_t), m->m_len); sp += m->m_len; len -= m->m_len; *mp = m; mp = &m->m_next; }}static voidmtd_free (struct mtd *mtd){ mtd->mtd_mbuf = (struct mbuf *)0; mtd->mtd_link = mtdfree; mtdfree = mtd;}static struct mtd *mtd_alloc (){ struct mtd *mtd; mtd = mtdfree; if (mtd) { mtdfree = mtd->mtd_link; mtd->mtd_link = 0; } return (mtd);}/* * CAM support */static voidcaminitialise (){ int i; bzero ((char *)cda, CDASIZE); for (i = 0; i < MAXCAM; i++) { cda->desc[i].cam_ep = i; cda->desc[i].cam_ap0 = 0xdead; cda->desc[i].cam_ap1 = 0xdead; cda->desc[i].cam_ap2 = 0xdead; } cda->enable = 0;}static voidcamentry (int entry, u_char *ea){ cda->desc[entry].cam_ep = entry; cda->desc[entry].cam_ap2 = (ea[5]<<8) | ea[4]; cda->desc[entry].cam_ap1 = (ea[3]<<8) | ea[2]; cda->desc[entry].cam_ap0 = (ea[1]<<8) | ea[0]; cda->enable |= (1 << entry);}static voidsonictxdump (char *msg, struct TXpkt *txp){ int i; printf ("%s:\n", msg); printf ("txp:0x%08x status:0x%04x config:0x%04x pkt_size:0x%04x frag_count:%d\n", txp, MASK(txp->status), txp->config, txp->pkt_size, txp->frag_count); for (i = 0; i < txp->frag_count; i++) { printf ("ptrlo=0x%04x ptrhi=0x%04x size=0x%04x\n", txp->frags[i].frag_ptrlo, txp->frags[i].frag_ptrhi, txp->frags[i].frag_size); } }static voidsonicdump (char *msg, volatile struct sn_reg *csr){ printf ("%s:\n", msg); printf ("s_cr\t0x%04x ", csr->s_cr); printf ("s_dcr\t0x%04x ", csr->s_dcr); printf ("s_rcr\t0x%04x ", csr->s_rcr); printf ("\n"); printf ("s_tcr\t0x%04x ", csr->s_tcr); printf ("s_imr\t0x%04x ", csr->s_imr); printf ("s_isr\t0x%04x ", csr->s_isr); printf ("\n"); printf ("s_utda\t0x%04x ", csr->s_utda); printf ("s_ctda\t0x%04x ", csr->s_ctda); printf ("s_urda\t0x%04x ", csr->s_urda); printf ("\n"); printf ("s_crda\t0x%04x ", csr->s_crda); printf ("s_eobc\t0x%04x ", csr->s_eobc); printf ("s_urra\t0x%04x ", csr->s_urra); printf ("\n"); printf ("s_rsa\t0x%04x ", csr->s_rsa); printf ("s_rea\t0x%04x ", csr->s_rea); printf ("s_rrp\t0x%04x ", csr->s_rrp); printf ("\n"); printf ("s_rwp\t0x%04x ", csr->s_rwp); printf ("s_cep\t0x%04x ", csr->s_cep); printf ("s_cap2\t0x%04x ", csr->s_cap2); printf ("\n"); printf ("s_cap1\t0x%04x ", csr->s_cap1); printf ("s_cap0\t0x%04x ", csr->s_cap0); printf ("s_ce\t0x%04x ", csr->s_ce); printf ("\n"); printf ("s_cdp\t0x%04x ", csr->s_cdp); printf ("s_cdc\t0x%04x ", csr->s_cdc); printf ("s_sr\t0x%04x ", csr->s_sr); printf ("\n"); printf ("s_wt0\t0x%04x ", csr->s_wt0); printf ("s_wt1\t0x%04x ", csr->s_wt1); printf ("s_rsc\t0x%04x ", csr->s_rsc); printf ("\n"); printf ("s_crct\t0x%04x ", csr->s_crct); printf ("s_faet\t0x%04x ", csr->s_faet); printf ("s_mpt\t0x%04x ", csr->s_mpt); printf ("\n"); printf ("s_dcr2\t0x%04x ", csr->s_dcr2); printf ("\n"); printf ("_s_crba0\t0x%04x ", csr->_s_crba0); printf ("_s_crba1\t0x%04x ", csr->_s_crba1); printf ("_s_rbwc0\t0x%04x ", csr->_s_rbwc0); printf ("_s_rbwc1\t0x%04x ", csr->_s_rbwc1); printf ("\n");}static voidcamdump(volatile struct sn_reg *csr){ int i; printf ("CAM entries:\n"); csr->s_cr = CR_RST; wbflush (); for (i = 0; i < 16; i++) { u_short ap2, ap1, ap0; csr->s_cep = i; wbflush (); ap2 = csr->s_cap2; ap1 = csr->s_cap1; ap0 = csr->s_cap0; printf ("%d: ap2=0x%x ap1=0x%x ap0=0x%x\n", i, ap2, ap1, ap0); } printf ("CAM enable 0x%x\n", csr->s_ce); csr->s_cr = 0; wbflush ();}static intcamprogram(struct sn_softc *sn){ volatile struct sn_reg *csr; int timeout; int i; csr = sn->sn_csr; csr->s_cdp = LOWER(cda); csr->s_cdc = MAXCAM; wbflush (); csr->s_cr = CR_LCAM; wbflush (); DELAY(1000) timeout = 1000; while ((csr->s_cr & CR_LCAM) && --timeout > 0) DELAY (100); /* let it get at the bus */ if (timeout <= 0) { log (LOG_ERR, "sonic: CAM init failed\n"); return 0; } timeout = 1000; while ((csr->s_isr & ISR_LCD) == 0 && --timeout > 0) DELAY (100); csr->s_isr = ISR_LCD; wbflush(); if (timeout <= 0) { log (LOG_ERR, "sonic: CAM init didn't interrupt\n"); return 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -