Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
/*
 * 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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
/*
 * 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;
}