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

📄 if_xdssonic.c

📁 很好的一个嵌入式linux平台下的bootloader
💻 C
📖 第 1 页 / 共 4 页
字号:
        /* clear pending interrupts */    csr->s_isr = ~0;        /* clear tally counters */    csr->s_crct = ~0;    csr->s_faet = ~0;    csr->s_mpt = ~0;        /* initialise memory descriptors */    if (rba) {	bzero (rba, NRBA * RBASIZE);	if (IS_K0SEG (rba))	  clean_dcache (rba, NRBA * RBASIZE);    } else {	error = allocatebuffers ();	if (error)	  goto bad;    }    caminitialise ();    initialise_tda (sn);    initialise_rda (sn);    initialise_rra (sn);        /* enable (unreset) the chip */    csr->s_cr = 0; wbflush();    /* program the cam with our address (m/c addresses already present) */    camentry (0, sn->sn_enaddr);    if (!camprogram (sn))      goto bad;        /* get it to read initial resource descriptors */    csr->s_cr = CR_RRRA; wbflush ();    while (csr->s_cr & CR_RRRA)      DELAY(100);/* sonicdump ("After reading resource descriptors", csr); */    /* enable receiver */    csr->s_cr = CR_RXEN; wbflush ();        /* flag interface as "running" */    sn->sn_if.if_flags |= IFF_RUNNING;    sn->sn_retries = 0;    sn->sn_rbe = 0;    splx(s);    return 0; bad:    snclosedown (sn);    return error;}/* * snclosedown(): close down an interface and free its buffers * Called on final close of device, or if snstartup() fails * part way through. */static intsnclosedown (struct sn_softc *sn){    register volatile struct sn_reg *csr = sn->sn_csr;    int s = splhigh();    sn->sn_if.if_flags &= ~(IFF_RUNNING | IFF_UP | IFF_OACTIVE);    sn->sn_if.if_timer = 0;    log (LOG_INFO, "%s%d: stopping interface\n",	 sn->sn_if.if_name, sn->sn_if.if_unit);    /* update tally counters */    sn->sn_crct += csr->s_crct;    sn->sn_faet += csr->s_faet;    sn->sn_mpt += csr->s_mpt;    /* forcibly shut the chip up */    csr->s_cr = CR_RST; wbflush();    DELAY(1000);        /* free all receive buffers (currently static so nowt to do) */        /* free all transmit mbufs still pending */    {	struct mtd *mtd;	for (mtd = mtdhead; mtd; mtd = mtd->mtd_link) {	    if (mtd->mtd_mbuf) {		m_freem (mtd->mtd_mbuf);		mtd->mtd_mbuf = 0;	    }	}    }        splx(s);    return 0;}#ifdef PROMstatic intsncheckclient (struct sn_softc *sn){    register volatile struct sn_reg *csr = sn->sn_csr;    unsigned short upper = csr->s_urra;    unsigned short lower = csr->s_rsa;    static int consecutivefails = 0;    if (upper != UPPER (rra) || lower != LOWER (rra)) {	/* client has reprogrammed sonic, we must now ignore it */	sn->sn_if.if_flags &= ~IFF_RUNNING;	consecutivefails++;	log (LOG_DEBUG, "%s%d: count %d: 0x%04x/0x%04x 0x%04x/0x%04x\n",	     sn->sn_if.if_name, sn->sn_if.if_unit, consecutivefails,	     upper, UPPER (rra), lower, LOWER (rra));	if (consecutivefails <= 3)	    return 1;	log (LOG_DEBUG, "%s%d: reprogrammed by client, PMON ignoring\n",	     sn->sn_if.if_name, sn->sn_if.if_unit);	return 0;    }    consecutivefails = 0;    return 1;}#endifstatic intsnifstart (struct ifnet *ifp){    register struct sn_softc *sn = &sn_softc[ifp->if_unit];    int s;#ifdef PROM    if (!sncheckclient (sn))	return ENETDOWN;#endif    /*     * start feeding any queued packets to chip     */    s = splimp ();    for (;;) {	struct mbuf *m;		IF_DEQUEUE (&ifp->if_snd, m);	if (m == 0)			/* nothing left to send */	  break;		if (!snput (sn, m)) {	    /* not enough space */	    IF_PREPEND (&ifp->if_snd, m);	    ifp->if_flags |= IFF_OACTIVE;	    ifp->if_oerrors++;	    break;	}    }    (void) splx (s);    return 0;}/* * stuff packet into sonic (at splimp) */#if defined(XDS)static intsnput (struct sn_softc *sn, struct mbuf *m0){    volatile struct sn_reg *csr = sn->sn_csr;    register volatile union frag *fr;    register struct mtd *mtdnew;    register volatile struct TXpkt *txp;    register struct mbuf *m;    int len, i;    unsigned char *ptba;    unsigned int pa;    if (!csr)       return 0;    /* grab the replacement mtd */    if ((mtdnew = mtd_alloc()) == 0)      return 0;        /* this packet goes in mtdnext */    txp = mtdnext->mtd_txp;    txp->config = 0;    txp->status = 0;#ifdef MIPSEL    /* Byte-swap the mbuf chain */    m0 = snswapm (m0);#endif    /* copy the data into the static RAM buffer */    fr = &txp->frags[0];    ptba = mtdnext->mtd_tba;    len = 0;    for (m = m0; m; m = m->m_next) {	copy_host_to_data (mtod (m, char *), ptba, m->m_len);	ptba += m->m_len;	len += m->m_len;    }    /* pad out last fragment for minimum size */    if (len < ETHERMIN + sizeof(struct ether_header))	len = ETHERMIN + sizeof(struct ether_header);#ifdef XDSSONICBUG    xds_expand_buffer (mtdnext->mtd_tba, len);#else#if defined(R4000)    /* flush data to static RAM */    clean_dcache(mtdnext->mtd_tba, len);#endif#endif    pa = K0_TO_PHYS(mtdnext->mtd_tba);    txp->frag_count = 1;    txp->pkt_size = len;    fr->frag_ptrlo = LOWER(pa);    fr->frag_ptrhi = UPPER(pa);    fr->frag_size = len;    /* link onto the next mtd that will be used */    fr++;    fr->tlink = LOWER(mtdnew->mtd_txp) | EOL;        if (!mtdhead) {	/* no current transmit list, so start with this one */	mtdhead = mtdnext;    } else {	/* have an existing transmit list, so append it to end of list	 * note mtdnext is already physically linked to mtdtail in	 * mtdtail->mtd_txp->frags[mtdtail->mtd_txp->frag_count].tlink	 */	mtdtail->mtd_txp->frags[mtdtail->mtd_txp->frag_count].tlink &= ~EOL;	wbflush ();    }/*    sonictxdump ("Transmit descriptor", txp); *//*    sonicdump ("Before kicking transmitter", csr); */    /* kick transmitter */    csr->s_cr = CR_TXP; wbflush ();/*    DELAY(1000); *//*    sonicdump ("After kicking transmitter\n", csr); */    /* update s/w linkage */    mtdnext->mtd_mbuf = m0;	/* to be freed on txint */    mtdnext->mtd_link = mtdnew;    mtdtail = mtdnext;    mtdnext = mtdnew;        sn->sn_if.if_timer = 5;	/* 5 second watchdog */    return 1;}#elsestatic intsnput (struct sn_softc *sn, struct mbuf *m0){    volatile struct sn_reg *csr = sn->sn_csr;    register volatile union frag *fr;    register struct mtd *mtdnew;    register volatile struct TXpkt *txp;    register struct mbuf *m;    int firstattempt = 1;    int len, nfr, i, tinyfrags, needcompress;        if (!csr)       return 0;    /* grab the replacement mtd */    if ((mtdnew = mtd_alloc()) == 0)      return 0;        /* this packet goes in mtdnext */    txp = mtdnext->mtd_txp;    txp->config = 0;    txp->status = 0; retry:    /* see whether it will fit in the TDA */    tinyfrags = needcompress = len = nfr = 0;    fr = &txp->frags[0];    for (m = m0; m; m = m->m_next) {	unsigned va = mtod (m, unsigned);	int resid = m->m_len;		len += resid;	while (resid) {	    unsigned n = resid;#ifndef PROM	    if (IS_KSEG2 (va)) {		/* this could cross a page boundary */		n = NBPC - (va & (NBPC - 1));		if (n > resid)		  n = resid;	    }#endif	    /* heuristic to prevent transmit underflow */	    if (n < TINYFRAG) {		if (++tinyfrags > MAXTINIES && tinyfrags > needcompress)		  needcompress = tinyfrags; /* remember maximum */	    }	    else 	      tinyfrags = 0;	    nfr++; va += n; resid -= n;	}    }    if (needcompress != 0 || nfr > FRAGMAX) {	if (firstattempt) {	    /* try to compress chain */	    m0 = sn_fillup (m0, ETHERMTU / FRAGMAX + 1);	    firstattempt = 0;	    goto retry;	}	mtd_free (mtdnew);	m_freem (m0);	log (LOG_WARNING, "%s%d: frag compress failed (%d frags, %d tiny)\n",	     sn->sn_if.if_name, sn->sn_if.if_unit, nfr, needcompress);	sn->sn_if.if_oerrors++;	return 1;    }#ifdef MIPSEL    /* Byte-swap the mbuf chain */    m0 = snswapm (m0);#endif#ifdef R4000    /* hand mbuf data over to Sonic */    if (IS_K0SEG (m0))      for (m = m0; m; m = m->m_next)	if (m->m_len)	  clean_dcache (mtod(m, caddr_t), m->m_len);#endif    /* Now fill up the txd fragment list */    fr = &txp->frags[0];    for (m = m0; m; m = m->m_next) {	unsigned va = mtod (m, unsigned);	int resid = m->m_len;		while (resid) {	    u_long pa;	    unsigned n = resid;#ifndef PROM	    pa = kvtophys (va);	    if (IS_KSEG2 (va)) {		/* this could cross a page boundary */		n = NBPC - (pa & (NBPC - 1));		if (n > resid)		  n = resid;	    }#else	    pa = K1_TO_PHYS (va);#endif	    fr->frag_ptrlo = pa;	    fr->frag_ptrhi = pa >> 16;	    fr->frag_size = n;	    fr++;	    va += n; resid -= n;	}    }    /* pad out last fragment for minimum size */    if (len < ETHERMIN + sizeof(struct ether_header)) {	int pad = (ETHERMIN + sizeof(struct ether_header)) - len;	(fr-1)->frag_size += pad;	len = ETHERMIN + sizeof(struct ether_header);    }    txp->frag_count = nfr;    txp->pkt_size = len;    /* link onto the next mtd that will be used */    fr->tlink = LOWER(mtdnew->mtd_txp) | EOL;        if (!mtdhead) {	/* no current transmit list, so start with this one */	mtdhead = mtdnext;    } else {	/* have an existing transmit list, so append it to end of list	 * note mtdnext is already physically linked to mtdtail in	 * mtdtail->mtd_txp->frags[mtdtail->mtd_txp->frag_count].tlink	 */	mtdtail->mtd_txp->frags[mtdtail->mtd_txp->frag_count].tlink &= ~EOL;	wbflush ();    }    /* kick transmitter */    csr->s_cr = CR_TXP; wbflush ();    /* update s/w linkage */    mtdnext->mtd_mbuf = m0;	/* to be freed on txint */    mtdnext->mtd_link = mtdnew;    mtdtail = mtdnext;    mtdnext = mtdnew;        sn->sn_if.if_timer = 5;	/* 5 second watchdog */    return 1;}#endifvoidsnintr (int unit){    struct sn_softc *sn = &sn_softc[unit];    volatile struct sn_reg *csr = sn->sn_csr;    register u_int isr;    if (unit >= NSONIC || !csr)      return;        while (isr = csr->s_isr) {/*	printf ("snintr: csr=0x%x 0x%x\n", csr, isr); */#ifdef PROM	if (!sncheckclient (sn))	    return;#endif	/* scrub the interrupts that we are going to service */	csr->s_isr = isr & ~ISR_RBE; wbflush ();	if (isr & ISR_BR) {	    log (LOG_WARNING, "%s%d: bus error\n",		 sn->sn_if.if_name, sn->sn_if.if_unit);	    snrestart (sn);	    break;	}	if (isr & (ISR_LCD|ISR_PINT|ISR_TC))	  log (LOG_WARNING, "%s%d: unexpected interrupt status 0x%x\n",	       sn->sn_if.if_name, sn->sn_if.if_unit, isr);		if (isr & (ISR_TXDN|ISR_TXER))	  sntxint (sn);		if (isr & ISR_PKTRX)	  snrxint (sn);	if (isr & ISR_ERRS) {	    if (snerrint (sn, isr))	      break;	} else {	    sn->sn_rbe = 0;	}    }}/* * Error interrupt routine */static intsnerrint (struct sn_softc *sn, u_int isr){    if (isr & ISR_RBE) {	sn->sn_if.if_ierrors++;	sn->sn_sum.ss_rbuff++;	log (LOG_INFO, "%s%d: receive buffer exhausted, isr=0x%x\n",	     sn->sn_if.if_name, sn->sn_if.if_unit, isr);	if (!sn->sn_rbe || (isr & ISR_PKTRX)) {	    /* probably managed to free some rx space, try again */	    sn->sn_csr->s_isr = ISR_RBE; wbflush ();	    sn->sn_rbe = 1;	} else if (sn->sn_rbe) {	    log (LOG_INFO, "%s%d: and no rx data to free\n",		 sn->sn_if.if_name, sn->sn_if.if_unit);	    snrestart (sn);	    return (1);	}    }    if (isr & ISR_RDE) {	sn->sn_if.if_ierrors++;	sn->sn_sum.ss_rbuff++;	log (LOG_INFO, "%s%d: rx descriptors exhausted, isr=0x%x\n",	     sn->sn_if.if_name, sn->sn_if.if_unit, isr);    }    else if (isr & ISR_RBAE) {	sn->sn_if.if_ierrors++;	sn->sn_sum.ss_rbuff++;	log (LOG_INFO, "%s%d: rx buffer area exceeded, isr=0x%x\n",	     sn->sn_if.if_name, sn->sn_if.if_unit, isr);    }    else if (isr & ISR_RFO) {	sn->sn_if.if_ierrors++;	sn->sn_sum.ss_roflo++;	log (LOG_INFO, "%s%d: rx fifo overflow, isr=0x%x\n",	     sn->sn_if.if_name, sn->sn_if.if_unit, isr);    }    if (isr & ISR_HBL)      sn->sn_sum.ss_noheart++;        if (isr & ISR_CRC)      sn->sn_crct += 0x10000;        if (isr & ISR_FAE)      sn->sn_faet += 0x10000;        if (isr & ISR_MP)      sn->sn_mpt += 0x10000;    return (0);}/* * Transmit interrupt routine */static voidsntxint (struct sn_softc *sn){    struct mtd *mtd;    register volatile struct TXpkt *txp;    register u_int status, ncol;    while (mtd = mtdhead) {	txp = mtd->mtd_txp;	if ((status = MASK(txp->status)) == 0) {		    /* this packet isn't sent yet */	    break;	}	txp->status = 0;#ifdef DEBUG	if (T_txp) {	    struct ether_header *eh=mtod(mtd->mtd_mbuf,struct ether_header *);	    printf ("xmit status=0x%x len=%d type=0x%x from %s",			status, txp->pkt_size, 			ntohs(eh->ether_type), ether_sprintf(eh->ether_shost));	    printf(" (to %s)\n", ether_sprintf (eh->ether_dhost));	}#endif	if (status & TSR_PTX) {	    /* tx packet has flown, free the packet mbufs */	    sntxdone (sn, mtd);

⌨️ 快捷键说明

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