int ad1848_trigger_input(void *addr, void *start, void *end, int blksize, void (*intr)(void *), void *arg, struct audio_params *param) { struct ad1848_softc *sc = addr; u_char reg; if (sc->sc_recdrq == -1) { DPRINTF(("ad1848_trigger_input: invalid recording drq\n")); return ENXIO; } isa_dmastart(sc->sc_isa, sc->sc_recdrq, start, (char *)end - (char *)start, NULL, DMAMODE_READ | DMAMODE_LOOP, BUS_DMA_NOWAIT); sc->sc_recrun = 1; sc->sc_rintr = intr; sc->sc_rarg = arg; blksize = (blksize * NBBY) / (param->precision * param->channels) - 1; if (sc->mode == 2) { ad_write(sc, CS_LOWER_REC_CNT, (blksize & 0xff)); ad_write(sc, CS_UPPER_REC_CNT, ((blksize >> 8) & 0xff)); } else {
int satlinkopen(dev_t dev, int flags, int fmt, struct lwp *l) { struct satlink_softc *sc; int error; sc = device_lookup_private(&satlink_cd, minor(dev)); if (sc == NULL) return (ENXIO); if (sc->sc_flags & SATF_ISOPEN) return (EBUSY); bus_space_write_1(sc->sc_iot, sc->sc_ioh, SATLINK_COMMAND, SATLINK_CMD_RESET); /* Reset the ring buffer, and start the DMA loop. */ sc->sc_uptr = 0; sc->sc_sptr = 0; sc->sc_lastresid = sc->sc_bufsize; memset(sc->sc_buf, 0, sc->sc_bufsize); error = isa_dmastart(sc->sc_ic, sc->sc_drq, sc->sc_buf, sc->sc_bufsize, NULL, DMAMODE_READ|DMAMODE_LOOP, BUS_DMA_WAITOK); if (error) return (error); sc->sc_flags |= SATF_ISOPEN; callout_reset(&sc->sc_ch, SATLINK_TIMEOUT, satlinktimeout, sc); return (0); }
/* Start DMA operation over ISA bus */ int atppc_isadma_start(isa_chipset_tag_t ic, int drq, void *buf, u_int nbytes, u_int8_t mode) { return (isa_dmastart(ic, drq, buf, nbytes, NULL, ((mode == ATPPC_DMA_MODE_WRITE) ? DMAMODE_WRITE : DMAMODE_READ) | DMAMODE_DEMAND, ((mode == ATPPC_DMA_MODE_WRITE) ? BUS_DMA_WRITE : BUS_DMA_READ) | BUS_DMA_NOWAIT)); }
static void wdc_isapnp_dma_start(void *scv, void *buf, size_t size, int read) { struct wdc_isapnp_softc *sc = scv; isa_dmastart(sc->sc_ic, sc->sc_drq, buf, size, NULL, (read ? DMAMODE_READ : DMAMODE_WRITE) | DMAMODE_DEMAND, BUS_DMA_NOWAIT); }
static int wdc_isa_dma_init(void *v, int channel, int drive, void *databuf, size_t datalen, int read) { struct wdc_isa_softc *sc = v; isa_dmastart(sc->sc_isa, sc->sc_drq, databuf, datalen, NULL, (read ? DMAMODE_READ : DMAMODE_WRITE), BUS_DMA_NOWAIT); return 0; }
int ad1848_isa_trigger_input( void *addr, void *start, void *end, int blksize, void (*intr)(void *), void *arg, const audio_params_t *param) { struct ad1848_isa_softc *isc; struct ad1848_softc *sc; uint8_t reg; isc = addr; sc = &isc->sc_ad1848; isa_dmastart(isc->sc_ic, isc->sc_recdrq, start, (char *)end - (char *)start, NULL, DMAMODE_READ | DMAMODE_LOOPDEMAND, BUS_DMA_NOWAIT); isc->sc_recrun = 1; if (sc->mode == 2 && isc->sc_playdrq != isc->sc_recdrq) { isc->sc_rintr = intr; isc->sc_rarg = arg; } else { isc->sc_pintr = intr; isc->sc_parg = arg; } /* * Calculate number of transfers. * Note that ADPCM is always transferred 4 bytes at at a time. */ blksize = (param->encoding == AUDIO_ENCODING_ADPCM) ? blksize / 4 - 1 : (blksize * 8) / (param->precision * param->channels) - 1; if (sc->mode >= 2) { ad_write(sc, CS_LOWER_REC_CNT, blksize & 0xff); ad_write(sc, CS_UPPER_REC_CNT, blksize >> 8); } else {
void sndbuf_dma(struct snd_dbuf *b, int go) { KASSERT(b, ("sndbuf_dma called with b == NULL")); KASSERT(sndbuf_getflags(b) & SNDBUF_F_DMA, ("sndbuf_dma called on non-ISA buffer")); switch (go) { case PCMTRIG_START: /* isa_dmainit(b->chan, size); */ isa_dmastart(b->dir | ISADMA_RAW, b->buf, b->bufsize, b->dmachan); break; case PCMTRIG_STOP: case PCMTRIG_ABORT: isa_dmastop(b->dmachan); isa_dmadone(b->dir | ISADMA_RAW, b->buf, b->bufsize, b->dmachan); break; } DEB(printf("buf 0x%p ISA DMA %s, channel %d\n", b, (go == PCMTRIG_START)? "started" : "stopped", b->dmachan)); }
/* * Call this function if you want to send data in any advanced mode * of your parallel port: FIFO, DMA * * If what you want is not possible (no ECP, no DMA...), * EINVAL is returned */ int ppc_write(device_t dev, char *buf, int len, int how) { struct ppc_data *ppc = DEVTOSOFTC(dev); char ecr, ecr_sav, ctr, ctr_sav; int s, error = 0; int spin; #ifdef PPC_DEBUG printf("w"); #endif ecr_sav = r_ecr(ppc); ctr_sav = r_ctr(ppc); /* * Send buffer with DMA, FIFO and interrupts */ if ((ppc->ppc_avm & PPB_ECP) && (ppc->ppc_registered)) { if (ppc->ppc_dmachan > 0) { /* byte mode, no intr, no DMA, dir=0, flush fifo */ ecr = PPC_ECR_STD | PPC_DISABLE_INTR; w_ecr(ppc, ecr); /* disable nAck interrupts */ ctr = r_ctr(ppc); ctr &= ~IRQENABLE; w_ctr(ppc, ctr); ppc->ppc_dmaflags = 0; ppc->ppc_dmaddr = (caddr_t)buf; ppc->ppc_dmacnt = (u_int)len; switch (ppc->ppc_mode) { case PPB_COMPATIBLE: /* compatible mode with FIFO, no intr, DMA, dir=0 */ ecr = PPC_ECR_FIFO | PPC_DISABLE_INTR | PPC_ENABLE_DMA; break; case PPB_ECP: ecr = PPC_ECR_ECP | PPC_DISABLE_INTR | PPC_ENABLE_DMA; break; default: error = EINVAL; goto error; } w_ecr(ppc, ecr); ecr = r_ecr(ppc); /* enter splhigh() not to be preempted * by the dma interrupt, we may miss * the wakeup otherwise */ s = splhigh(); ppc->ppc_dmastat = PPC_DMA_INIT; /* enable interrupts */ ecr &= ~PPC_SERVICE_INTR; ppc->ppc_irqstat = PPC_IRQ_DMA; w_ecr(ppc, ecr); isa_dmastart( ppc->ppc_dmaflags, ppc->ppc_dmaddr, ppc->ppc_dmacnt, ppc->ppc_dmachan); #ifdef PPC_DEBUG printf("s%d", ppc->ppc_dmacnt); #endif ppc->ppc_dmastat = PPC_DMA_STARTED; /* Wait for the DMA completed interrupt. We hope we won't * miss it, otherwise a signal will be necessary to unlock the * process. */ do { /* release CPU */ error = tsleep(ppc, PPBPRI | PCATCH, "ppcdma", 0); } while (error == EWOULDBLOCK); splx(s); if (error) { #ifdef PPC_DEBUG printf("i"); #endif /* stop DMA */ isa_dmadone( ppc->ppc_dmaflags, ppc->ppc_dmaddr, ppc->ppc_dmacnt, ppc->ppc_dmachan); /* no dma, no interrupt, flush the fifo */ w_ecr(ppc, PPC_ECR_RESET); ppc->ppc_dmastat = PPC_DMA_INTERRUPTED; goto error; } /* wait for an empty fifo */ while (!(r_ecr(ppc) & PPC_FIFO_EMPTY)) { for (spin=100; spin; spin--) if (r_ecr(ppc) & PPC_FIFO_EMPTY) goto fifo_empty; #ifdef PPC_DEBUG printf("Z"); #endif error = tsleep(ppc, PPBPRI | PCATCH, "ppcfifo", hz/100); if (error != EWOULDBLOCK) { #ifdef PPC_DEBUG printf("I"); #endif /* no dma, no interrupt, flush the fifo */ w_ecr(ppc, PPC_ECR_RESET); ppc->ppc_dmastat = PPC_DMA_INTERRUPTED; error = EINTR; goto error; } } fifo_empty: /* no dma, no interrupt, flush the fifo */ w_ecr(ppc, PPC_ECR_RESET); } else error = EINVAL; /* XXX we should FIFO and * interrupts */ } else error = EINVAL; error: /* PDRQ must be kept unasserted until nPDACK is * deasserted for a minimum of 350ns (SMC datasheet) * * Consequence may be a FIFO that never empty */ DELAY(1); w_ecr(ppc, ecr_sav); w_ctr(ppc, ctr_sav); return (error); }
static int buffer_read(struct gsc_unit *scu) { int stb; int res = SUCCESS; int chan_bit; char *p; int sps; int delay; lprintf("gsc.buffer_read: begin\n"); if (scu->ctrl_byte == INVALID) { lprintf("gsc.buffer_read: invalid ctrl_byte\n"); return EIO; } sps=splbio(); outb( scu->ctrl, scu->ctrl_byte | GSC_POWER_ON ); outb( scu->clrp, 0 ); stb = inb( scu->stat ); isa_dmastart(B_READ, scu->sbuf.base, scu->sbuf.size, scu->channel); chan_bit = 0x01 << scu->channel; for(delay=0; !(inb(DMA1_READY) & 0x01 << scu->channel); delay += LONG) { if(delay >= scu->btime) { splx(sps); lprintf("gsc.buffer_read: timeout\n"); res = EWOULDBLOCK; break; } res = tsleep((caddr_t)scu, GSCPRI | PCATCH, "gscread", LONG); if ( ( res == 0 ) || ( res == EWOULDBLOCK ) ) res = SUCCESS; else break; } splx(sps); isa_dmadone(B_READ, scu->sbuf.base, scu->sbuf.size, scu->channel); outb( scu->clrp, 0 ); if(res != SUCCESS) { lprintf("gsc.buffer_read: aborted with %d\n", res); return res; } lprintf("gsc.buffer_read: invert buffer\n"); for(p = scu->sbuf.base + scu->sbuf.size - 1; p >= scu->sbuf.base; p--) *p = ~*p; scu->sbuf.poi = 0; lprintf("gsc.buffer_read: ok\n"); return SUCCESS; }
static int fdcintr1(struct fdc_softc *fdc) { #define st0 fdc->sc_status[0] #define cyl fdc->sc_status[1] struct fd_softc *fd; struct buf *bp; bus_space_tag_t iot = fdc->sc_iot; bus_space_handle_t ioh = fdc->sc_ioh; int read, head, sec, i, nblks; struct fd_type *type; struct ne7_fd_formb *finfo = NULL; KASSERT(mutex_owned(&fdc->sc_mtx)); if (fdc->sc_state == PROBING) { #ifdef DEBUG printf("fdcintr: got probe interrupt\n"); #endif fdc->sc_probe++; goto out; } loop: /* Is there a drive for the controller to do a transfer with? */ fd = TAILQ_FIRST(&fdc->sc_drives); if (fd == NULL) { fdc->sc_state = DEVIDLE; goto out; } /* Is there a transfer to this drive? If not, deactivate drive. */ bp = BUFQ_PEEK(fd->sc_q); if (bp == NULL) { fd->sc_ops = 0; TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain); fd->sc_active = 0; goto loop; } if (bp->b_flags & B_FORMAT) finfo = (struct ne7_fd_formb *)bp->b_data; switch (fdc->sc_state) { case DEVIDLE: fdc->sc_errors = 0; fd->sc_skip = 0; fd->sc_bcount = bp->b_bcount; fd->sc_blkno = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE); callout_stop(&fd->sc_motoroff_ch); if ((fd->sc_flags & FD_MOTOR_WAIT) != 0) { fdc->sc_state = MOTORWAIT; return 1; } if ((fd->sc_flags & FD_MOTOR) == 0) { /* Turn on the motor, being careful about pairing. */ struct fd_softc *ofd = fdc->sc_fd[fd->sc_drive ^ 1]; if (ofd && ofd->sc_flags & FD_MOTOR) { callout_stop(&ofd->sc_motoroff_ch); ofd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT); } fd->sc_flags |= FD_MOTOR | FD_MOTOR_WAIT; fd_set_motor(fdc, 0); fdc->sc_state = MOTORWAIT; /* Allow .25s for motor to stabilize. */ callout_reset(&fd->sc_motoron_ch, hz / 4, fd_motor_on, fd); return 1; } /* Make sure the right drive is selected. */ fd_set_motor(fdc, 0); /* fall through */ case DOSEEK: doseek: if (fd->sc_cylin == bp->b_cylinder) goto doio; out_fdc(iot, ioh, NE7CMD_SPECIFY);/* specify command */ out_fdc(iot, ioh, fd->sc_type->steprate); out_fdc(iot, ioh, 6); /* XXX head load time == 6ms */ out_fdc(iot, ioh, NE7CMD_SEEK); /* seek function */ out_fdc(iot, ioh, fd->sc_drive); /* drive number */ out_fdc(iot, ioh, bp->b_cylinder * fd->sc_type->step); fd->sc_cylin = -1; fdc->sc_state = SEEKWAIT; iostat_seek(fd->sc_dk.dk_stats); disk_busy(&fd->sc_dk); callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc); return 1; case DOIO: doio: type = fd->sc_type; if (finfo) fd->sc_skip = (char *)&(finfo->fd_formb_cylno(0)) - (char *)finfo; sec = fd->sc_blkno % type->seccyl; nblks = type->seccyl - sec; nblks = min(nblks, fd->sc_bcount / FDC_BSIZE); nblks = min(nblks, fdc->sc_maxiosize / FDC_BSIZE); fd->sc_nblks = nblks; fd->sc_nbytes = finfo ? bp->b_bcount : nblks * FDC_BSIZE; head = sec / type->sectrac; sec -= head * type->sectrac; #ifdef DIAGNOSTIC { int block; block = (fd->sc_cylin * type->heads + head) * type->sectrac + sec; if (block != fd->sc_blkno) { printf("fdcintr: block %d != blkno " "%" PRId64 "\n", block, fd->sc_blkno); #ifdef DDB Debugger(); #endif } } #endif read = bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE; isa_dmastart(fdc->sc_ic, fdc->sc_drq, (char *)bp->b_data + fd->sc_skip, fd->sc_nbytes, NULL, read | DMAMODE_DEMAND, BUS_DMA_NOWAIT); bus_space_write_1(iot, fdc->sc_fdctlioh, 0, type->rate); #ifdef FD_DEBUG printf("fdcintr: %s drive %d track %d head %d sec %d nblks %d\n", read ? "read" : "write", fd->sc_drive, fd->sc_cylin, head, sec, nblks); #endif if (finfo) { /* formatting */ if (out_fdc(iot, ioh, NE7CMD_FORMAT) < 0) { fdc->sc_errors = 4; fdcretry(fdc); goto loop; } out_fdc(iot, ioh, (head << 2) | fd->sc_drive); out_fdc(iot, ioh, finfo->fd_formb_secshift); out_fdc(iot, ioh, finfo->fd_formb_nsecs); out_fdc(iot, ioh, finfo->fd_formb_gaplen); out_fdc(iot, ioh, finfo->fd_formb_fillbyte); } else { if (read) out_fdc(iot, ioh, NE7CMD_READ); /* READ */ else out_fdc(iot, ioh, NE7CMD_WRITE); /* WRITE */ out_fdc(iot, ioh, (head << 2) | fd->sc_drive); out_fdc(iot, ioh, fd->sc_cylin); /* track */ out_fdc(iot, ioh, head); out_fdc(iot, ioh, sec + 1); /* sector +1 */ out_fdc(iot, ioh, type->secsize);/* sector size */ out_fdc(iot, ioh, type->sectrac);/* sectors/track */ out_fdc(iot, ioh, type->gap1); /* gap1 size */ out_fdc(iot, ioh, type->datalen);/* data length */ } fdc->sc_state = IOCOMPLETE; disk_busy(&fd->sc_dk); /* allow 2 seconds for operation */ callout_reset(&fdc->sc_timo_ch, 2 * hz, fdctimeout, fdc); return 1; /* will return later */ case SEEKWAIT: callout_stop(&fdc->sc_timo_ch); fdc->sc_state = SEEKCOMPLETE; /* allow 1/50 second for heads to settle */ callout_reset(&fdc->sc_intr_ch, hz / 50, fdcintrcb, fdc); return 1; case SEEKCOMPLETE: /* no data on seek */ disk_unbusy(&fd->sc_dk, 0, 0); /* Make sure seek really happened. */ out_fdc(iot, ioh, NE7CMD_SENSEI); if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || cyl != bp->b_cylinder * fd->sc_type->step) { #ifdef FD_DEBUG fdcstatus(fd->sc_dev, 2, "seek failed"); #endif fdcretry(fdc); goto loop; } fd->sc_cylin = bp->b_cylinder; goto doio; case IOTIMEDOUT: isa_dmaabort(fdc->sc_ic, fdc->sc_drq); case SEEKTIMEDOUT: case RECALTIMEDOUT: case RESETTIMEDOUT: fdcretry(fdc); goto loop; case IOCOMPLETE: /* IO DONE, post-analyze */ callout_stop(&fdc->sc_timo_ch); disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid), (bp->b_flags & B_READ)); if (fdcresult(fdc) != 7 || (st0 & 0xf8) != 0) { isa_dmaabort(fdc->sc_ic, fdc->sc_drq); #ifdef FD_DEBUG fdcstatus(fd->sc_dev, 7, bp->b_flags & B_READ ? "read failed" : "write failed"); printf("blkno %llu nblks %d\n", (unsigned long long)fd->sc_blkno, fd->sc_nblks); #endif fdcretry(fdc); goto loop; } isa_dmadone(fdc->sc_ic, fdc->sc_drq); if (fdc->sc_errors) { diskerr(bp, "fd", "soft error (corrected)", LOG_PRINTF, fd->sc_skip / FDC_BSIZE, NULL); printf("\n"); fdc->sc_errors = 0; } fd->sc_blkno += fd->sc_nblks; fd->sc_skip += fd->sc_nbytes; fd->sc_bcount -= fd->sc_nbytes; if (!finfo && fd->sc_bcount > 0) { bp->b_cylinder = fd->sc_blkno / fd->sc_type->seccyl; goto doseek; } fdfinish(fd, bp); goto loop; case DORESET: /* try a reset, keep motor on */ fd_set_motor(fdc, 1); delay(100); fd_set_motor(fdc, 0); fdc->sc_state = RESETCOMPLETE; callout_reset(&fdc->sc_timo_ch, hz / 2, fdctimeout, fdc); return 1; /* will return later */ case RESETCOMPLETE: callout_stop(&fdc->sc_timo_ch); /* clear the controller output buffer */ for (i = 0; i < 4; i++) { out_fdc(iot, ioh, NE7CMD_SENSEI); (void) fdcresult(fdc); } /* fall through */ case DORECAL: out_fdc(iot, ioh, NE7CMD_RECAL); /* recalibrate function */ out_fdc(iot, ioh, fd->sc_drive); fdc->sc_state = RECALWAIT; callout_reset(&fdc->sc_timo_ch, 5 * hz, fdctimeout, fdc); return 1; /* will return later */ case RECALWAIT: callout_stop(&fdc->sc_timo_ch); fdc->sc_state = RECALCOMPLETE; /* allow 1/30 second for heads to settle */ callout_reset(&fdc->sc_intr_ch, hz / 30, fdcintrcb, fdc); return 1; /* will return later */ case RECALCOMPLETE: out_fdc(iot, ioh, NE7CMD_SENSEI); if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) { #ifdef FD_DEBUG fdcstatus(fd->sc_dev, 2, "recalibrate failed"); #endif fdcretry(fdc); goto loop; } fd->sc_cylin = 0; goto doseek; case MOTORWAIT: if (fd->sc_flags & FD_MOTOR_WAIT) return 1; /* time's not up yet */ goto doseek; default: fdcstatus(fd->sc_dev, 0, "stray interrupt"); return 1; } #undef st0 #undef cyl out: cv_signal(&fdc->sc_cv); return 1; }
void cecxfer(void *v, int slave, int sec, void *buf, int count, int dir, int timo) { struct cec_softc *sc = v; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; DPRINTF(DBG_FOLLOW, ("cecxfer: slave=%d sec=%d buf=%p count=%d dir=%x timo=%d\n", slave, sec, buf, count, dir, timo)); sc->sc_flags |= CECF_IO; if (dir == GPIB_READ) sc->sc_flags |= CECF_READ; if (timo) { sc->sc_flags |= CECF_TIMO; callout_reset(&sc->sc_timeout_ch, 5*hz, cectimeout, sc); } if (sc->sc_flags & CECF_READ) { DPRINTF(DBG_FOLLOW, ("cecxfer: DMA read request\n")); if ((sc->sc_flags & CECF_USEDMA) != 0) { isa_dmastart(sc->sc_ic, sc->sc_drq, buf, count, NULL, DMAMODE_READ | DMAMODE_DEMAND, BUS_DMA_NOWAIT); bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_DMAI); bus_space_write_1(iot, ioh, NEC7210_IMR1, IMR1_END); // XXX (void) cecrecv(sc, slave, sec, NULL, 0); (void) gpibrecv(&cec_ic, slave, sec, NULL, 0); } else { /* XXX this doesn't work */ DPRINTF(DBG_FOLLOW, ("cecxfer: polling instead\n")); bus_space_write_1(iot, ioh, NEC7210_IMR1, IMR1_END); // XXX (void) cecrecv(sc, slave, sec, buf, count); (void) gpibrecv(&cec_ic, slave, sec, buf, count); bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_CO); } } else { DPRINTF(DBG_FOLLOW, ("cecxfer: DMA write request\n")); bus_space_write_1(iot, ioh, NEC7210_IMR2, 0); if (count < cecdmathresh || (sc->sc_flags & CECF_USEDMA) == 0) { DPRINTF(DBG_FOLLOW, ("cecxfer: polling instead\n")); // XXX (void) cecsend(sc, slave, sec, buf, count); (void) gpibsend(&cec_ic, slave, sec, buf, count); bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_CO); return; } /* we send the last byte with EOI set */ isa_dmastart(sc->sc_ic, sc->sc_drq, buf, count-1, NULL, DMAMODE_WRITE | DMAMODE_DEMAND, BUS_DMA_NOWAIT); bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_DMAO); // XXX (void) cecsend(sc, slave, sec, NULL, 0); (void) gpibsend(&cec_ic, slave, sec, NULL, 0); while (!isa_dmafinished(sc->sc_ic, sc->sc_drq)) DELAY(1); (void) cecwait(sc, ISR1_DO, 0); bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SEOI); bus_space_write_1(iot, ioh, NEC7210_CDOR, *(char *)buf+count); /* generate interrupt */ bus_space_write_1(iot, ioh, NEC7210_IMR1, IMR1_DO); } }