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); }
/* * 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); }
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); }
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); }
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); }
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); }
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 }
/* * 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; }
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]); }