Пример #1
0
static int
fw_open (struct cdev *dev, int flags, int fmt, fw_proc *td)
{
	int err = 0;
	int unit = DEV2UNIT(dev);
	struct fw_drv1 *d;
	struct firewire_softc *sc;

	if (DEV_FWMEM(dev))
		return fwmem_open(dev, flags, fmt, td);

	sc = devclass_get_softc(firewire_devclass, unit);
	if (sc == NULL)
		return (ENXIO);

	FW_GLOCK(sc->fc);
	if (dev->si_drv1 != NULL) {
		FW_GUNLOCK(sc->fc);
		return (EBUSY);
	}
	/* set dummy value for allocation */
	dev->si_drv1 = (void *)-1;
	FW_GUNLOCK(sc->fc);

	dev->si_drv1 = malloc(sizeof(struct fw_drv1), M_FW, M_WAITOK | M_ZERO);
	if (dev->si_drv1 == NULL)
		return (ENOMEM);

#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
	if ((dev->si_flags & SI_NAMED) == 0) {
		int unit = DEV2UNIT(dev);
		int sub = DEV2SUB(dev);

		make_dev(&firewire_cdevsw, dev2unit(dev),
			UID_ROOT, GID_OPERATOR, 0660,
			"fw%d.%d", unit, sub);
	}
#endif
	d = (struct fw_drv1 *)dev->si_drv1;
	d->fc = sc->fc;
	STAILQ_INIT(&d->binds);
	STAILQ_INIT(&d->rq);

	return err;
}
Пример #2
0
static int
fw_read_async(struct fw_drv1 *d, struct uio *uio, int ioflag)
{
	int err = 0, s;
	struct fw_xfer *xfer;
	struct fw_bind *fwb;
	struct fw_pkt *fp;
	struct tcode_info *tinfo;

	FW_GLOCK(d->fc);
	while ((xfer = STAILQ_FIRST(&d->rq)) == NULL && err == 0)
		err = msleep(&d->rq, FW_GMTX(d->fc), FWPRI, "fwra", 0);

	if (err != 0) {
		FW_GUNLOCK(d->fc);
		return (err);
	}

	s = splfw();
	STAILQ_REMOVE_HEAD(&d->rq, link);
	FW_GUNLOCK(xfer->fc);
	splx(s);
	fp = &xfer->recv.hdr;
#if 0 /* for GASP ?? */
	if (fc->irx_post != NULL)
		fc->irx_post(fc, fp->mode.ld);
#endif
	tinfo = &xfer->fc->tcode[fp->mode.hdr.tcode];
	err = uiomove(fp, tinfo->hdr_len, uio);
	if (err)
		goto out;
	err = uiomove(xfer->recv.payload, xfer->recv.pay_len, uio);

out:
	/* recycle this xfer */
	fwb = (struct fw_bind *)xfer->sc;
	fw_xfer_unload(xfer);
	xfer->recv.pay_len = PAGE_SIZE;
	FW_GLOCK(xfer->fc);
	STAILQ_INSERT_TAIL(&fwb->xferlist, xfer, link);
	FW_GUNLOCK(xfer->fc);
	return (err);
}
Пример #3
0
static int
fw_write_async(struct fw_drv1 *d, struct uio *uio, int ioflag)
{
	struct fw_xfer *xfer;
	struct fw_pkt pkt;
	struct tcode_info *tinfo;
	int err;

	bzero(&pkt, sizeof(struct fw_pkt));
	if ((err = uiomove((caddr_t)&pkt, sizeof(uint32_t), uio)))
		return (err);
	tinfo = &d->fc->tcode[pkt.mode.hdr.tcode];
	if ((err = uiomove((caddr_t)&pkt + sizeof(uint32_t),
	    tinfo->hdr_len - sizeof(uint32_t), uio)))
		return (err);

	if ((xfer = fw_xfer_alloc_buf(M_FWXFER, uio->uio_resid,
	    PAGE_SIZE/*XXX*/)) == NULL)
		return (ENOMEM);

	bcopy(&pkt, &xfer->send.hdr, sizeof(struct fw_pkt));
	xfer->send.pay_len = uio->uio_resid;
	if (uio->uio_resid > 0) {
		if ((err = uiomove((caddr_t)&xfer->send.payload[0],
		    uio->uio_resid, uio)))
			goto out;
	}

	xfer->fc = d->fc;
	xfer->sc = NULL;
	xfer->hand = fw_xferwake;
	xfer->send.spd = 2 /* XXX */;

	if ((err = fw_asyreq(xfer->fc, -1, xfer)))
		goto out;

	if ((err = fw_xferwait(xfer)))
		goto out;

	if (xfer->resp != 0) {
		err = xfer->resp;
		goto out;
	}

	if (xfer->flag & FWXF_RCVD) {
		FW_GLOCK(xfer->fc);
		STAILQ_INSERT_TAIL(&d->rq, xfer, link);
		FW_GUNLOCK(xfer->fc);
		return (0);
	}

out:
	fw_xfer_free(xfer);
	return (err);
}
Пример #4
0
static void
fw_hand(struct fw_xfer *xfer)
{
	struct fw_bind *fwb;
	struct fw_drv1 *d;

	fwb = (struct fw_bind *)xfer->sc;
	d = fwb->sc;
	FW_GLOCK(xfer->fc);
	STAILQ_INSERT_TAIL(&d->rq, xfer, link);
	FW_GUNLOCK(xfer->fc);
	wakeup(&d->rq);
}
Пример #5
0
int
fwmem_open(struct cdev *dev, int flags, int fmt, fw_proc *td)
{
	struct fwmem_softc *fms;
	struct firewire_softc *sc;
	int unit = DEV2UNIT(dev);

	sc = devclass_get_softc(firewire_devclass, unit);
	if (sc == NULL)
		return (ENXIO);

	FW_GLOCK(sc->fc);
	if (dev->si_drv1 != NULL) {
		if ((flags & FWRITE) != 0) {
			FW_GUNLOCK(sc->fc);
			return (EBUSY);
		}
		FW_GUNLOCK(sc->fc);
		fms = dev->si_drv1;
		fms->refcount++;
	} else {
		dev->si_drv1 = (void *)-1;
		FW_GUNLOCK(sc->fc);
		dev->si_drv1 = malloc(sizeof(struct fwmem_softc),
		    M_FWMEM, M_WAITOK);
		if (dev->si_drv1 == NULL)
			return (ENOMEM);
		dev->si_iosize_max = DFLTPHYS;
		fms = dev->si_drv1;
		bcopy(&fwmem_eui64, &fms->eui, sizeof(struct fw_eui64));
		fms->sc = sc;
		fms->refcount = 1;
	}
	if (fwmem_debug)
		printf("%s: refcount=%d\n", __func__, fms->refcount);

	return (0);
}
Пример #6
0
int
fwmem_close (struct cdev *dev, int flags, int fmt, fw_proc *td)
{
	struct fwmem_softc *fms;

	fms = dev->si_drv1;

	FW_GLOCK(fms->sc->fc);
	fms->refcount--;
	FW_GUNLOCK(fms->sc->fc);
	if (fwmem_debug)
		printf("%s: refcount=%d\n", __func__, fms->refcount);
	if (fms->refcount < 1) {
		free(dev->si_drv1, M_FWMEM);
		dev->si_drv1 = NULL;
	}

	return (0);
}
Пример #7
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;
}
Пример #8
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;
}