📄 if_egl.c
字号:
ether_attach ( &egl->egl_if, unit, "egl", egl_init, egl_ioctl, ether_output, egl_reset); egl->egl_if.if_start = (FUNCPTR)egl_start;#endif egl->egl_if.if_mtu = ETHERMTU - 4; /* MTU = 1496 for block bug */ (void)intConnect (INUM_TO_IVEC (ivec+0), egl_intr, unit); /* XXX temporarily while R3K targets don't do vectored VME interrupts */#if CPU_FAMILY!=MIPS (void)intConnect (INUM_TO_IVEC (ivec+1), egl_intr, unit); (void)intConnect (INUM_TO_IVEC (ivec+2), egl_intr, unit); (void)intConnect (INUM_TO_IVEC (ivec+3), egl_intr, unit); (void)intConnect (INUM_TO_IVEC (ivec+4), egl_intr, unit);#endif /* CPU_FAMILY!=MIPS */ sysIntEnable (ilevel); if (egl_init (unit) != 0) return (ERROR); return (OK); }/********************************************************************************* egl_config - configure the Eagle to default settings** RETURNS: 0 or -1 on error.*/LOCAL int egl_config ( int unit, int itype ) { EGL_SOFTC *egl = egl_softc [unit]; volatile SHIO *shio = egl->eglAddr; volatile CIB *cib = (CIB *)&shio->sh_SCRTCH[0]; /* scratch area */ volatile IC_IOPB *iopb = (IC_IOPB *)&shio->sh_MCE_IOPB; int status = 0; int ix; /* Controller Initialization Block */ cib->cib_RES0 = 0; cib->cib_NCQE = NUM_CQE; cib->cib_IMOD = (USHORT)M_IMOD_PE; /* Ethernet */ cib->cib_NTXR = EGL_TX_NRINGS; /* LANCE Tx Rings */ cib->cib_NRXR = EGL_RX_NRINGS; /* LANCE Rx Rings */ /* default Physical Address */ bcopy ((char*)egl->egl_cstb.cstb_PHY, (char*)cib->cib_PHY, sizeof(egl->egl_cstb.cstb_PHY)); /* default Logical Address Filter */ bcopy ((char*)egl->egl_cstb.cstb_FILT, (char*)cib->cib_FILT, sizeof (egl->egl_cstb.cstb_FILT)); cib->cib_RXSIZ = EGL_RX_BUFSZ; /* Max Rx Packet */ cib->cib_NRBUF = EGL_RX_NRINGS; /* Num Rx Buffers */ cib->cib_TXSIZ = EGL_TX_BUFSZ; /* Max Tx Packet */ cib->cib_NIBUF = EGL_TX_NRINGS; /* Num Tx Buffers */ cib->cib_NHBUF = EGL_NHBUF; /* Num Host Buffers */ cib->cib_NVECT = egl->qav_vec; /* needed for error handling */ cib->cib_EVECT = egl->qav_vec; /* needed for error handling */ cib->cib_BURST = EGL_BURST; /* DMA Burst Count */ bzero ((char*)cib->cib_RES1, sizeof(cib->cib_RES1)); /* MCE IOPB */ iopb->ic_iopb_CMD = CNTR_INIT; /* XXX big-endian or quad alignment? */ iopb->ic_iopb_OPTION = M_OPT_SG | itype; /* 0 no int; 1 int */ iopb->ic_iopb_NVCT = egl->qav_vec; iopb->ic_iopb_EVCT = egl->qav_vec; iopb->ic_iopb_RES0 = 0; iopb->ic_iopb_BUFF = (ULONG)cib - (ULONG)shio;/* CIB offset from shio */ bzero ((char*)iopb->ic_iopb_RES1, sizeof(iopb->ic_iopb_RES1)); shio->sh_MCE.cqe_CTAG = 0; shio->sh_MCE.cqe_IOPB_ADDR = O_MCE_IOPB; shio->sh_MCE.cqe_WORK_QUEUE = 0; CQE_GO(shio->sh_MCE.cqe_QECR); if (!itype) { ix = egl_wait (&shio->sh_CRB); if (CRB_ERROR(ix)) {#ifdef EGL_DEBUG logMsg ("egl%d: *error* unable to configure interface\n", unit, 0, 0, 0, 0, 0); if (iopb->ic_iopb_STATUS) logMsg ("iopb error status = %#x\n", iopb->ic_iopb_STATUS, 0, 0, 0, 0, 0);#endif status = -1; } else if (ix == 0x1000) {#ifdef EGL_DEBUG logMsg ("egl%d: *timeout* unable to configure interface\n", unit, 0, 0, 0, 0, 0);#endif status = -1; } } return (status); }/********************************************************************************* egl_hangrcv - place a receive request for the specified iobp** RETURNS: 1 or 0.*/LOCAL int egl_hangrcv ( int unit, int index ) { ETH_BUF *eth_buf; volatile IOPB *iopb; EGL_SOFTC *egl = egl_softc [unit]; volatile SHIO *shio = egl->eglAddr; volatile CQE *cqe = egl->egl_cqe; if (egl->egl_qfull != 0) {#ifdef EGL_DEBUG logMsg ("egl%d: egl_hangrcv - packet queue full\n", unit, 0, 0, 0, 0,0);#endif /* EGL_DEBUG */ return (0); } /* place a receive request */ if (CQE_BUSY(cqe->cqe_QECR)) { egl->egl_qfull++; /* feed queue full */ return (0); } if ((eth_buf = egl->egl_rbinfo[index]) == NULL) GET_ETH_BUF(eth_buf); iopb = eth_buf->iopb; iopb->iopb_BUFF = eth_buf->eth_dat_adr; eth_buf->eth_len = EGL_MTU; egl->egl_rbinfo[index] = eth_buf; egl_ioflush (eth_buf); cqe->cqe_CTAG = index; cqe->cqe_IOPB_ADDR = (caddr_t)iopb - (caddr_t)shio; cqe->cqe_WORK_QUEUE = EGL_RECVQ; CQE_GO(cqe->cqe_QECR); if (++egl->egl_cqe == &shio->sh_CQE[MAX_CQE]) egl->egl_cqe = (CQE *)&shio->sh_CQE[0]; return (1); }/********************************************************************************* egl_init - initialization of interface; clear pending operations** RETURNS: 0 or -1.*/LOCAL int egl_init ( int unit ) { EGL_SOFTC *egl = egl_softc [unit]; volatile SHIO *shio = egl->eglAddr; volatile CRB *crb = &shio->sh_CRB; struct ifnet *ifp = &egl->egl_if; int s; int ix; ifp->if_flags &= ~(IFF_UP|IFF_RUNNING); s = splimp (); if (egl_reset (unit) == -1) { splx (s); return (-1); } /* LANCE is turned OFF now */ if (egl_config (unit, NOINT) == -1) { splx (s); return (-1); } /* LANCE is turned ON now */ egl_setiopbs (unit); /* setup iopbs */ egl->egl_qmode = 0; /* not queue mode */ /* start up queue mode */ if (egl_iworkq (unit, NOINT) == -1) { splx (s);#ifdef EGL_DEBUG logMsg ("egl%d: egl_init - failed\n", 0, 0, 0, 0, 0, 0);#endif return (-1); } for (ix = 0; ix < 10000; ix++) { if (CRB_QSTARTED(crb->crb_CRSW)) break; DELAY(500); } if (!CRB_QSTARTED(crb->crb_CRSW)) {#ifdef EGL_DEBUG logMsg ("egl%d: failed to start Q-Mode\n", unit, 0, 0, 0, 0, 0);#endif splx (s); return (-1); } egl->egl_qmode++; CRB_CLR_DONE(crb->crb_CRSW); /* release Eagle */ /* initial hang receive requests */ for (ix = 0; ix < EGL_RX_NBUFF; ix++) { if (egl_hangrcv (unit, ix) == 0) break; } egl->egl_if.if_flags |= IFF_UP | IFF_RUNNING;#ifdef BSD43_DRIVER egl_start (unit); /* start transmits */#else egl_start (egl);#endif splx (s); return (0); }/********************************************************************************* egl_intr - read vector and dispatch to routine handler*/LOCAL void egl_intr ( int unit ) {#ifdef EGL_DEBUG static char message [150]; char *nullmsg = "";#endif EGL_SOFTC *egl = egl_softc [unit]; volatile SHIO *shio = egl->eglAddr; volatile CRB *crb = &shio->sh_CRB; volatile CSB *csb = &shio->sh_CSB; volatile IOPB tiopb; int real_errors; int vector; int index; int len; /* ack interrupt, read vector */ vector = sysBusIntAck (egl->eglIntLevel) & 0x00ff; /* XXX temporarily while R3K targets don't do vectored VME interrupts */ if (vector != (shio->sh_VMEIV & 0x00ff)) {#ifdef EGL_DEBUG logMsg ("egl%d: vectors disagree: sysBusIntAck = %#x, CSB-vec = %#x\n", unit, vector, shio->sh_VMEIV & 0x00ff, 0, 0, 0);#endif /* EGL_DEBUG */ vector = shio->sh_VMEIV & 0x00ff; } switch (vector - egl->eglIntVec) { case 0: /* xmit */ if (shio->sh_RET_IOPB.iopb_LAN1 & (LANCE_TONE | LANCE_TMORE)) egl->egl_if.if_collisions++; index = crb->crb_CTAG; CRB_CLR_DONE(crb->crb_CRSW); /* release Eagle */ netJobAdd ((FUNCPTR)egl_tint, unit, (int)egl, index, 0, 0); break; case 1: /* xmiterr */ tiopb = shio->sh_RET_IOPB; if (tiopb.iopb_LAN1 & LANCE_TERR) {#ifdef EGL_DEBUG sprintf (message, "egl%d: transmit error LAN1=%#x LAN3=%#x %s%s%s%s%s\n", unit, tiopb.iopb_LAN1, tiopb.iopb_LAN3, ((tiopb.iopb_LAN3&LAN3_BUFF) ? "buffer error " : nullmsg), ((tiopb.iopb_LAN3&LAN3_UFLO) ? "underflow " : nullmsg), ((tiopb.iopb_LAN3&LAN3_LCOL) ? "late collision " : nullmsg), ((tiopb.iopb_LAN3&LAN3_LCAR) ? "carrier loss " : nullmsg), ((tiopb.iopb_LAN3&LAN3_RTRY) ? "retry error" : nullmsg)); logMsg (message, 0, 0, 0, 0, 0, 0);#endif } else if (tiopb.iopb_STATUS) {#ifdef EGL_DEBUG logMsg ("egl%d: transmit error status %#x\n", unit, tiopb.iopb_STATUS, 0, 0, 0, 0);#endif } index = crb->crb_CTAG; CRB_CLR_DONE(crb->crb_CRSW); /* release Eagle */ egl->egl_if.if_oerrors++; egl->egl_if.if_opackets--; netJobAdd ((FUNCPTR)egl_tint, unit, (int)egl, index, 0, 0); break; case 2: /* rcv */ len = shio->sh_RET_IOPB.iopb_LENGTH;/* length of recv packet */ index = crb->crb_CTAG; CRB_CLR_DONE(crb->crb_CRSW); /* release Eagle */ netJobAdd ((FUNCPTR)egl_rint, unit, (int)egl, index, len, 0); break; case 3: /* rcverr */ len = shio->sh_RET_IOPB.iopb_LENGTH; /* length of recv packet */ index = crb->crb_CTAG; tiopb = shio->sh_RET_IOPB; if (tiopb.iopb_LAN1 & LANCE_RERR) { /* First, check for bogus LANCE errors: * call normal completion code if no "real" errors. */ real_errors = tiopb.iopb_LAN1; if ((tiopb.iopb_LAN1&LAN1_OFLO) && (tiopb.iopb_LAN1&LANCE_RENP)) real_errors ^= LAN1_OFLO; /* turn off bogus OFLO */ if (!(tiopb.iopb_LAN1&LANCE_RENP)|| (tiopb.iopb_LAN1&LAN1_OFLO)) real_errors &= (0xffff - (LAN1_FRAM | LAN1_CRC)); if (!(real_errors & (LAN1_FRAM|LAN1_OFLO|LAN1_CRC|LAN1_BUFF))) { /* Error was bogus. Treat like normal receive int. */ CRB_CLR_DONE(crb->crb_CRSW); /* release Eagle */ netJobAdd ((FUNCPTR)egl_rint, unit, (int)egl, index, len,0); return; } /* looks like a real receive error */#ifdef EGL_DEBUG sprintf (message, "egl%d: receive error LAN1=%#x LAN3=%#x %s%s%s%s\n", unit, tiopb.iopb_LAN1, tiopb.iopb_LAN3, (real_errors&LAN1_FRAM) ? "framing error " : nullmsg, (real_errors&LAN1_OFLO) ? "overflow " : nullmsg, (real_errors&LAN1_CRC) ? "CRC error " : nullmsg, (real_errors&LAN1_BUFF) ? "buffer error" : nullmsg);#endif if ((++egl->egl_if.if_ierrors % 100) == 0) { /* Interphase Inc. only reports every 100 errors; * we seem to get a fair number of CRC errors but * probably they're bogus. */#ifdef EGL_DEBUG logMsg (message, 0, 0, 0, 0, 0, 0);#endif } } else if (tiopb.iopb_STATUS) { /* only interesting if non RERR */#ifdef EGL_DEBUG logMsg ("egl%d: receive error status %#x\n", unit, tiopb.iopb_STATUS, 0, 0, 0, 0); /* valid only if no RERR */ if (!tiopb.iopb_LENGTH) logMsg ("egl%d: 0 length receive\n", unit, 0, 0, 0, 0, 0);#endif } if (csb->csb_CSR0MISS > egl->egl_csr0miss) { /* any new ones? */ egl->egl_csr0miss = csb->csb_CSR0MISS;#ifdef EGL_DEBUG logMsg ("egl%d: csr0 missed receive packet, count = %d\n", unit, egl->egl_csr0miss, 0, 0, 0, 0);#endif } CRB_CLR_DONE(crb->crb_CRSW); /* release Eagle */ egl->egl_if.if_ierrors++; netJobAdd ((FUNCPTR)egl_rint, unit, (int)egl, index, -1, 0); break; case 4: /* qav */ netJobAdd ((FUNCPTR)egl_qint, unit, (int)egl, 0, 0, 0); break; default:#ifdef EGL_DEBUG logMsg ( "egl%d: egl_intr - unknown interrupt vector %#x\n", unit, vector, 0, 0, 0, 0);#endif break; } }/********************************************************************************* egl_ioctl - process an ioctl request** RETURNS: 0 or errno.*/LOCAL int egl_ioctl ( struct ifnet *ifp, int cmd, caddr_t data ) { int unit = ifp->if_unit; EGL_SOFTC *egl = egl_softc [unit]; int error = 0; int status; int s; s = splimp (); switch (cmd) { case SIOCSIFADDR: /* Set */ ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN (data)->sin_addr; arpwhohas (ifp, &IA_SIN (data)->sin_addr); break; case SIOCGIFADDR: /* Get */ bcopy ((char*)egl->egl_enaddr, (caddr_t) ((struct ifreq *)data)->ifr_addr.sa_data, 6);#ifdef EGL_DEBUG printf ("egl%d: egl_ioctl - SIOCGIFADDR\n", unit);#endif /* EGL_DEBUG */ break; case SIOCGIFFLAGS: /* Get */ *(short *)data = ifp->if_flags;#ifdef EGL_DEBUG printf ("egl%d: egl_ioctl - SIOCGIFFLAGS\n", unit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -