/* * 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); }
/* * Allocate DMA-able memory and map it on the unibus. */ int ubmemalloc(struct uba_softc *uh, struct ubinfo *ui, int flags) { int waitok = (flags & UBA_CANTWAIT ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK); int error; if ((error = bus_dmamem_alloc(uh->uh_dmat, ui->ui_size, NBPG, 0, &ui->ui_seg, 1, &ui->ui_rseg, waitok))) return error; if ((error = bus_dmamem_map(uh->uh_dmat, &ui->ui_seg, ui->ui_rseg, ui->ui_size, &ui->ui_vaddr, waitok|BUS_DMA_COHERENT))) { bus_dmamem_free(uh->uh_dmat, &ui->ui_seg, ui->ui_rseg); return error; } if ((error = uballoc(uh, ui, flags))) { bus_dmamem_unmap(uh->uh_dmat, ui->ui_vaddr, ui->ui_size); bus_dmamem_free(uh->uh_dmat, &ui->ui_seg, ui->ui_rseg); } return error; }
/* * Initialization of interface; reinitialize UNIBUS usage. */ int dmcinit(struct ifnet *ifp) { struct dmc_softc *sc = ifp->if_softc; struct ifrw *ifrw; struct ifxmt *ifxp; struct dmcbufs *rp; struct dmc_command *qp; struct ifaddr *ifa; cfdata_t ui = device_cfdata(sc->sc_dev); int base; int s; /* * Check to see that an address has been set * (both local and destination for an address family). */ IFADDR_FOREACH(ifa, ifp) if (ifa->ifa_addr->sa_family && ifa->ifa_dstaddr->sa_family) break; if (ifa == (struct ifaddr *) 0) return 0; if ((DMC_RBYTE(DMC_BSEL1) & DMC_RUN) == 0) { printf("dmcinit: DMC not running\n"); ifp->if_flags &= ~IFF_UP; return 0; } /* map base table */ if ((sc->sc_flag & DMC_BMAPPED) == 0) { sc->sc_ui.ui_size = sizeof(struct dmc_base); sc->sc_ui.ui_vaddr = (void *)&sc->dmc_base; uballoc(device_private(device_parent(sc->sc_dev)), &sc->sc_ui, 0); sc->sc_flag |= DMC_BMAPPED; } /* initialize UNIBUS resources */ sc->sc_iused = sc->sc_oused = 0; if ((ifp->if_flags & IFF_RUNNING) == 0) { if (if_ubaminit(&sc->sc_ifuba, device_private(device_parent(sc->sc_dev)), sizeof(struct dmc_header) + DMCMTU, sc->sc_ifr, NRCV, sc->sc_ifw, NXMT) == 0) { aprint_error_dev(sc->sc_dev, "can't allocate uba resources\n"); ifp->if_flags &= ~IFF_UP; return 0; } ifp->if_flags |= IFF_RUNNING; } sc->sc_flag &= ~DMC_ONLINE; sc->sc_flag |= DMC_RUNNING; /* * Limit packets enqueued until we see if we're on the air. */ ifp->if_snd.ifq_maxlen = 3; /* initialize buffer pool */ /* receives */ ifrw = &sc->sc_ifr[0]; for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) { rp->ubinfo = ifrw->ifrw_info; rp->cc = DMCMTU + sizeof (struct dmc_header); rp->flags = DBUF_OURS|DBUF_RCV; ifrw++; } /* transmits */ ifxp = &sc->sc_ifw[0]; for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++) { rp->ubinfo = ifxp->ifw_info; rp->cc = 0; rp->flags = DBUF_OURS|DBUF_XMIT; ifxp++; } /* set up command queues */ sc->sc_qfreeh = sc->sc_qfreet = sc->sc_qhead = sc->sc_qtail = sc->sc_qactive = (struct dmc_command *)0; /* set up free command buffer list */ for (qp = &sc->sc_cmdbuf[0]; qp < &sc->sc_cmdbuf[NCMDS]; qp++) { QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet); } /* base in */ base = sc->sc_ui.ui_baddr; dmcload(sc, DMC_BASEI, (u_short)base, (base>>2) & DMC_XMEM); /* specify half duplex operation, flags tell if primary */ /* or secondary station */ if (ui->cf_flags == 0) /* use DDCMP mode in full duplex */ dmcload(sc, DMC_CNTLI, 0, 0); else if (ui->cf_flags == 1) /* use MAINTENENCE mode */ dmcload(sc, DMC_CNTLI, 0, DMC_MAINT ); else if (ui->cf_flags == 2) /* use DDCMP half duplex as primary station */ dmcload(sc, DMC_CNTLI, 0, DMC_HDPLX); else if (ui->cf_flags == 3) /* use DDCMP half duplex as secondary station */ dmcload(sc, DMC_CNTLI, 0, DMC_HDPLX | DMC_SEC); /* enable operation done interrupts */ while ((DMC_RBYTE(DMC_BSEL2) & DMC_IEO) == 0) DMC_WBYTE(DMC_BSEL2, DMC_RBYTE(DMC_BSEL2) | DMC_IEO); s = splnet(); /* queue first NRCV buffers for DMC to fill */ for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) { rp->flags |= DBUF_DMCS; dmcload(sc, DMC_READ, rp->ubinfo, (((rp->ubinfo>>2)&DMC_XMEM) | rp->cc)); sc->sc_iused++; } splx(s); return 0; }
/* * 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; }
/* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */ int ilinit(struct ifnet *ifp) { struct il_softc *sc = ifp->if_softc; int s; if (sc->sc_flags & ILF_RUNNING) return 0; if ((ifp->if_flags & IFF_RUNNING) == 0) { if (if_ubainit(&sc->sc_ifuba, device_private(device_parent(sc->sc_dev)), ETHER_MAX_LEN)) { aprint_error_dev(sc->sc_dev, "can't initialize\n"); sc->sc_if.if_flags &= ~IFF_UP; return 0; } sc->sc_ui.ui_size = sizeof(sc->sc_isu); sc->sc_ui.ui_vaddr = (void *)&sc->sc_isu; uballoc(device_private(device_parent(sc->sc_dev)), &sc->sc_ui, 0); } sc->sc_scaninterval = ILWATCHINTERVAL; ifp->if_timer = sc->sc_scaninterval; /* * Turn off source address insertion (it's faster this way), * and set board online. Former doesn't work if board is * already online (happens on ubareset), so we put it offline * first. */ s = splnet(); IL_WCSR(IL_CSR, ILC_RESET); if (ilwait(sc, "hardware diag")) { sc->sc_if.if_flags &= ~IFF_UP; goto out; } IL_WCSR(IL_CSR, ILC_CISA); while ((IL_RCSR(IL_CSR) & IL_CDONE) == 0) ; /* * If we must reprogram this board's physical ethernet * address (as for secondary XNS interfaces), we do so * before putting it on line, and starting receive requests. * If you try this on an older 1010 board, it will total * wedge the board. */ if (sc->sc_flags & ILF_SETADDR) { memcpy(&sc->sc_isu, CLLADDR(ifp->if_sadl), ETHER_ADDR_LEN); IL_WCSR(IL_BAR, LOWORD(sc->sc_ui.ui_baddr)); IL_WCSR(IL_BCR, ETHER_ADDR_LEN); IL_WCSR(IL_CSR, ((sc->sc_ui.ui_baddr >> 2) & IL_EUA)|ILC_LDPA); if (ilwait(sc, "setaddr")) goto out; 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); if (ilwait(sc, "verifying setaddr")) goto out; if (memcmp(sc->sc_stats.ils_addr, CLLADDR(ifp->if_sadl), ETHER_ADDR_LEN) != 0) { aprint_error_dev(sc->sc_dev, "setaddr didn't work\n"); goto out; } }