void dmac3_attach(device_t parent, device_t self, void *aux) { struct dmac3_softc *sc = device_private(self); struct apbus_attach_args *apa = aux; struct dmac3reg *reg; static paddr_t dmamap = DMAC3_PAGEMAP; static vaddr_t dmaaddr = 0; sc->sc_dev = self; reg = (void *)apa->apa_hwbase; sc->sc_reg = reg; sc->sc_ctlnum = apa->apa_ctlnum; sc->sc_dmamap = (uint32_t *)dmamap; sc->sc_dmaaddr = dmaaddr; dmamap += 0x1000; dmaaddr += 0x200000; sc->sc_conf = DMAC3_CONF_PCEN | DMAC3_CONF_DCEN | DMAC3_CONF_FASTACCESS; dmac3_reset(sc); aprint_normal(" slot%d addr 0x%lx", apa->apa_slotno, apa->apa_hwbase); aprint_normal(": ctlnum = %d, map = %p, va = %lx", apa->apa_ctlnum, sc->sc_dmamap, sc->sc_dmaaddr); aprint_normal("\n"); }
void dmac3_start(struct dmac3_softc *sc, vaddr_t addr, int len, int direction) { struct dmac3reg *reg = sc->sc_reg; paddr_t pa; vaddr_t start, end, v; volatile uint32_t *p; if (reg->csr & DMAC3_CSR_ENABLE) dmac3_reset(sc); start = mips_trunc_page(addr); end = mips_round_page(addr + len); p = sc->sc_dmamap; for (v = start; v < end; v += PAGE_SIZE) { pa = kvtophys(v); mips_dcache_wbinv_range(MIPS_PHYS_TO_KSEG0(pa), PAGE_SIZE); *p++ = 0; *p++ = (pa >> PGSHIFT) | 0xc0000000; } *p++ = 0; *p++ = 0x003fffff; addr &= PGOFSET; addr += sc->sc_dmaaddr; reg->len = len; reg->addr = addr; reg->intr = DMAC3_INTR_EOPIE | DMAC3_INTR_INTEN; reg->csr = DMAC3_CSR_ENABLE | direction | BURST_MODE | APAD_MODE; }
int dmac3_intr(void *v) { struct dmac3_softc *sc = v; struct dmac3reg *reg = sc->sc_reg; int intr, conf, rv = 1; intr = reg->intr; if ((intr & DMAC3_INTR_INT) == 0) return 0; /* clear interrupt */ conf = reg->conf; reg->conf = conf; reg->intr = intr; if (intr & DMAC3_INTR_PERR) { printf("%s: intr = 0x%x\n", device_xname(sc->sc_dev), intr); rv = -1; } if (conf & (DMAC3_CONF_IPER | DMAC3_CONF_MPER | DMAC3_CONF_DERR)) { printf("%s: conf = 0x%x\n", device_xname(sc->sc_dev), conf); if (conf & DMAC3_CONF_DERR) { printf("DMA address = 0x%x\n", reg->addr); printf("resetting DMA...\n"); dmac3_reset(sc); } } return rv; }
void spifi_attach(device_t parent, device_t self, void *aux) { struct spifi_softc *sc = device_private(self); struct apbus_attach_args *apa = aux; struct dmac3_softc *dma; int intr, i; sc->sc_dev = self; /* Initialize scbs. */ TAILQ_INIT(&sc->free_scb); TAILQ_INIT(&sc->ready_scb); for (i = 0; i < __arraycount(sc->sc_scb); i++) TAILQ_INSERT_TAIL(&sc->free_scb, &sc->sc_scb[i], chain); sc->sc_reg = (struct spifi_reg *)apa->apa_hwbase; sc->sc_id = 7; /* XXX */ /* Find my dmac3. */ dma = dmac3_link(apa->apa_ctlnum); if (dma == NULL) { aprint_error(": cannot find slave dmac\n"); return; } sc->sc_dma = dma; aprint_normal(" slot%d addr 0x%lx", apa->apa_slotno, apa->apa_hwbase); aprint_normal(": SCSI ID = %d, using %s\n", sc->sc_id, device_xname(dma->sc_dev)); dmac3_reset(sc->sc_dma); DMAC3_SLOWACCESS(sc); spifi_reset(sc); DMAC3_FASTACCESS(sc); sc->sc_adapter.adapt_dev = self; sc->sc_adapter.adapt_nchannels = 1; sc->sc_adapter.adapt_openings = 7; sc->sc_adapter.adapt_max_periph = 1; sc->sc_adapter.adapt_ioctl = NULL; sc->sc_adapter.adapt_minphys = minphys; sc->sc_adapter.adapt_request = spifi_scsipi_request; memset(&sc->sc_channel, 0, sizeof(sc->sc_channel)); sc->sc_channel.chan_adapter = &sc->sc_adapter; sc->sc_channel.chan_bustype = &scsi_bustype; sc->sc_channel.chan_channel = 0; sc->sc_channel.chan_ntargets = 8; sc->sc_channel.chan_nluns = 8; sc->sc_channel.chan_id = sc->sc_id; if (apa->apa_slotno == 0) intr = NEWS5000_INT0_DMAC; else intr = SLOTTOMASK(apa->apa_slotno); apbus_intr_establish(0, intr, 0, spifi_intr, sc, apa->apa_name, apa->apa_ctlnum); config_found(self, &sc->sc_channel, scsiprint); }