Beispiel #1
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;
}
Beispiel #2
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;
}