📄 if_egl.c
字号:
#endif /* EGL_DEBUG */ break; case SIOCSIFFLAGS: /* Set */ /* Handled outside module - nothing more to do. */ break; default:#ifdef EGL_DEBUG printf ("egl%d: egl_ioctl - unknown ioctl\n", unit);#endif /* EGL_DEBUG */ error = EINVAL; break; } splx (s); return (error); }/********************************************************************************* egl_iworkq - initialize work queues** RETURNS: 0 or -1 on error.*/LOCAL int egl_iworkq ( int unit, int itype ) { EGL_SOFTC *egl = egl_softc [unit]; volatile SHIO *shio = egl->eglAddr; volatile WQCF *iopb = (WQCF *)&shio->sh_MCE_IOPB; volatile USHORT *mcr = &shio->sh_MCSB.mcsb_MCR; int ix; iopb->wqcf_CMD = CNTR_INIT_WORKQ; iopb->wqcf_OPTION |= itype; /* 0 no int; 1 int (M_OPT_IE) */ iopb->wqcf_NVCT = egl->qav_vec; iopb->wqcf_EVCT = egl->qav_vec; bzero ((char*)iopb->wqcf_RES0, sizeof(iopb->wqcf_RES0)); iopb->wqcf_WORKQ = EGL_MISCQ; /* misc queue */ iopb->wqcf_WOPT = 0; iopb->wqcf_SLOTS = EGL_MS_SLOTS; /* misc queue size */ iopb->wqcf_PRIORITY = EGL_MS_PRIORITY; /* misc queue priority */ iopb->wqcf_WDIV = EGL_MS_WDIV; /* misc queue work division */ bzero ((char*)iopb->wqcf_RES1, sizeof(iopb->wqcf_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 initialize misc workq\n", unit, 0, 0, 0, 0, 0);#endif return (-1); } else if (ix == 0x1000) /* unused value */ {#ifdef EGL_DEBUG logMsg ("egl%d: *timeout* unable to initialize misc workq\n", unit, 0, 0, 0, 0, 0);#endif return (-1); } } else {#ifdef EGL_DEBUG logMsg ("egl%d: initialize misc workq done\n", unit, 0, 0, 0, 0, 0);#endif /* EGL_DEBUG */ } /* DMA MCE IOPB */ iopb->wqcf_CMD = CNTR_INIT_WORKQ; iopb->wqcf_OPTION |= itype; /* 0 no int; 1 int (M_OPT_IE) */ iopb->wqcf_NVCT = egl->qav_vec; iopb->wqcf_EVCT = egl->qav_vec; bzero ((char*)iopb->wqcf_RES0, sizeof(iopb->wqcf_RES0)); iopb->wqcf_WORKQ = EGL_DMAQ; /* misc queue */ iopb->wqcf_WOPT = 0; iopb->wqcf_SLOTS = EGL_DM_SLOTS; /* misc queue size */ iopb->wqcf_PRIORITY = EGL_DM_PRIORITY; /* misc queue priority */ iopb->wqcf_WDIV = EGL_DM_WDIV; /* misc queue work division */ bzero ((char*)iopb->wqcf_RES1, sizeof(iopb->wqcf_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 initialize DMA workq\n", unit, 0, 0, 0, 0, 0);#endif return (-1); } else if (ix == 0x1000) /* unused value */ {#ifdef EGL_DEBUG logMsg ("egl%d: *timeout* unable to initialize DMA workq\n", unit, 0, 0, 0, 0, 0);#endif return (-1); } } else {#ifdef EGL_DEBUG logMsg ("egl%d: initialize DMA workq done\n", unit, 0, 0, 0, 0, 0);#endif /* EGL_DEBUG */ } /* receive MCE IOPB */ iopb->wqcf_CMD = CNTR_INIT_WORKQ; iopb->wqcf_OPTION |= itype; /* 0 no int; 1 int (M_OPT_IE) */ iopb->wqcf_NVCT = egl->qav_vec; iopb->wqcf_EVCT = egl->qav_vec; bzero ((char*)iopb->wqcf_RES0, sizeof(iopb->wqcf_RES0)); iopb->wqcf_WORKQ = EGL_RECVQ; /* receive queue */ iopb->wqcf_WOPT = 0; iopb->wqcf_SLOTS = EGL_RX_SLOTS; /* receive queue size */ iopb->wqcf_PRIORITY = EGL_RX_PRIORITY; /* receive queue priority */ iopb->wqcf_WDIV = EGL_RX_WDIV; /* receive q work division */ bzero ((char*)iopb->wqcf_RES1, sizeof(iopb->wqcf_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 initialize receive workq\n", unit, 0, 0, 0, 0, 0);#endif return (-1); } else if (ix == 0x1000) /* unused value */ {#ifdef EGL_DEBUG logMsg ("egl%d: *timeout* unable to initialize receive workq\n", unit, 0, 0, 0, 0, 0);#endif return (-1); } } else {#ifdef EGL_DEBUG logMsg ("egl%d: initialize receive workq done\n", unit, 0, 0, 0, 0, 0);#endif /* EGL_DEBUG */ } /* transmit MCE IOPB */ iopb->wqcf_CMD = CNTR_INIT_WORKQ; iopb->wqcf_OPTION |= itype; /* 0 no int; 1 int (M_OPT_IE) */ iopb->wqcf_NVCT = egl->qav_vec; iopb->wqcf_EVCT = egl->qav_vec; bzero ((char*)iopb->wqcf_RES0, sizeof(iopb->wqcf_RES0)); iopb->wqcf_WORKQ = EGL_XMTQN(0); /* transmit queue 0 */ iopb->wqcf_WOPT = 0; iopb->wqcf_SLOTS = EGL_TX_SLOTS; /* transmit queue size */ iopb->wqcf_PRIORITY = EGL_TX_PRIORITY; /* transmit queue priority */ iopb->wqcf_WDIV = EGL_TX_WDIV; /* transmit q work division */ bzero ((char*)iopb->wqcf_RES1, sizeof(iopb->wqcf_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 initialize transmit workq\n", unit, 0, 0, 0, 0, 0);#endif return (-1); } else if (ix == 0x1000) /* unused value */ {#ifdef EGL_DEBUG logMsg ("egl%d: *timeout* unable to initialize transmit workq\n", unit, 0, 0, 0, 0, 0);#endif return (-1); } } else {#ifdef EGL_DEBUG logMsg ("egl%d: initialize transmit workq done\n", unit, 0, 0, 0, 0, 0);#endif /* EGL_DEBUG */ } *mcr |= M_MCR_SQM; /* start queue mode */ sysWbFlush(); return (0); }#ifdef BSD43_DRIVER/********************************************************************************* egl_output - Ethernet output routine** RETURNS: ?*/LOCAL int egl_output ( struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst ) { return (ether_output (ifp, m0, dst, (FUNCPTR) egl_start, &egl_softc [ifp->if_unit]->egl_ac)); }#endif/********************************************************************************* egl_physreset - physical reset of the Interphase Eagle card** RETURNS: 0 or -1 if reset or diagnostics fail.*/LOCAL STATUS egl_physreset ( int unit ) { EGL_SOFTC *egl = egl_softc [unit]; volatile SHIO *shio = egl->eglAddr; volatile USHORT *msr = &shio->sh_MCSB.mcsb_MSR; volatile USHORT *mcr = &shio->sh_MCSB.mcsb_MCR; int ix;#ifdef EGL_DEBUG printf ("egl%d: egl_physreset - msr address = %#x\n", unit, msr);#endif /* EGL_DEBUG */ for (ix = 0; ix < 1000; ix++) { if (!(*msr & M_MSR_CNA) && (*msr & M_MSR_BOK)) break; DELAY(8000); } if (ix == 1000) {#ifdef EGL_DEBUG printf ( "egl%d: diagnostics failed, or controller not available; msr = %#x\n", unit, *msr);#endif return (-1); } *msr |= M_MSR_CNA; sysWbFlush(); *mcr = M_MCR_RES; /* reset the Eagle */ sysWbFlush(); DELAY(500); /* at least 50usec required */ *mcr &= ~M_MCR_RES; sysWbFlush(); for (ix = 0; ix < 1000; ix++) { if (!(*msr & M_MSR_CNA)) break; DELAY(8000); } if (ix == 1000) {#ifdef EGL_DEBUG printf ("egl%d: diagnostics failed during phase 1; msr = %#x\n", unit, *msr);#endif return (-1); } /* more delay necessary as reset is not yet done! (Interphase bug) */ for (ix = 0; ix < 1000; ix++) { if (*msr & M_MSR_BOK) break; DELAY(8000); } if (ix == 1000) {#ifdef EGL_DEBUG printf ("egl%d: diagnostics failed during phase 2; msr = %#x\n", unit, *msr);#endif *msr |= M_MSR_BOK; /* re-set board OK (iphase bug) */ return (-1); } return (0); }/********************************************************************************* egl_qint - Ethernet interface queue entry available interrupt*/LOCAL void egl_qint ( int unit, EGL_SOFTC *egl ) { volatile SHIO *shio = egl->eglAddr; volatile CRB *crb = &shio->sh_CRB; volatile CSB *csb = &shio->sh_CSB; volatile USHORT *msr = &shio->sh_MCSB.mcsb_MSR; IOPB tiopb; tiopb = shio->sh_RET_IOPB; /* controller not available */ if (*msr & M_MSR_CNA) {#ifdef EGL_DEBUG logMsg ("egl%d: died and restarted; error status = %#x\n", unit, tiopb.iopb_STATUS, 0, 0, 0, 0);#endif /* these errors (among others) will turn the LANCE transmitter off, which will send us here */ /* any new ones? */ if (csb->csb_CSR0MEM > egl->egl_csr0mem) { egl->egl_csr0mem = csb->csb_CSR0MEM;#ifdef EGL_DEBUG logMsg ("egl%d: %d csr0 MEMORY ERRORS caught\n", unit, egl->egl_csr0mem, 0, 0, 0, 0);#endif }#ifdef EGL_DEBUG /* save the returned IOPB */ logMsg ("returned IOPB: cmd %#x options %#x status %#x nvect %#x\n", tiopb.iopb_CMD, tiopb.iopb_OPTION, tiopb.iopb_STATUS, tiopb.iopb_NVCT, 0, 0); logMsg ("evect %#x topt %#x buff_addr %#x length %#x\n", tiopb.iopb_EVCT, tiopb.iopb_TOPT, tiopb.iopb_BUFF, tiopb.iopb_LENGTH, 0, 0); logMsg ("host_buf %#x ptlf %#x sge_cnt %#x lan1 %#x lan3 %#x\n", tiopb.iopb_HBUF, tiopb.iopb_PTLF, tiopb.iopb_SGEC, tiopb.iopb_LAN1, tiopb.iopb_LAN3, 0); logMsg ("src/dest node %x:%x:%x:%x:%x:%x\n", tiopb.iopb_NODE[0],tiopb.iopb_NODE[1],tiopb.iopb_NODE[2], tiopb.iopb_NODE[3],tiopb.iopb_NODE[4],tiopb.iopb_NODE[5]);#endif /* EGL_DEBUG */ egl_init (unit); return; } if (CRB_QAVAIL(crb->crb_CRSW)) { /* feed queue is no longer full */ egl->egl_qfull = 0; /* at least one slot open now */ } if (CRB_QSTARTED(crb->crb_CRSW)) { /* how about q mode started */ egl->egl_qmode++; /* remember for later */ } CRB_CLR_DONE(crb->crb_CRSW); /* release Eagle */ }/********************************************************************************* egl_recv - process Ethernet receive completion** This procedure handles Ethernet receive completion interrupts. If* input error just drop packet, otherwise examine packet to determine* type. If can't determine length from type, then have to drop packet,* otherwise decapsulate packet based on type and pass to type-specific* higher-level input routine.** RETURNS: ?*/LOCAL void egl_recv ( int unit, int len, ETH_BUF *eth_buf ) { EGL_SOFTC *egl = egl_softc [unit]; struct ether_header *eh; struct mbuf *m;#ifdef BSD43_DRIVER int off;#endif unsigned char *pData; egl->egl_if.if_ipackets++; /* speed fix (in Eagle firmware) for 14 byte Ethernet header */ eh = (struct ether_header *) ((int)eth_buf->eth_dat + 2); /* call input hook if any */ if (etherInputHookRtn != NULL && (* etherInputHookRtn) (&egl->egl_if, (char *) eh, len)) { return; } len -= SIZEOF_ETHERHEADER + 4; /* total length - (ether header + CRC) */ pData = ((unsigned char *) eh) + SIZEOF_ETHERHEADER;#ifdef BSD43_DRIVER check_trailer (eh, pData, &len, &off, &egl->egl_if); if (len == 0) return; /* copy data from Eagle to mbuf a word at a time */ m = bcopy_to_mbufs (pData, len, off, (struct ifnet *) &egl->egl_if, eglMemWidth); if (m != NULL) do_protocol_with_type (eh->ether_type, m, &egl->egl_ac, len);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -