예제 #1
0
void
bmac_init_dma(struct bmac_softc *sc)
{
	dbdma_command_t *cmd = sc->sc_rxcmd;
	int i;

	dbdma_reset(sc->sc_txdma);
	dbdma_reset(sc->sc_rxdma);

	bzero(sc->sc_txcmd, BMAC_TXBUFS * sizeof(dbdma_command_t));
	bzero(sc->sc_rxcmd, (BMAC_RXBUFS + 1) * sizeof(dbdma_command_t));

	for (i = 0; i < BMAC_RXBUFS; i++) {
		DBDMA_BUILD(cmd, DBDMA_CMD_IN_LAST, 0, BMAC_BUFLEN,
			sc->sc_rxbuf_pa + BMAC_BUFLEN * i,
			DBDMA_INT_ALWAYS, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
		cmd++;
	}
	DBDMA_BUILD(cmd, DBDMA_CMD_NOP, 0, 0, 0,
		DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_ALWAYS);
	dbdma_st32(&cmd->d_cmddep, sc->sc_rxdbdma->d_paddr);

	sc->sc_rxlast = 0;

	dbdma_start(sc->sc_rxdma, sc->sc_rxdbdma);
}
예제 #2
0
/*
 * Reset and enable bmac by heathrow FCR.
 */
void
bmac_reset_chip(struct bmac_softc *sc)
{
	u_int v;

	dbdma_reset(sc->sc_txdma);
	dbdma_reset(sc->sc_rxdma);

	v = in32rb(heathrow_FCR);

	v |= EnetEnable;
	out32rb(heathrow_FCR, v);
	delay(50000);

	/* assert reset */
	v |= ResetEnetCell;
	out32rb(heathrow_FCR, v);
	delay(50000);

	/* deassert reset */
	v &= ~ResetEnetCell;
	out32rb(heathrow_FCR, v);
	delay(50000);

	/* enable */
	v |= EnetEnable;
	out32rb(heathrow_FCR, v);
	delay(50000);

	/* make certain they stay set? */
	out32rb(heathrow_FCR, v);
	v = in32rb(heathrow_FCR);
}
예제 #3
0
파일: if_mc.c 프로젝트: ryo/netbsd-src
hide void
mc_reset_txdma(struct mc_softc *sc)
{
	dbdma_command_t *cmd = sc->sc_txdmacmd;
	dbdma_regmap_t *dmareg = sc->sc_txdma;
	u_int8_t maccc;

	/* disable transmitter */
	maccc = NIC_GET(sc, MACE_MACCC);
	NIC_PUT(sc, MACE_MACCC, maccc & ~ENXMT);

	dbdma_reset(dmareg);

	DBDMA_BUILD(cmd, DBDMA_CMD_OUT_LAST, 0, 0, sc->sc_txbuf_phys,
		DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
	cmd++;
	DBDMA_BUILD(cmd, DBDMA_CMD_STOP, 0, 0, 0,
		DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);

	out32rb(&dmareg->d_cmdptrhi, 0);
	out32rb(&dmareg->d_cmdptrlo, kvtop((void *)sc->sc_txdmacmd));

	/* restore old value */
	NIC_PUT(sc, MACE_MACCC, maccc);
}
예제 #4
0
파일: if_mc.c 프로젝트: ryo/netbsd-src
hide void
mc_reset_rxdma(struct mc_softc *sc)
{
	dbdma_command_t *cmd = sc->sc_rxdmacmd;
	dbdma_regmap_t *dmareg = sc->sc_rxdma;
	int i;
	u_int8_t maccc;

	/* Disable receiver, reset the DMA channels */
	maccc = NIC_GET(sc, MACE_MACCC);
	NIC_PUT(sc, MACE_MACCC, maccc & ~ENRCV);

	dbdma_reset(dmareg);

	for (i = 0; i < MC_RXDMABUFS; i++) {
		DBDMA_BUILD(cmd, DBDMA_CMD_IN_LAST, 0, ETHERMTU + 22,
			sc->sc_rxbuf_phys + MC_BUFSIZE * i, DBDMA_INT_ALWAYS,
			DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
		cmd++;
	}

	DBDMA_BUILD(cmd, DBDMA_CMD_NOP, 0, 0, 0,
		DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_ALWAYS);
	out32rb(&cmd->d_cmddep, kvtop((void *)sc->sc_rxdmacmd));
	cmd++;

	dbdma_start(dmareg, sc->sc_rxdmacmd);

	sc->sc_tail = 0;

	/* Reenable receiver, reenable DMA */
	NIC_PUT(sc, MACE_MACCC, maccc);
}
예제 #5
0
void
mc_reset_rxdma(struct mc_softc *sc)
{
	dbdma_command_t *cmd = sc->sc_rxdmacmd;
	int i;
	u_int8_t maccc;

	/* Disable receiver, reset the DMA channels */
	maccc = NIC_GET(sc, MACE_MACCC);
	NIC_PUT(sc, MACE_MACCC, maccc & ~ENRCV);

	dbdma_reset(sc->sc_rxdma);

	bzero(sc->sc_rxdmacmd, 8 * sizeof(dbdma_command_t));
	for (i = 0; i < MC_RXDMABUFS; i++) {
		DBDMA_BUILD(cmd, DBDMA_CMD_IN_LAST, 0, MACE_BUFLEN,
		    sc->sc_rxbuf_pa + MACE_BUFLEN * i, DBDMA_INT_ALWAYS,
		    DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
		cmd++;
	}

	DBDMA_BUILD(cmd, DBDMA_CMD_NOP, 0, 0, 0,
	    DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_ALWAYS);
	dbdma_st32(&cmd->d_cmddep, sc->sc_rxdbdma->d_paddr);
	cmd++;

	sc->sc_tail = 0;

	dbdma_start(sc->sc_rxdma, sc->sc_rxdbdma);
	/* Reenable receiver, reenable DMA */
	NIC_PUT(sc, MACE_MACCC, maccc);
}
예제 #6
0
void
xlights_timeout(void *v)
{
	struct xlights_softc *sc = (struct xlights_softc *)v;

	dbdma_reset(sc->sc_dma);
	timeout_del(&sc->sc_tmo);
	sc->sc_dmasts = 0;
	wakeup(sc->sc_buf);
}
예제 #7
0
파일: if_mc.c 프로젝트: ryo/netbsd-src
hide void
mc_attach(device_t parent, device_t self, void *aux)
{
	struct confargs *ca = aux;
	struct mc_softc *sc = device_private(self);
	u_int8_t myaddr[ETHER_ADDR_LEN];
	u_int *reg;

	sc->sc_dev = self;
	sc->sc_node = ca->ca_node;
	sc->sc_regt = ca->ca_tag;

	reg  = ca->ca_reg;
	reg[0] += ca->ca_baseaddr;
	reg[2] += ca->ca_baseaddr;
	reg[4] += ca->ca_baseaddr;

	sc->sc_txdma = mapiodev(reg[2], reg[3], false);
	sc->sc_rxdma = mapiodev(reg[4], reg[5], false);
	bus_space_map(sc->sc_regt, reg[0], reg[1], 0, &sc->sc_regh);

	sc->sc_tail = 0;
	sc->sc_txdmacmd = dbdma_alloc(sizeof(dbdma_command_t) * 2, NULL);
	sc->sc_rxdmacmd = (void *)dbdma_alloc(sizeof(dbdma_command_t) * 8,
	    NULL);
	memset(sc->sc_txdmacmd, 0, sizeof(dbdma_command_t) * 2);
	memset(sc->sc_rxdmacmd, 0, sizeof(dbdma_command_t) * 8);

	printf(": irq %d,%d,%d",
		ca->ca_intr[0], ca->ca_intr[1], ca->ca_intr[2]);

	if (OF_getprop(sc->sc_node, "local-mac-address", myaddr, 6) != 6) {
		printf(": failed to get MAC address.\n");
		return;
	}

	/* allocate memory for transmit buffer and mark it non-cacheable */
	sc->sc_txbuf = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK);
	sc->sc_txbuf_phys = kvtop(sc->sc_txbuf);
	memset(sc->sc_txbuf, 0, PAGE_SIZE);

	/*
	 * allocate memory for receive buffer and mark it non-cacheable
	 * XXX This should use the bus_dma interface, since the buffer
	 * needs to be physically contiguous. However, it seems that
	 * at least on my system, malloc() does allocate contiguous
	 * memory. If it's not, suggest reducing the number of buffers
	 * to 2, which will fit in one 4K page.
	 */
	sc->sc_rxbuf = malloc(MC_NPAGES * PAGE_SIZE, M_DEVBUF, M_WAITOK);
	sc->sc_rxbuf_phys = kvtop(sc->sc_rxbuf);
	memset(sc->sc_rxbuf, 0, MC_NPAGES * PAGE_SIZE);

	if ((int)sc->sc_txbuf & PGOFSET)
		printf("txbuf is not page-aligned\n");
	if ((int)sc->sc_rxbuf & PGOFSET)
		printf("rxbuf is not page-aligned\n");

	sc->sc_bus_init = mc_init;
	sc->sc_putpacket = mc_putpacket;


	/* disable receive DMA */
	dbdma_reset(sc->sc_rxdma);

	/* disable transmit DMA */
	dbdma_reset(sc->sc_txdma);

	/* install interrupt handlers */
	/*intr_establish(ca->ca_intr[1], IST_EDGE, IPL_NET, mc_dmaintr, sc);*/
	intr_establish(ca->ca_intr[2], IST_EDGE, IPL_NET, mc_dmaintr, sc);
	intr_establish(ca->ca_intr[0], IST_EDGE, IPL_NET, mcintr, sc);

	sc->sc_biucc = XMTSP_64;
	sc->sc_fifocc = XMTFW_16 | RCVFW_64 | XMTFWU | RCVFWU |
	    XMTBRST | RCVBRST;
	/*sc->sc_plscc = PORTSEL_10BT;*/
	sc->sc_plscc = PORTSEL_GPSI | ENPLSIO;

	/* mcsetup returns 1 if something fails */
	if (mcsetup(sc, myaddr)) {
		printf("mcsetup returns non zero\n");
		return;
	}
#ifdef NOTYET
	sc->sc_mediachange = mc_mediachange;
	sc->sc_mediastatus = mc_mediastatus;
	sc->sc_supmedia = mc_supmedia;
	sc->sc_nsupmedia = N_SUPMEDIA;
	sc->sc_defaultmedia = IFM_ETHER | IFM_10_T;
#endif
}
예제 #8
0
/*
 * Attach a found zs.
 *
 * Match slave number to zs unit number, so that misconfiguration will
 * not set up the keyboard as ttya, etc.
 */
void
zsc_attach(struct device *parent, struct device *self, void *aux)
{
	struct zsc_softc *zsc = (void *)self;
	struct confargs *ca = aux;
	struct zsc_attach_args zsc_args;
	volatile struct zschan *zc;
	struct xzs_chanstate *xcs;
	struct zs_chanstate *cs;
	struct zsdevice *zsd;
	int zsc_unit, channel;
	int s, theflags;
	int node, intr[3][3];
	u_int regs[16];

	zsc_unit = zsc->zsc_dev.dv_unit;

	zsd = mapiodev(ca->ca_baseaddr + ca->ca_reg[0], ca->ca_reg[1]);
	node = OF_child(ca->ca_node);	/* ch-a */

	for (channel = 0; channel < 2; channel++) {
		if (OF_getprop(node, "AAPL,interrupts",
			       intr[channel], sizeof(intr[0])) == -1 &&
		    OF_getprop(node, "interrupts",
			       intr[channel], sizeof(intr[0])) == -1) {
			printf(": cannot find interrupt property\n");
			return;
		}

		if (OF_getprop(node, "reg", regs, sizeof(regs)) < 24) {
			printf(": cannot find reg property\n");
			return;
		}
		regs[2] += ca->ca_baseaddr;
		regs[4] += ca->ca_baseaddr;
#ifdef ZS_TXDMA
		zsc->zsc_txdmareg[channel] = mapiodev(regs[2], regs[3]);
		zsc->zsc_txdmacmd[channel] =
			dbdma_alloc(sizeof(dbdma_command_t) * 3);
		memset(zsc->zsc_txdmacmd[channel], 0,
			sizeof(dbdma_command_t) * 3);
		dbdma_reset(zsc->zsc_txdmareg[channel]);
#endif
		node = OF_peer(node);	/* ch-b */
	}

	printf(": irq %d,%d\n", intr[0][0], intr[1][0]);

	/*
	 * Initialize software state for each channel.
	 */
	for (channel = 0; channel < 2; channel++) {
		zsc_args.channel = channel;
		zsc_args.hwflags = zs_hwflags[zsc_unit][channel];
		xcs = &zsc->xzsc_xcs_store[channel];
		cs  = &xcs->xzs_cs;
		zsc->zsc_cs[channel] = cs;

		cs->cs_channel = channel;
		cs->cs_private = NULL;
		cs->cs_ops = &zsops_null;

		zc = (channel == 0) ? &zsd->zs_chan_a : &zsd->zs_chan_b;

		cs->cs_reg_csr  = &zc->zc_csr;
		cs->cs_reg_data = &zc->zc_data;

		memcpy(cs->cs_creg, zs_init_reg, 16);
		memcpy(cs->cs_preg, zs_init_reg, 16);

		/* Current BAUD rate generator clock. */
		/* RTxC is 230400*16, so use 230400 */
		cs->cs_brg_clk = PCLK / 16;
		if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE)
			cs->cs_defspeed = zs_get_speed(cs);
		else
			cs->cs_defspeed =
			    zs_defspeed[zsc_unit][channel];
		cs->cs_defcflag = zs_def_cflag;

		/* Make these correspond to cs_defcflag (-crtscts) */
		cs->cs_rr0_dcd = ZSRR0_DCD;
		cs->cs_rr0_cts = 0;
		cs->cs_wr5_dtr = ZSWR5_DTR;
		cs->cs_wr5_rts = 0;

#ifdef __notyet__
		cs->cs_slave_type = ZS_SLAVE_NONE;
#endif

		/* Define BAUD rate stuff. */
		xcs->cs_clocks[0].clk = PCLK;
		xcs->cs_clocks[0].flags = ZSC_RTXBRG | ZSC_RTXDIV;
		xcs->cs_clocks[1].flags =
			ZSC_RTXBRG | ZSC_RTXDIV | ZSC_VARIABLE | ZSC_EXTERN;
		xcs->cs_clocks[2].flags = ZSC_TRXDIV | ZSC_VARIABLE;
		xcs->cs_clock_count = 3;
		if (channel == 0) {
			theflags = 0; /*mac68k_machine.modem_flags;*/
			/*xcs->cs_clocks[1].clk = mac68k_machine.modem_dcd_clk;*/
			/*xcs->cs_clocks[2].clk = mac68k_machine.modem_cts_clk;*/
			xcs->cs_clocks[1].clk = 0;
			xcs->cs_clocks[2].clk = 0;
		} else {
			theflags = 0; /*mac68k_machine.print_flags;*/
			xcs->cs_clocks[1].flags = ZSC_VARIABLE;
			/*
			 * Yes, we aren't defining ANY clock source enables for the
			 * printer's DCD clock in. The hardware won't let us
			 * use it. But a clock will freak out the chip, so we
			 * let you set it, telling us to bar interrupts on the line.
			 */
			/*xcs->cs_clocks[1].clk = mac68k_machine.print_dcd_clk;*/
			/*xcs->cs_clocks[2].clk = mac68k_machine.print_cts_clk;*/
			xcs->cs_clocks[1].clk = 0;
			xcs->cs_clocks[2].clk = 0;
		}
		if (xcs->cs_clocks[1].clk)
			zsc_args.hwflags |= ZS_HWFLAG_NO_DCD;
		if (xcs->cs_clocks[2].clk)
			zsc_args.hwflags |= ZS_HWFLAG_NO_CTS;

		/* Set defaults in our "extended" chanstate. */
		xcs->cs_csource = 0;
		xcs->cs_psource = 0;
		xcs->cs_cclk_flag = 0;  /* Nothing fancy by default */
		xcs->cs_pclk_flag = 0;

		if (theflags & ZSMAC_RAW) {
			zsc_args.hwflags |= ZS_HWFLAG_RAW;
			printf(" (raw defaults)");
		}

		/*
		 * XXX - This might be better done with a "stub" driver
		 * (to replace zstty) that ignores LocalTalk for now.
		 */
		if (theflags & ZSMAC_LOCALTALK) {
			printf(" shielding from LocalTalk");
			cs->cs_defspeed = 1;
			cs->cs_creg[ZSRR_BAUDLO] = cs->cs_preg[ZSRR_BAUDLO] = 0xff;
			cs->cs_creg[ZSRR_BAUDHI] = cs->cs_preg[ZSRR_BAUDHI] = 0xff;
			zs_write_reg(cs, ZSRR_BAUDLO, 0xff);
			zs_write_reg(cs, ZSRR_BAUDHI, 0xff);
			/*
			 * If we might have LocalTalk, then make sure we have the
			 * Baud rate low-enough to not do any damage.
			 */
		}

		/*
		 * We used to disable chip interrupts here, but we now
		 * do that in zscnprobe, just in case MacOS left the chip on.
		 */
		
		xcs->cs_chip = 0;
		
		/* Stash away a copy of the final H/W flags. */
		xcs->cs_hwflags = zsc_args.hwflags;
		
		/*
		 * Look for a child driver for this channel.
		 * The child attach will setup the hardware.
		 */
		if (!config_found(self, (void *)&zsc_args, zsc_print)) {
			/* No sub-driver.  Just reset it. */
			u_char reset = (channel == 0) ?
				ZSWR9_A_RESET : ZSWR9_B_RESET;
			s = splzs();
			zs_write_reg(cs, 9, reset);
			splx(s);
		}
	}

	/* XXX - Now safe to install interrupt handlers. */
	mac_intr_establish(parent, intr[0][0], IST_LEVEL, IPL_TTY,
	    zshard, NULL, "zs0");
	mac_intr_establish(parent, intr[1][0], IST_LEVEL, IPL_TTY,
	    zshard, NULL, "zs1");
#ifdef ZS_TXDMA
	mac_intr_establish(parent, intr[0][1], IST_LEVEL, IPL_TTY,
	    zs_txdma_int, (void *)0, "zsdma0");
	mac_intr_establish(parent, intr[1][1], IST_LEVEL, IPL_TTY,
	    zs_txdma_int, (void *)1, "zsdma1");
#endif
	zsc->zsc_softintr = softintr_establish(IPL_SOFTTTY, zssoft, zsc);
	if (zsc->zsc_softintr == NULL)
		panic("zsattach: could not establish soft interrupt");

	/*
	 * Set the master interrupt enable and interrupt vector.
	 * (common to both channels, do it on A)
	 */
	cs = zsc->zsc_cs[0];
	s = splzs();
	/* interrupt vector */
	zs_write_reg(cs, 2, zs_init_reg[2]);
	/* master interrupt control (enable) */
	zs_write_reg(cs, 9, zs_init_reg[9]);
	splx(s);

	/* connect power management for port 0 */
	cs->enable = zs_enable;
	cs->disable = zs_disable;
}
예제 #9
0
void
mc_attach(struct device *parent, struct device *self, void *aux)
{
	struct confargs *ca = aux;
	struct mc_softc *sc = (struct mc_softc *)self;
	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
	u_int8_t lladdr[ETHER_ADDR_LEN];
	int nseg, error;

	if (OF_getprop(ca->ca_node, "local-mac-address", lladdr,
	    ETHER_ADDR_LEN) != ETHER_ADDR_LEN) {
		printf(": failed to get MAC address.\n");
		return;
	}

	ca->ca_reg[0] += ca->ca_baseaddr;
	ca->ca_reg[2] += ca->ca_baseaddr;
	ca->ca_reg[4] += ca->ca_baseaddr;

	if ((sc->sc_reg = mapiodev(ca->ca_reg[0], ca->ca_reg[1])) == NULL) {
		printf(": cannot map registers\n");
		return;
	}

	sc->sc_dmat = ca->ca_dmat;
	sc->sc_tail = 0;

	if ((sc->sc_txdma = mapiodev(ca->ca_reg[2], ca->ca_reg[3])) == NULL) {
		printf(": cannot map TX DMA registers\n");
		goto notxdma;
	}
	if ((sc->sc_rxdma = mapiodev(ca->ca_reg[4], ca->ca_reg[5])) == NULL) {
		printf(": cannot map RX DMA registers\n");
		goto norxdma;
	}
	if ((sc->sc_txdbdma = dbdma_alloc(sc->sc_dmat, 2)) == NULL) {
		printf(": cannot alloc TX DMA descriptors\n");
		goto notxdbdma;
	}
	sc->sc_txdmacmd = sc->sc_txdbdma->d_addr;

	if ((sc->sc_rxdbdma = dbdma_alloc(sc->sc_dmat, 8 + 1)) == NULL) {
		printf(": cannot alloc RX DMA descriptors\n");
		goto norxdbdma;
	}
	sc->sc_rxdmacmd = sc->sc_rxdbdma->d_addr;

	if ((error = bus_dmamem_alloc(sc->sc_dmat, MACE_BUFSZ, PAGE_SIZE, 0,
	    sc->sc_bufseg, 1, &nseg, BUS_DMA_NOWAIT))) {
		printf(": cannot allocate DMA mem (%d)\n", error);
		goto nodmamem;
	}

	if ((error = bus_dmamem_map(sc->sc_dmat, sc->sc_bufseg, nseg,
	    MACE_BUFSZ, &sc->sc_txbuf, BUS_DMA_NOWAIT))) {
		printf(": cannot map DMA mem (%d)\n", error);
		goto nodmamap;
	}

	if ((error = bus_dmamap_create(sc->sc_dmat, MACE_BUFSZ, 1, MACE_BUFSZ,
	    0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_bufmap))) {
		printf(": cannot create DMA map (%d)\n", error);
		goto nodmacreate;
	}

	if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_bufmap, sc->sc_txbuf,
	    MACE_BUFSZ, NULL, BUS_DMA_NOWAIT))) {
		printf(": cannot load DMA map (%d)\n", error);
		goto nodmaload;
	}

	sc->sc_txbuf_pa = sc->sc_bufmap->dm_segs->ds_addr;
	sc->sc_rxbuf = sc->sc_txbuf + MACE_BUFLEN * MACE_TXBUFS;
	sc->sc_rxbuf_pa = sc->sc_txbuf_pa + MACE_BUFLEN * MACE_TXBUFS;

	printf(": irq %d,%d,%d", ca->ca_intr[0], ca->ca_intr[1],
	    ca->ca_intr[2]);

	/* disable receive DMA */
	dbdma_reset(sc->sc_rxdma);

	/* disable transmit DMA */
	dbdma_reset(sc->sc_txdma);

	/* install interrupt handlers */
	mac_intr_establish(parent, ca->ca_intr[2], IST_LEVEL, IPL_NET,
	    mc_dmaintr, sc, sc->sc_dev.dv_xname);
	mac_intr_establish(parent, ca->ca_intr[0],  IST_LEVEL, IPL_NET,
	    mc_intr, sc, sc->sc_dev.dv_xname);

	sc->sc_biucc = XMTSP_64;
	sc->sc_fifocc = XMTFW_16 | RCVFW_64 | XMTFWU | RCVFWU |
	    XMTBRST | RCVBRST;
	sc->sc_plscc = PORTSEL_GPSI | ENPLSIO;

	/* reset the chip and disable all interrupts */
	NIC_PUT(sc, MACE_BIUCC, SWRST);
	DELAY(100);

	NIC_PUT(sc, MACE_IMR, ~0);

	bcopy(lladdr, sc->sc_enaddr, ETHER_ADDR_LEN);
	bcopy(sc->sc_enaddr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
	printf(": address %s\n", ether_sprintf(lladdr));

	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
	ifp->if_softc = sc;
	ifp->if_ioctl = mc_ioctl;
	ifp->if_start = mc_start;
	ifp->if_flags =
		IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
	ifp->if_watchdog = mc_watchdog;
	ifp->if_timer = 0;
	IFQ_SET_READY(&ifp->if_snd);

	if_attach(ifp);
	ether_ifattach(ifp);

	return;
nodmaload:
	bus_dmamap_destroy(sc->sc_dmat, sc->sc_bufmap);
nodmacreate:
	bus_dmamem_unmap(sc->sc_dmat, sc->sc_txbuf, MACE_BUFSZ);
nodmamap:
	bus_dmamem_free(sc->sc_dmat, sc->sc_bufseg, 1);
nodmamem:
	dbdma_free(sc->sc_rxdbdma);
norxdbdma:
	dbdma_free(sc->sc_txdbdma);
notxdbdma:
	unmapiodev((void *)sc->sc_rxdma, ca->ca_reg[5]);
norxdma:
	unmapiodev((void *)sc->sc_txdma, ca->ca_reg[3]);
notxdma:
	unmapiodev(sc->sc_reg, ca->ca_reg[1]);
}