static int fw_write (struct dev_write_args *ap) { cdev_t dev = ap->a_head.a_dev; struct uio *uio = ap->a_uio; int err = 0; struct firewire_softc *sc; int unit = DEV2UNIT(dev); int slept = 0; struct fw_pkt *fp; struct fw_xferq *it; if (DEV_FWMEM(dev)) return physwrite(ap); sc = devclass_get_softc(firewire_devclass, unit); it = ((struct fw_drv1 *)dev->si_drv1)->it; if (it == NULL || it->buf == NULL) return (EIO); isoloop: if (it->stproc == NULL) { it->stproc = STAILQ_FIRST(&it->stfree); if (it->stproc != NULL) { crit_enter(); STAILQ_REMOVE_HEAD(&it->stfree, link); crit_exit(); it->queued = 0; } else if (slept == 0) { slept = 1; err = sc->fc->itx_enable(sc->fc, it->dmach); if (err) return err; err = tsleep(it, FWPRI, "fw_write", hz); if (err) return err; goto isoloop; } else { err = EIO; return err; } } fp = (struct fw_pkt *)fwdma_v_addr(it->buf, it->stproc->poffset + it->queued); err = uiomove((caddr_t)fp, sizeof(struct fw_isohdr), uio); err = uiomove((caddr_t)fp->mode.stream.payload, fp->mode.stream.len, uio); it->queued ++; if (it->queued >= it->bnpacket) { crit_enter(); STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link); crit_exit(); it->stproc = NULL; err = sc->fc->itx_enable(sc->fc, it->dmach); } if (uio->uio_resid >= sizeof(struct fw_isohdr)) { slept = 0; goto isoloop; } return err; }
static int fw_write(struct cdev *dev, struct uio *uio, int ioflag) { int err = 0; int s, slept = 0; struct fw_drv1 *d; struct fw_pkt *fp; struct firewire_comm *fc; struct fw_xferq *it; if (DEV_FWMEM(dev)) return (physio(dev, uio, ioflag)); d = dev->si_drv1; fc = d->fc; it = d->it; if (it == NULL) return (fw_write_async(d, uio, ioflag)); if (it->buf == NULL) return (EIO); FW_GLOCK(fc); isoloop: if (it->stproc == NULL) { it->stproc = STAILQ_FIRST(&it->stfree); if (it->stproc != NULL) { s = splfw(); STAILQ_REMOVE_HEAD(&it->stfree, link); splx(s); it->queued = 0; } else if (slept == 0) { slept = 1; #if 0 /* XXX to avoid lock recursion */ err = fc->itx_enable(fc, it->dmach); if (err) goto out; #endif err = msleep(it, FW_GMTX(fc), FWPRI, "fw_write", hz); if (err) goto out; goto isoloop; } else { err = EIO; goto out; } } FW_GUNLOCK(fc); fp = (struct fw_pkt *)fwdma_v_addr(it->buf, it->stproc->poffset + it->queued); err = uiomove((caddr_t)fp, sizeof(struct fw_isohdr), uio); err = uiomove((caddr_t)fp->mode.stream.payload, fp->mode.stream.len, uio); it->queued++; if (it->queued >= it->bnpacket) { s = splfw(); STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link); splx(s); it->stproc = NULL; err = fc->itx_enable(fc, it->dmach); } if (uio->uio_resid >= sizeof(struct fw_isohdr)) { slept = 0; FW_GLOCK(fc); goto isoloop; } return err; out: FW_GUNLOCK(fc); return err; }
/* * read request. */ static int fw_read(struct cdev *dev, struct uio *uio, int ioflag) { struct fw_drv1 *d; struct fw_xferq *ir; struct firewire_comm *fc; int err = 0, s, slept = 0; struct fw_pkt *fp; if (DEV_FWMEM(dev)) return (physio(dev, uio, ioflag)); d = dev->si_drv1; fc = d->fc; ir = d->ir; if (ir == NULL) return (fw_read_async(d, uio, ioflag)); if (ir->buf == NULL) return (EIO); FW_GLOCK(fc); readloop: if (ir->stproc == NULL) { /* iso bulkxfer */ ir->stproc = STAILQ_FIRST(&ir->stvalid); if (ir->stproc != NULL) { s = splfw(); STAILQ_REMOVE_HEAD(&ir->stvalid, link); splx(s); ir->queued = 0; } } if (ir->stproc == NULL) { /* no data avaliable */ if (slept == 0) { slept = 1; ir->flag |= FWXFERQ_WAKEUP; err = msleep(ir, FW_GMTX(fc), FWPRI, "fw_read", hz); ir->flag &= ~FWXFERQ_WAKEUP; if (err == 0) goto readloop; } else if (slept == 1) err = EIO; FW_GUNLOCK(fc); return err; } else if (ir->stproc != NULL) { /* iso bulkxfer */ FW_GUNLOCK(fc); fp = (struct fw_pkt *)fwdma_v_addr(ir->buf, ir->stproc->poffset + ir->queued); if (fc->irx_post != NULL) fc->irx_post(fc, fp->mode.ld); if (fp->mode.stream.len == 0) { err = EIO; return err; } err = uiomove((caddr_t)fp, fp->mode.stream.len + sizeof(uint32_t), uio); ir->queued++; if (ir->queued >= ir->bnpacket) { s = splfw(); STAILQ_INSERT_TAIL(&ir->stfree, ir->stproc, link); splx(s); fc->irx_enable(fc, ir->dmach); ir->stproc = NULL; } if (uio->uio_resid >= ir->psize) { slept = -1; FW_GLOCK(fc); goto readloop; } } return err; }
int fw_write(dev_t dev, struct uio *uio, int ioflag) { struct firewire_softc *sc; struct firewire_comm *fc; struct fw_drv1 *d; struct fw_pkt *fp; struct fw_xferq *it; int slept = 0, err = 0; sc = device_lookup_private(&ieee1394if_cd, DEV2UNIT(dev)); if (sc == NULL) return ENXIO; if (DEV_FWMEM(dev)) return physio(fw_strategy, NULL, dev, ioflag, minphys, uio); d = (struct fw_drv1 *)sc->si_drv1; fc = d->fc; it = d->it; if (it == NULL) return fw_write_async(d, uio, ioflag); if (it->buf == NULL) return EIO; mutex_enter(&fc->fc_mtx); isoloop: if (it->stproc == NULL) { it->stproc = STAILQ_FIRST(&it->stfree); if (it->stproc != NULL) { STAILQ_REMOVE_HEAD(&it->stfree, link); it->queued = 0; } else if (slept == 0) { slept = 1; #if 0 /* XXX to avoid lock recursion */ err = fc->itx_enable(fc, it->dmach); if (err) goto out; #endif mutex_exit(&fc->fc_mtx); err = tsleep(it, FWPRI, "fw_write", hz); mutex_enter(&fc->fc_mtx); if (err) goto out; goto isoloop; } else { err = EIO; goto out; } } mutex_exit(&fc->fc_mtx); fp = (struct fw_pkt *)fwdma_v_addr(it->buf, it->stproc->poffset + it->queued); err = uiomove((void *)fp, sizeof(struct fw_isohdr), uio); if (err != 0) return err; err = uiomove((void *)fp->mode.stream.payload, fp->mode.stream.len, uio); it->queued++; if (it->queued >= it->bnpacket) { STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link); it->stproc = NULL; err = fc->itx_enable(fc, it->dmach); } if (uio->uio_resid >= sizeof(struct fw_isohdr)) { slept = 0; mutex_enter(&fc->fc_mtx); goto isoloop; } return err; out: mutex_exit(&fc->fc_mtx); return err; }
int fw_read(dev_t dev, struct uio *uio, int ioflag) { struct firewire_softc *sc; struct firewire_comm *fc; struct fw_drv1 *d; struct fw_xferq *ir; struct fw_pkt *fp; int err = 0, slept = 0; sc = device_lookup_private(&ieee1394if_cd, DEV2UNIT(dev)); if (sc == NULL) return ENXIO; if (DEV_FWMEM(dev)) return physio(fw_strategy, NULL, dev, ioflag, minphys, uio); d = (struct fw_drv1 *)sc->si_drv1; fc = d->fc; ir = d->ir; if (ir == NULL) return fw_read_async(d, uio, ioflag); if (ir->buf == NULL) return EIO; mutex_enter(&fc->fc_mtx); readloop: if (ir->stproc == NULL) { /* iso bulkxfer */ ir->stproc = STAILQ_FIRST(&ir->stvalid); if (ir->stproc != NULL) { STAILQ_REMOVE_HEAD(&ir->stvalid, link); ir->queued = 0; } } if (ir->stproc == NULL) { /* no data avaliable */ if (slept == 0) { slept = 1; ir->flag |= FWXFERQ_WAKEUP; mutex_exit(&fc->fc_mtx); err = tsleep(ir, FWPRI, "fw_read", hz); mutex_enter(&fc->fc_mtx); ir->flag &= ~FWXFERQ_WAKEUP; if (err == 0) goto readloop; } else if (slept == 1) err = EIO; mutex_exit(&fc->fc_mtx); return err; } else if (ir->stproc != NULL) { /* iso bulkxfer */ mutex_exit(&fc->fc_mtx); fp = (struct fw_pkt *)fwdma_v_addr(ir->buf, ir->stproc->poffset + ir->queued); if (fc->irx_post != NULL) fc->irx_post(fc, fp->mode.ld); if (fp->mode.stream.len == 0) return EIO; err = uiomove((void *)fp, fp->mode.stream.len + sizeof(uint32_t), uio); ir->queued++; if (ir->queued >= ir->bnpacket) { STAILQ_INSERT_TAIL(&ir->stfree, ir->stproc, link); fc->irx_enable(fc, ir->dmach); ir->stproc = NULL; } if (uio->uio_resid >= ir->psize) { slept = -1; mutex_enter(&fc->fc_mtx); goto readloop; } } else mutex_exit(&fc->fc_mtx); return err; }
/* * read request. */ static int fw_read (struct dev_read_args *ap) { cdev_t dev = ap->a_head.a_dev; struct uio *uio = ap->a_uio; struct firewire_softc *sc; struct fw_xferq *ir; struct fw_xfer *xfer; int err = 0, slept = 0; int unit = DEV2UNIT(dev); struct fw_pkt *fp; if (DEV_FWMEM(dev)) return physread(ap); sc = devclass_get_softc(firewire_devclass, unit); ir = ((struct fw_drv1 *)dev->si_drv1)->ir; if (ir == NULL || ir->buf == NULL) return (EIO); readloop: xfer = STAILQ_FIRST(&ir->q); if (ir->stproc == NULL) { /* iso bulkxfer */ ir->stproc = STAILQ_FIRST(&ir->stvalid); if (ir->stproc != NULL) { crit_enter(); STAILQ_REMOVE_HEAD(&ir->stvalid, link); crit_exit(); ir->queued = 0; } } if (xfer == NULL && ir->stproc == NULL) { /* no data avaliable */ if (slept == 0) { slept = 1; ir->flag |= FWXFERQ_WAKEUP; err = tsleep(ir, FWPRI, "fw_read", hz); ir->flag &= ~FWXFERQ_WAKEUP; if (err == 0) goto readloop; } else if (slept == 1) err = EIO; return err; } else if(xfer != NULL) { #if 0 /* XXX broken */ /* per packet mode or FWACT_CH bind?*/ crit_enter(); ir->queued --; STAILQ_REMOVE_HEAD(&ir->q, link); crit_exit(); fp = &xfer->recv.hdr; if (sc->fc->irx_post != NULL) sc->fc->irx_post(sc->fc, fp->mode.ld); err = uiomove((void *)fp, 1 /* XXX header size */, uio); /* XXX copy payload too */ /* XXX we should recycle this xfer */ #endif fw_xfer_free( xfer); } else if(ir->stproc != NULL) { /* iso bulkxfer */ fp = (struct fw_pkt *)fwdma_v_addr(ir->buf, ir->stproc->poffset + ir->queued); if(sc->fc->irx_post != NULL) sc->fc->irx_post(sc->fc, fp->mode.ld); if(fp->mode.stream.len == 0){ err = EIO; return err; } err = uiomove((caddr_t)fp, fp->mode.stream.len + sizeof(u_int32_t), uio); ir->queued ++; if(ir->queued >= ir->bnpacket){ crit_enter(); STAILQ_INSERT_TAIL(&ir->stfree, ir->stproc, link); crit_exit(); sc->fc->irx_enable(sc->fc, ir->dmach); ir->stproc = NULL; } if (uio->uio_resid >= ir->psize) { slept = -1; goto readloop; } } return err; }