void ubmemfree(struct uba_softc *uh, struct ubinfo *ui) { bus_dmamem_unmap(uh->uh_dmat, ui->ui_vaddr, ui->ui_size); bus_dmamem_free(uh->uh_dmat, &ui->ui_seg, ui->ui_rseg); ubfree(uh, ui); }
/* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. A STATUS command is done to get the ethernet * address and other interesting data. */ void ilattach(device_t parent, device_t self, void *aux) { struct uba_attach_args *ua = aux; struct il_softc *sc = device_private(self); struct ifnet *ifp = &sc->sc_if; int error; sc->sc_dev = self; sc->sc_iot = ua->ua_iot; sc->sc_ioh = ua->ua_ioh; sc->sc_dmat = ua->ua_dmat; /* * Map interrupt vectors and reset function. */ uba_intr_establish(ua->ua_icookie, ua->ua_cvec, ilcint, sc, &sc->sc_cintrcnt); evcnt_attach_dynamic(&sc->sc_cintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt, device_xname(sc->sc_dev), "intr"); uba_intr_establish(ua->ua_icookie, ua->ua_cvec-4, ilrint, sc, &sc->sc_rintrcnt); evcnt_attach_dynamic(&sc->sc_rintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt, device_xname(sc->sc_dev), "intr"); uba_reset_establish(ilreset, sc->sc_dev); /* * Reset the board and map the statistics * buffer onto the Unibus. */ IL_WCSR(IL_CSR, ILC_RESET); (void)ilwait(sc, "reset"); sc->sc_ui.ui_size = sizeof(struct il_stats); sc->sc_ui.ui_vaddr = (void *)&sc->sc_stats; if ((error = uballoc(device_private(parent), &sc->sc_ui, 0))) return printf(": failed uballoc, error = %d\n", error); IL_WCSR(IL_BAR, LOWORD(sc->sc_ui.ui_baddr)); IL_WCSR(IL_BCR, sizeof(struct il_stats)); IL_WCSR(IL_CSR, ((sc->sc_ui.ui_baddr >> 2) & IL_EUA)|ILC_STAT); (void)ilwait(sc, "status"); ubfree(device_private(parent), &sc->sc_ui); printf("%s: module=%s firmware=%s\n", device_xname(sc->sc_dev), sc->sc_stats.ils_module, sc->sc_stats.ils_firmware); printf("%s: hardware address %s\n", device_xname(sc->sc_dev), ether_sprintf(sc->sc_stats.ils_addr)); strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST; ifp->if_init = ilinit; ifp->if_stop = ilstop; ifp->if_ioctl = ether_ioctl; ifp->if_start = ilstart; ifp->if_watchdog = ilwatch; IFQ_SET_READY(&ifp->if_snd); if_attach(ifp); ether_ifattach(ifp, sc->sc_stats.ils_addr); }
/* * Check for present DEQNA. Done by sending a fake setup packet * and wait for interrupt. */ int qematch(device_t parent, cfdata_t cf, void *aux) { struct qe_softc ssc; struct qe_softc *sc = &ssc; struct uba_attach_args *ua = aux; struct uba_softc *uh = device_private(parent); struct ubinfo ui; #define PROBESIZE 4096 struct qe_ring *ring; struct qe_ring *rp; int error, match; ring = malloc(PROBESIZE, M_TEMP, M_WAITOK|M_ZERO); memset(sc, 0, sizeof(*sc)); sc->sc_iot = ua->ua_iot; sc->sc_ioh = ua->ua_ioh; sc->sc_dmat = ua->ua_dmat; uh->uh_lastiv -= 4; QE_WCSR(QE_CSR_CSR, QE_RESET); QE_WCSR(QE_CSR_VECTOR, uh->uh_lastiv); /* * Map the ring area. Actually this is done only to be able to * send and receive a internal packet; some junk is loopbacked * so that the DEQNA has a reason to interrupt. */ ui.ui_size = PROBESIZE; ui.ui_vaddr = (void *)&ring[0]; if ((error = uballoc(uh, &ui, UBA_CANTWAIT))) { match = 0; goto out0; } /* * Init a simple "fake" receive and transmit descriptor that * points to some unused area. Send a fake setup packet. */ rp = (void *)ui.ui_baddr; ring[0].qe_flag = ring[0].qe_status1 = QE_NOTYET; ring[0].qe_addr_lo = LOWORD(&rp[4]); ring[0].qe_addr_hi = HIWORD(&rp[4]) | QE_VALID | QE_EOMSG | QE_SETUP; ring[0].qe_buf_len = -64; ring[2].qe_flag = ring[2].qe_status1 = QE_NOTYET; ring[2].qe_addr_lo = LOWORD(&rp[4]); ring[2].qe_addr_hi = HIWORD(&rp[4]) | QE_VALID; ring[2].qe_buf_len = -(1500/2); QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~QE_RESET); DELAY(1000); /* * Start the interface and wait for the packet. */ QE_WCSR(QE_CSR_CSR, QE_INT_ENABLE|QE_XMIT_INT|QE_RCV_INT); QE_WCSR(QE_CSR_RCLL, LOWORD(&rp[2])); QE_WCSR(QE_CSR_RCLH, HIWORD(&rp[2])); QE_WCSR(QE_CSR_XMTL, LOWORD(rp)); QE_WCSR(QE_CSR_XMTH, HIWORD(rp)); DELAY(10000); match = 1; /* * All done with the bus resources. */ ubfree(uh, &ui); out0: free(ring, M_TEMP); return match; }