📄 if_xdssonic.c
字号:
/* camdump (csr); */ return 1;}/* * because the sonic is basically a 16 bit device it 'concatenates' * a higher buffer address to a 16 bit offset this can cause wrap * around problems near 64k boundaries !! */static intallocatebuffers (){ void *buf; u_long p, lo, hi;#undef XDSLOWMEM#if defined(XDS)#ifdef XDSLOWMEM rba = (char *)PHYS_TO_K1(0x07050000);#else rba = (char *)PHYS_TO_K1(SRAM_NET);#endif tba = rba + NRBA * RBASIZE; buf = tba + NTDA * TBASIZE;#else buf = malloc (SONICBUFSIZE, M_DEVBUF, 0); if (!buf) return (ENOBUFS); rba = (char *) malloc (NRBA * RBASIZE, M_DEVBUF, 0); if (!rba) { free (buf, M_DEVBUF); return (ENOBUFS); }#endif#ifdef R4000 /* flush dirty data first */ if (IS_K0SEG (buf)) { clean_dcache (buf, SONICBUFSIZE); clean_dcache (rba, NRBA * RBASIZE);#ifdef XDS clean_dcache (tba, NTDA * TBASIZE);#endif }#endif /* force into kseg1, and align correctly */ p = ((u_long) K0_TO_K1 (buf) + SONICALIGN - 1) & ~(SONICALIGN - 1); /* RRA and CDA must fit inside 64k region */ if ((p ^ (p+RRASIZE+CDASIZE)) & ~0xffff) p = (p+0x10000) & ~0xffff; rra = (struct RXrsrc *)p; p += RRASIZE; cda = (struct CDA *)p; p += CDASIZE; /* RDA must fit inside 64k region */ if ((p ^ (p+RDASIZE)) & ~0xffff) p = (p+0x10000) & ~0xffff; rda = (struct RXpkt *)p; p += RDASIZE; /* TDA must fit inside 64k region */ if ((p ^ (p+TDASIZE)) & ~0xffff) p = (p+0x10000) & ~0xffff; tda = (struct TXpkt *)p; p += TDASIZE; /* check sanity of buffer addreseses */ lo = (u_long) K0_TO_K1 (buf); hi = lo + SONICBUFSIZE; if ((unsigned)rra < lo || (unsigned)rra >= hi || (unsigned)cda < lo || (unsigned)cda >= hi || (unsigned)rda < lo || (unsigned)rda >= hi || (unsigned)tda < lo || (unsigned)tda >= hi) { log (LOG_ERR, "sonic descriptors out of range\n"); return ENOMEM; }#ifdef notdefprintf ("rba = 0x%08x\n", rba);printf ("tba = 0x%08x\n", tba);printf ("rra = 0x%08x\n", rra);printf ("cda = 0x%08x\n", cda);printf ("rda = 0x%08x\n", rda);printf ("tda = 0x%08x\n", tda);#endif /* return errno */ return 0;}static voidinitialise_tda (struct sn_softc *sn){ volatile struct sn_reg *csr = sn->sn_csr; struct mtd *mtd; int i; bzero ((char *)tda, TDASIZE); mtdfree = mtdhead = mtdtail = (struct mtd *)0; for (i = 0; i < NTDA; i++) { mtd = &mtda[i]; mtd->mtd_txp = &tda[i]; mtd_free(mtd);#ifdef XDS mtd->mtd_tba = tba + i*TBASIZE;#endif } mtdnext = mtd_alloc (); csr->s_utda = UPPER(tda); wbflush(); csr->s_ctda = LOWER(mtdnext->mtd_txp); wbflush();}static voidinitialise_rda (struct sn_softc *sn){ volatile struct sn_reg *csr = sn->sn_csr; int i; /* link the RDA's together into a circular list */ bzero ((char *)rda, RDASIZE); for (i = 0; i < (NRDA-1); i++) { rda[i].rlink = LOWER(&rda[i+1]); rda[i].in_use = ~0; } rda[NRDA-1].in_use = ~0; rda[NRDA-1].rlink = LOWER(&rda[0]) | EOL; /* mark end of receive descriptor list */ sn->sn_lrxp = &rda[NRDA-1]; sn->sn_rxmark = 0; csr->s_urda = UPPER(rda); csr->s_crda = LOWER(rda); wbflush();}static voidinitialise_rra (struct sn_softc *sn){ volatile struct sn_reg *csr = sn->sn_csr; char *rb; int i;again: bzero ((char *)rra, RRASIZE); csr->s_eobc = EOBC / 2; csr->s_urra = UPPER(rra); csr->s_rsa = LOWER(rra); csr->s_rea = LOWER(&rra[NRRA]); /* * fill up SOME of the rra with buffers */ for (i = 0, rb = rba; i < NRBA; i++, rb += RBASIZE) { rra[i].buff_ptrhi = UPPER(rb); rra[i].buff_ptrlo = LOWER(rb);#ifdef XDSSONICBUG rra[i].buff_wchi = (RBASIZE / 4) >> 16; rra[i].buff_wclo = (RBASIZE / 4);#else rra[i].buff_wchi = (RBASIZE / 2) >> 16; rra[i].buff_wclo = (RBASIZE / 2);#endif } sn->sn_rramark = NRBA; csr->s_rrp = LOWER(rra); csr->s_rwp = LOWER(&rra[sn->sn_rramark]); wbflush();}/* * snwatch(): interface watchdog timer * * Called if any Tx packets remain unsent after 5 seconds, * In all cases we just reset the chip, and any retransmission * will be handled by higher level protocol timeouts. */static intsnwatch (int unit){ struct sn_softc *sn = &sn_softc[unit]; int s = splimp(); if (mtdhead && mtdhead != mtdnext) { /* something still pending for transmit */ log (LOG_WARNING, "%s%d: Tx - %s\n", sn->sn_if.if_name, sn->sn_if.if_unit, (MASK(mtdhead->mtd_txp->status) == 0) ? "timeout" : "lost interrupt"); /* snrestart (sn); */ snclosedown (sn); } (void) splx (s); return 0;}/* * sn_pullup(): reorganise part of an mbuf chain to satisfy SONIC. * * It doesn't free mbufs that reduce to zero length. * This is in case they are NFS mbufs which point to disk buffers. * and the buffers must not be released until after the packet has flown. */static struct mbuf *sn_pullup (n, len) register struct mbuf *n; register int len;{ register struct mbuf *m; register int count; /* check it will fit in an ordinary mbuf */ if (len > MLEN) goto bad; if ((n->m_flags & M_EXT) == 0) { /* ordinary mbuf */ if (n->m_data + len > &n->m_dat[MLEN]) { /* not enough space: must realign buffer start */ bcopy (n->m_data, n->m_dat, n->m_len); n->m_data = n->m_dat; } } else { /* external cluster (must be only user) */ if (mclrefcnt[mtocl(n->m_data)] != 1) { log (LOG_NOTICE, "snpullup: shared ext cluster\n"); goto bad; } if (n->m_data + len > n->m_ext.ext_buf + n->m_ext.ext_size) { /* not enough space: must realign cluster start */#ifdef DEBUG if (len <= n->m_ext.ext_size) { log (LOG_NOTICE, "snpullup: ext buf too small (%d < %d)\n", n->m_ext.ext_size, len); goto bad; }#endif bcopy (n->m_data, n->m_ext.ext_buf, n->m_len); n->m_data = n->m_ext.ext_buf; } } /* now ok to append in place */ m = n; n = n->m_next; len -= m->m_len; while (len > 0 && n) { count = MIN(len, n->m_len); bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len, (unsigned)count); len -= count; m->m_len += count; n->m_len -= count; if (n->m_len) n->m_data += count; else n = n->m_next; } return (m); bad: m_freem(n); return (0);}/* * Fillup a whole chain, so that each mbuf has a sensible minimum * length, to avoid transmit underflows. */static struct mbuf *sn_fillup (m, minlen) register struct mbuf *m; register int minlen;{ struct mbuf *m0 = 0; register struct mbuf *mprev = (struct mbuf *)&m0; while (m) { if (m->m_len && m->m_len < minlen && m->m_next) m = sn_pullup (m, minlen); mprev->m_next = m; mprev = m; m = m->m_next; } return m0;}#ifdef MIPSELstatic voidsnswapb (s, d, len) u_char *s, *d; int len;{ while (len > 0) { *(unsigned int *)d = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; d += 4; s += 4; len -= 4; }}static struct mbuf *snswapm (m0) struct mbuf *m0;{ struct mbuf *m; caddr_t s; for (m = m0; m; m = m->m_next) { if ((m->m_flags & M_EXT) && mclrefcnt[mtocl(m->m_data)] != 1) /* external cluster (must be only user) */ panic ("snswapm: shared ext cluster"); s = m->m_data; if ((unsigned)s & 3) { /* buffer is unaligned: must align data in buffer */ caddr_t dat, d; unsigned int msz; /* determine data buffer base and size */ if (m->m_flags & M_EXT) { dat = m->m_ext.ext_buf; msz = m->m_ext.ext_size; } else if (m->m_flags & M_PKTHDR) { dat = m->m_pktdat; msz = MHLEN; } else { dat = m->m_dat; msz = MLEN; } /* round buffer base up to word boundary */ d = (caddr_t) (((unsigned long)dat + 3) & ~3); /* can we shuffle the data down to start of buffer? */ if (m->m_data > d) m->m_data = d; else { /* is there room after the current data? */ d = (caddr_t) (((unsigned long)m->m_data + m->m_len + 3) & ~3); if (d + ((m->m_len + 3) & ~3) <= dat + msz) m->m_data = d; else /* this shouldn't happen!! */ panic ("snswapm"); } } snswapb (s, m->m_data, m->m_len); } return m0;}#endif#ifdef XDSSONICBUG/* * compress buffer in SRAM after it has been received */static voidxds_compress_buffer (caddr_t addr, int len){ int words = (len + 3) >> 2; unsigned int *sp, *dp; /* ASSERT(IS_K1SEG(addr)); *//* printf ("xdr_compress_buffer (0x%08x, 0x%x)\n", addr, len); */ sp = dp = (unsigned int *)addr; while (words-- > 0) { *dp = *sp; dp += 1; sp += 2; }#ifdef notdef { unsigned int *w; int i; w = (unsigned int *)addr; words = (len + 3) >> 2; for (i = 0; i < words; i++) { printf ("%04x ", w[i]); if ((i & 3) == 3) printf ("\n"); } if ((words & 3) != 0) printf ("\n"); } #endif}/* * expand buffer in SRAM before it is sent */static voidxds_expand_buffer (caddr_t addr, int len){ int words = (len + 3) >> 2; unsigned int *sp, *dp; /* ASSERT(IS_K1SEG(addr)); *//* printf ("xds_expand_buffer (0x%08x, %d)\n", addr, len); */ sp = (unsigned int *)addr + words; dp = sp + words; while (words-- >= 0) { *dp = *sp; *(dp+1) = 0xdeaddead; sp -= 1; dp -= 2; }}#endif#ifdef XDSstatic voidcopy_host_to_data (caddr_t sp, caddr_t dp, int len){ unsigned int *wp; unsigned int w; unsigned int soffset, doffset; int shift; soffset = (unsigned int)sp & 3; doffset = (unsigned int)dp & 3; if (doffset) { /* first align dp */ wp = (unsigned int *)PHYS_TO_K1((unsigned int)dp & ~3); w = *wp; for (shift = 24 - 8*doffset; shift >= 0; shift -= 8) { w = (w & ~(0xff << shift)) | (*(unsigned char *)sp << shift); dp++; sp++; len--; if (len <= 0) { *wp = w; return; } } *wp = w; } if (soffset == doffset) { /* read a word, write a word */ while (len >= 4) { *(unsigned int *)dp = *(unsigned int *)sp; sp += 4; dp += 4; len -= 4; } } else { /* read 4 bytes, write a word */ while (len >= 4) { w = *(unsigned char *)(sp+0) << 24; w |= *(unsigned char *)(sp+1) << 16; w |= *(unsigned char *)(sp+2) << 8; w |= *(unsigned char *)(sp+3); *(unsigned int *)dp = w; sp += 4; dp += 4; len -= 4; } } if (len == 0) return; /* transfer last few bytes */ wp = (unsigned int *)dp; w = *wp; for (shift = 24; len > 0; shift -= 8) { w = (w & ~(0xff << shift)) | (*(unsigned char *)sp << shift); sp++; dp++; len--; } *wp = w;}static voidcopy_data_to_host (caddr_t sp, caddr_t dp, int len){ unsigned int *wp, w; unsigned int soffset, doffset; int shift; soffset = (unsigned int)sp & 3; doffset = (unsigned int)dp & 3; if (soffset) { /* first align sp */ w = *(unsigned int *)((unsigned int)sp & ~3); for (shift = 24 - 8*soffset; shift >= 0; shift -= 8) { *dp = w >> shift; dp++; sp++; len--; if (len <= 0) return; } } if (soffset == doffset) { /* read a word, write a word */ while (len >= 4) { *(unsigned int *)dp = *(unsigned int *)sp; sp += 4; dp += 4; len -= 4; } } else { /* read a word, write 4 bytes */ while (len >= 4) { w = *(unsigned int *)sp; *(unsigned char *)(dp+0) = w >> 24; *(unsigned char *)(dp+1) = w >> 16; *(unsigned char *)(dp+2) = w >> 8; *(unsigned char *)(dp+3) = w; sp += 4; dp += 4; len -= 4; } } if (len == 0) return; /* transfer last few bytes */ w = *(unsigned int *)sp; for (shift = 24; len > 0; shift -= 8) { *dp = w >> shift; sp++; dp++; len--; }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -