static void qeintr(void *arg) { struct qe_softc *sc = arg; struct qe_cdata *qc = sc->sc_qedata; struct ifnet *ifp = &sc->sc_if; struct ether_header *eh; struct mbuf *m; int csr, status1, status2, len; csr = QE_RCSR(QE_CSR_CSR); QE_WCSR(QE_CSR_CSR, QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT | QE_ILOOP); if (csr & QE_RCV_INT) while (qc->qc_recv[sc->sc_nextrx].qe_status1 != QE_NOTYET) { status1 = qc->qc_recv[sc->sc_nextrx].qe_status1; status2 = qc->qc_recv[sc->sc_nextrx].qe_status2; m = sc->sc_rxmbuf[sc->sc_nextrx]; len = ((status1 & QE_RBL_HI) | (status2 & QE_RBL_LO)) + 60; qe_add_rxbuf(sc, sc->sc_nextrx); m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = m->m_len = len; if (++sc->sc_nextrx == RXDESCS) sc->sc_nextrx = 0; eh = mtod(m, struct ether_header *); #if NBPFILTER > 0 if (ifp->if_bpf) { bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); if ((ifp->if_flags & IFF_PROMISC) != 0 && bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN) != 0 && ((eh->ether_dhost[0] & 1) == 0)) { m_freem(m); continue; } } #endif /* * ALLMULTI means PROMISC in this driver. */ if ((ifp->if_flags & IFF_ALLMULTI) && ((eh->ether_dhost[0] & 1) == 0) && bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN)) { m_freem(m); continue; } if ((status1 & QE_ESETUP) == 0) ether_input_mbuf(ifp, m); else m_freem(m); } if (csr & (QE_XMIT_INT|QE_XL_INVALID)) { while (qc->qc_xmit[sc->sc_lastack].qe_status1 != QE_NOTYET) { int idx = sc->sc_lastack; sc->sc_inq--; if (++sc->sc_lastack == TXDESCS) sc->sc_lastack = 0; /* XXX collect statistics */ qc->qc_xmit[idx].qe_addr_hi &= ~QE_VALID; qc->qc_xmit[idx].qe_status1 = qc->qc_xmit[idx].qe_flag = QE_NOTYET; if (qc->qc_xmit[idx].qe_addr_hi & QE_SETUP) continue; bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[idx]); if (sc->sc_txmbuf[idx]) { m_freem(sc->sc_txmbuf[idx]); sc->sc_txmbuf[idx] = 0; } } ifp->if_timer = 0; ifp->if_flags &= ~IFF_OACTIVE; qestart(ifp); /* Put in more in queue */ } /* * How can the receive list get invalid??? * Verified that it happens anyway. */ if ((qc->qc_recv[sc->sc_nextrx].qe_status1 == QE_NOTYET) && (QE_RCSR(QE_CSR_CSR) & QE_RL_INVALID)) { QE_WCSR(QE_CSR_RCLL, LOWORD(&sc->sc_pqedata->qc_recv[sc->sc_nextrx])); QE_WCSR(QE_CSR_RCLH, HIWORD(&sc->sc_pqedata->qc_recv[sc->sc_nextrx])); } }
/* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */ void qeattach(device_t parent, device_t self, void *aux) { struct uba_attach_args *ua = aux; struct qe_softc *sc = device_private(self); struct ifnet *ifp = &sc->sc_if; struct qe_ring *rp; u_int8_t enaddr[ETHER_ADDR_LEN]; int i, error; char *nullbuf; sc->sc_dev = self; sc->sc_uh = device_private(parent); sc->sc_iot = ua->ua_iot; sc->sc_ioh = ua->ua_ioh; sc->sc_dmat = ua->ua_dmat; /* * Allocate DMA safe memory for descriptors and setup memory. */ sc->sc_ui.ui_size = sizeof(struct qe_cdata) + ETHER_PAD_LEN; if ((error = ubmemalloc(sc->sc_uh, &sc->sc_ui, 0))) { aprint_error(": unable to ubmemalloc(), error = %d\n", error); return; } sc->sc_pqedata = (struct qe_cdata *)sc->sc_ui.ui_baddr; sc->sc_qedata = (struct qe_cdata *)sc->sc_ui.ui_vaddr; /* * Zero the newly allocated memory. */ memset(sc->sc_qedata, 0, sizeof(struct qe_cdata) + ETHER_PAD_LEN); nullbuf = ((char*)sc->sc_qedata) + sizeof(struct qe_cdata); /* * Create the transmit descriptor DMA maps. We take advantage * of the fact that the Qbus address space is big, and therefore * allocate map registers for all transmit descriptors also, * so that we can avoid this each time we send a packet. */ for (i = 0; i < TXDESCS; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &sc->sc_xmtmap[i]))) { aprint_error( ": unable to create tx DMA map %d, error = %d\n", i, error); goto fail_4; } } /* * Create receive buffer DMA maps. */ for (i = 0; i < RXDESCS; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, BUS_DMA_NOWAIT, &sc->sc_rcvmap[i]))) { aprint_error( ": unable to create rx DMA map %d, error = %d\n", i, error); goto fail_5; } } /* * Pre-allocate the receive buffers. */ for (i = 0; i < RXDESCS; i++) { if ((error = qe_add_rxbuf(sc, i)) != 0) { aprint_error( ": unable to allocate or map rx buffer %d," " error = %d\n", i, error); goto fail_6; } } if ((error = bus_dmamap_create(sc->sc_dmat, ETHER_PAD_LEN, 1, ETHER_PAD_LEN, 0, BUS_DMA_NOWAIT,&sc->sc_nulldmamap)) != 0) { aprint_error( ": unable to create pad buffer DMA map, error = %d\n", error); goto fail_6; } if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_nulldmamap, nullbuf, ETHER_PAD_LEN, NULL, BUS_DMA_NOWAIT)) != 0) { aprint_error( ": unable to load pad buffer DMA map, error = %d\n", error); goto fail_7; } bus_dmamap_sync(sc->sc_dmat, sc->sc_nulldmamap, 0, ETHER_PAD_LEN, BUS_DMASYNC_PREWRITE); /* * Create ring loops of the buffer chains. * This is only done once. */ rp = sc->sc_qedata->qc_recv; rp[RXDESCS].qe_addr_lo = LOWORD(&sc->sc_pqedata->qc_recv[0]); rp[RXDESCS].qe_addr_hi = HIWORD(&sc->sc_pqedata->qc_recv[0]) | QE_VALID | QE_CHAIN; rp[RXDESCS].qe_flag = rp[RXDESCS].qe_status1 = QE_NOTYET; rp = sc->sc_qedata->qc_xmit; rp[TXDESCS].qe_addr_lo = LOWORD(&sc->sc_pqedata->qc_xmit[0]); rp[TXDESCS].qe_addr_hi = HIWORD(&sc->sc_pqedata->qc_xmit[0]) | QE_VALID | QE_CHAIN; rp[TXDESCS].qe_flag = rp[TXDESCS].qe_status1 = QE_NOTYET; /* * Get the vector that were set at match time, and remember it. */ sc->sc_intvec = sc->sc_uh->uh_lastiv; QE_WCSR(QE_CSR_CSR, QE_RESET); DELAY(1000); QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~QE_RESET); /* * Read out ethernet address and tell which type this card is. */ for (i = 0; i < 6; i++) enaddr[i] = QE_RCSR(i * 2) & 0xff; QE_WCSR(QE_CSR_VECTOR, sc->sc_intvec | 1); aprint_normal(": %s, hardware address %s\n", QE_RCSR(QE_CSR_VECTOR) & 1 ? "delqa":"deqna", ether_sprintf(enaddr)); QE_WCSR(QE_CSR_VECTOR, QE_RCSR(QE_CSR_VECTOR) & ~1); /* ??? */ uba_intr_establish(ua->ua_icookie, ua->ua_cvec, qeintr, sc, &sc->sc_intrcnt); evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt, device_xname(sc->sc_dev), "intr"); strcpy(ifp->if_xname, device_xname(sc->sc_dev)); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_start = qestart; ifp->if_ioctl = qeioctl; ifp->if_watchdog = qetimeout; IFQ_SET_READY(&ifp->if_snd); /* * Attach the interface. */ if_attach(ifp); ether_ifattach(ifp, enaddr); return; /* * Free any resources we've allocated during the failed attach * attempt. Do this in reverse order and fall through. */ fail_7: bus_dmamap_destroy(sc->sc_dmat, sc->sc_nulldmamap); fail_6: for (i = 0; i < RXDESCS; i++) { if (sc->sc_rxmbuf[i] != NULL) { bus_dmamap_unload(sc->sc_dmat, sc->sc_rcvmap[i]); m_freem(sc->sc_rxmbuf[i]); } } fail_5: for (i = 0; i < RXDESCS; i++) { if (sc->sc_rcvmap[i] != NULL) bus_dmamap_destroy(sc->sc_dmat, sc->sc_rcvmap[i]); } fail_4: for (i = 0; i < TXDESCS; i++) { if (sc->sc_xmtmap[i] != NULL) bus_dmamap_destroy(sc->sc_dmat, sc->sc_xmtmap[i]); } }
/* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */ void qeattach(struct device *parent, struct device *self, void *aux) { struct uba_attach_args *ua = aux; struct uba_softc *ubasc = (struct uba_softc *)parent; struct qe_softc *sc = (struct qe_softc *)self; struct ifnet *ifp = (struct ifnet *)&sc->sc_if; struct qe_ring *rp; int i, error; sc->sc_iot = ua->ua_iot; sc->sc_ioh = ua->ua_ioh; sc->sc_dmat = ua->ua_dmat; /* * Allocate DMA safe memory for descriptors and setup memory. */ sc->sc_ui.ui_size = sizeof(struct qe_cdata); if ((error = ubmemalloc((struct uba_softc *)parent, &sc->sc_ui, 0))) { printf(": unable to ubmemalloc(), error = %d\n", error); return; } sc->sc_pqedata = (struct qe_cdata *)sc->sc_ui.ui_baddr; sc->sc_qedata = (struct qe_cdata *)sc->sc_ui.ui_vaddr; /* * Zero the newly allocated memory. */ bzero(sc->sc_qedata, sizeof(struct qe_cdata)); /* * Create the transmit descriptor DMA maps. We take advantage * of the fact that the Qbus address space is big, and therefore * allocate map registers for all transmit descriptors also, * so that we can avoid this each time we send a packet. */ for (i = 0; i < TXDESCS; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &sc->sc_xmtmap[i]))) { printf(": unable to create tx DMA map %d, error = %d\n", i, error); goto fail_4; } } /* * Create receive buffer DMA maps. */ for (i = 0; i < RXDESCS; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, BUS_DMA_NOWAIT, &sc->sc_rcvmap[i]))) { printf(": unable to create rx DMA map %d, error = %d\n", i, error); goto fail_5; } } /* * Pre-allocate the receive buffers. */ for (i = 0; i < RXDESCS; i++) { if ((error = qe_add_rxbuf(sc, i)) != 0) { printf(": unable to allocate or map rx buffer %d\n," " error = %d\n", i, error); goto fail_6; } } /* * Create ring loops of the buffer chains. * This is only done once. */ rp = sc->sc_qedata->qc_recv; rp[RXDESCS].qe_addr_lo = LOWORD(&sc->sc_pqedata->qc_recv[0]); rp[RXDESCS].qe_addr_hi = HIWORD(&sc->sc_pqedata->qc_recv[0]) | QE_VALID | QE_CHAIN; rp[RXDESCS].qe_flag = rp[RXDESCS].qe_status1 = QE_NOTYET; rp = sc->sc_qedata->qc_xmit; rp[TXDESCS].qe_addr_lo = LOWORD(&sc->sc_pqedata->qc_xmit[0]); rp[TXDESCS].qe_addr_hi = HIWORD(&sc->sc_pqedata->qc_xmit[0]) | QE_VALID | QE_CHAIN; rp[TXDESCS].qe_flag = rp[TXDESCS].qe_status1 = QE_NOTYET; /* * Get the vector that were set at match time, and remember it. */ sc->sc_intvec = ubasc->uh_lastiv; QE_WCSR(QE_CSR_CSR, QE_RESET); DELAY(1000); QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~QE_RESET); /* * Read out ethernet address and tell which type this card is. */ for (i = 0; i < 6; i++) sc->sc_ac.ac_enaddr[i] = QE_RCSR(i * 2) & 0xff; QE_WCSR(QE_CSR_VECTOR, sc->sc_intvec | 1); printf(": %s, address %s\n", QE_RCSR(QE_CSR_VECTOR) & 1 ? "delqa" : "deqna", ether_sprintf(sc->sc_ac.ac_enaddr)); QE_WCSR(QE_CSR_VECTOR, QE_RCSR(QE_CSR_VECTOR) & ~1); /* ??? */ uba_intr_establish(ua->ua_icookie, ua->ua_cvec, qeintr, sc, &sc->sc_intrcnt); sc->sc_cvec = ua->ua_cvec; evcount_attach(&sc->sc_intrcnt, sc->sc_dev.dv_xname, &sc->sc_cvec); strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, sizeof ifp->if_xname); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_start = qestart; ifp->if_ioctl = qeioctl; ifp->if_watchdog = qetimeout; IFQ_SET_READY(&ifp->if_snd); /* * Attach the interface. */ if_attach(ifp); ether_ifattach(ifp); return; /* * Free any resources we've allocated during the failed attach * attempt. Do this in reverse order and fall through. */ fail_6: for (i = 0; i < RXDESCS; i++) { if (sc->sc_rxmbuf[i] != NULL) { bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[i]); m_freem(sc->sc_rxmbuf[i]); } } fail_5: for (i = 0; i < RXDESCS; i++) { if (sc->sc_xmtmap[i] != NULL) bus_dmamap_destroy(sc->sc_dmat, sc->sc_xmtmap[i]); } fail_4: for (i = 0; i < TXDESCS; i++) { if (sc->sc_rcvmap[i] != NULL) bus_dmamap_destroy(sc->sc_dmat, sc->sc_rcvmap[i]); } }