Exemplo n.º 1
0
/*
 * 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;
}
Exemplo n.º 2
0
/*
 * Initialization of interface; clear recorded pending
 * operations, and reinitialize UNIBUS usage.
 */
int
deinit(struct ifnet *ifp)
{
	struct de_softc *sc = ifp->if_softc;
	struct de_cdata *dc, *pdc;
	struct ifrw *ifrw;
	struct ifxmt *ifxp;
	struct de_ring *rp;
	int s, error;

	if (ifp->if_flags & IFF_RUNNING)
		return 0;
	if ((sc->sc_flags & DSF_MAPPED) == 0) {
		if (if_ubaminit(&sc->sc_ifuba, (void *)sc->sc_dev.dv_parent,
		    MCLBYTES, sc->sc_ifr, NRCV, sc->sc_ifw, NXMT)) {
			printf("%s: can't initialize\n", sc->sc_dev.dv_xname);
			ifp->if_flags &= ~IFF_UP;
			return 0;
		}
		sc->sc_ui.ui_size = sizeof(struct de_cdata);
		if ((error = ubmemalloc((void *)sc->sc_dev.dv_parent,
		    &sc->sc_ui, 0))) {
			printf(": unable to ubmemalloc(), error = %d\n", error);
			return 0;
		}
		sc->sc_pdedata = (struct de_cdata *)sc->sc_ui.ui_baddr;
		sc->sc_dedata = (struct de_cdata *)sc->sc_ui.ui_vaddr;
		sc->sc_flags |= DSF_MAPPED;
	}

	/*
	 * Tell the DEUNA about our PCB
	 */
	DE_WCSR(DE_PCSR2, LOWORD(sc->sc_pdedata));
	DE_WCSR(DE_PCSR3, HIWORD(sc->sc_pdedata));
	DE_WLOW(0);		/* reset INTE */
	DELAY(500);
	DE_WLOW(CMD_GETPCBB);
	dewait(sc, "pcbb");

	dc = sc->sc_dedata;
	pdc = sc->sc_pdedata;
	/* set the transmit and receive ring header addresses */
	dc->dc_pcbb.pcbb0 = FC_WTRING;
	dc->dc_pcbb.pcbb2 = LOWORD(&pdc->dc_udbbuf);
	dc->dc_pcbb.pcbb4 = HIWORD(&pdc->dc_udbbuf);

	dc->dc_udbbuf.b_tdrbl = LOWORD(&pdc->dc_xrent[0]);
	dc->dc_udbbuf.b_tdrbh = HIWORD(&pdc->dc_xrent[0]);
	dc->dc_udbbuf.b_telen = sizeof (struct de_ring) / sizeof(u_int16_t);
	dc->dc_udbbuf.b_trlen = NXMT;
	dc->dc_udbbuf.b_rdrbl = LOWORD(&pdc->dc_rrent[0]);
	dc->dc_udbbuf.b_rdrbh = HIWORD(&pdc->dc_rrent[0]);
	dc->dc_udbbuf.b_relen = sizeof (struct de_ring) / sizeof(u_int16_t);
	dc->dc_udbbuf.b_rrlen = NRCV;

	DE_WLOW(CMD_GETCMD);
	dewait(sc, "wtring");

	sc->sc_dedata->dc_pcbb.pcbb0 = FC_WTMODE;
	sc->sc_dedata->dc_pcbb.pcbb2 = MOD_TPAD|MOD_HDX|MOD_DRDC|MOD_ENAL;
	DE_WLOW(CMD_GETCMD);
	dewait(sc, "wtmode");

	/* set up the receive and transmit ring entries */
	ifxp = &sc->sc_ifw[0];
	for (rp = &dc->dc_xrent[0]; rp < &dc->dc_xrent[NXMT]; rp++) {
		rp->r_segbl = LOWORD(ifxp->ifw_info);
		rp->r_segbh = HIWORD(ifxp->ifw_info);
		rp->r_flags = 0;
		ifxp++;
	}
	ifrw = &sc->sc_ifr[0];
	for (rp = &dc->dc_rrent[0]; rp < &dc->dc_rrent[NRCV]; rp++) {
		rp->r_slen = MCLBYTES - 2;
		rp->r_segbl = LOWORD(ifrw->ifrw_info);
		rp->r_segbh = HIWORD(ifrw->ifrw_info);
		rp->r_flags = RFLG_OWN;
		ifrw++;
	}

	/* start up the board (rah rah) */
	s = splnet();
	sc->sc_rindex = sc->sc_xindex = sc->sc_xfree = sc->sc_nxmit = 0;
	sc->sc_if.if_flags |= IFF_RUNNING;
	DE_WLOW(PCSR0_INTE);			/* avoid interlock */
	destart(&sc->sc_if);		/* queue output packets */
	DE_WLOW(CMD_START|PCSR0_INTE);
	splx(s);
	return 0;
}