Example #1
0
static void
fwip_stop(struct fwip_softc *fwip)
{
	struct firewire_comm *fc;
	struct fw_xferq *xferq;
	struct ifnet *ifp = fwip->fw_softc.fwip_ifp;
	struct fw_xfer *xfer, *next;
	int i;

	fc = fwip->fd.fc;

	if (fwip->dma_ch >= 0) {
		xferq = fc->ir[fwip->dma_ch];

		if (xferq->flag & FWXFERQ_RUNNING)
			fc->irx_disable(fc, fwip->dma_ch);
		xferq->flag &= 
			~(FWXFERQ_MODEMASK | FWXFERQ_OPEN | FWXFERQ_STREAM |
			FWXFERQ_EXTBUF | FWXFERQ_HANDLER | FWXFERQ_CHTAGMASK);
		xferq->hand =  NULL;

		for (i = 0; i < xferq->bnchunk; i ++)
			m_freem(xferq->bulkxfer[i].mbuf);
		free(xferq->bulkxfer, M_FWIP);

		fw_bindremove(fc, &fwip->fwb);
		for (xfer = STAILQ_FIRST(&fwip->fwb.xferlist); xfer != NULL;
					xfer = next) {
			next = STAILQ_NEXT(xfer, link);
			fw_xfer_free(xfer);
		}

		for (xfer = STAILQ_FIRST(&fwip->xferlist); xfer != NULL;
					xfer = next) {
			next = STAILQ_NEXT(xfer, link);
			fw_xfer_free(xfer);
		}
		STAILQ_INIT(&fwip->xferlist);

		xferq->bulkxfer =  NULL;
		fwip->dma_ch = -1;
	}

#if defined(__FreeBSD__)
	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
#else
	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
#endif
}
Example #2
0
struct fw_xfer *
fwmem_write_quad(
	struct fw_device *fwdev,
	caddr_t	sc,
	uint8_t spd,
	uint16_t dst_hi,
	uint32_t dst_lo,
	void *data,
	void (*hand)(struct fw_xfer *))
{
	struct fw_xfer *xfer;
	struct fw_pkt *fp;

	xfer = fwmem_xfer_req(fwdev, sc, spd, 0, 0, hand);
	if (xfer == NULL)
		return NULL;

	fp = &xfer->send.hdr;
	fp->mode.wreqq.tcode = FWTCODE_WREQQ;
	fp->mode.wreqq.dest_hi = dst_hi;
	fp->mode.wreqq.dest_lo = dst_lo;
	fp->mode.wreqq.data = *(uint32_t *)data;

	xfer->send.payload = xfer->recv.payload = NULL;

	if (fwmem_debug)
		printf("fwmem_write_quad: %d %04x:%08x %08x\n", fwdev->dst,
		    dst_hi, dst_lo, *(uint32_t *)data);

	if (fw_asyreq(xfer->fc, -1, xfer) == 0)
		return xfer;

	fw_xfer_free(xfer);
	return NULL;
}
Example #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);
}
Example #4
0
static void
fwmem_biodone(struct fw_xfer *xfer)
{
	struct bio *bp;

	bp = (struct bio *)xfer->sc;
	bp->bio_error = xfer->resp;

	if (bp->bio_error != 0) {
		if (fwmem_debug)
			printf("%s: err=%d\n", __func__, bp->bio_error);
		bp->bio_flags |= BIO_ERROR;
		bp->bio_resid = bp->bio_bcount;
	}

	fw_xfer_free(xfer);
	biodone(bp);
}
Example #5
0
static void
fwe_output_callback(struct fw_xfer *xfer)
{
	struct fwe_softc *fwe;
	struct ifnet *ifp;

	fwe = (struct fwe_softc *)xfer->sc;
	/* XXX error check */
	FWEDEBUG("resp = %d\n", xfer->resp);
	m_freem(xfer->mbuf);
	xfer->send.buf = NULL;
	fw_xfer_free(xfer);
#if 1
	/* XXX for queue full */
	ifp = &fwe->fwe_if;
	if (ifp->if_snd.ifq_head != NULL)
		fwe_start(ifp);
#endif
}
Example #6
0
struct fw_xfer *
fwmem_write_block(
	struct fw_device *fwdev,
	caddr_t	sc,
	uint8_t spd,
	uint16_t dst_hi,
	uint32_t dst_lo,
	int len,
	void *data,
	void (*hand)(struct fw_xfer *))
{
	struct fw_xfer *xfer;
	struct fw_pkt *fp;

	xfer = fwmem_xfer_req(fwdev, sc, spd, len, 0, hand);
	if (xfer == NULL)
		return NULL;

	fp = &xfer->send.hdr;
	fp->mode.wreqb.tcode = FWTCODE_WREQB;
	fp->mode.wreqb.dest_hi = dst_hi;
	fp->mode.wreqb.dest_lo = dst_lo;
	fp->mode.wreqb.len = len;
	fp->mode.wreqb.extcode = 0;

	xfer->send.payload = data;
	xfer->recv.payload = NULL;

	if (fwmem_debug)
		printf("fwmem_write_block: %d %04x:%08x %d\n", fwdev->dst,
				dst_hi, dst_lo, len);
	if (fw_asyreq(xfer->fc, -1, xfer) == 0)
		return xfer;

	fw_xfer_free(xfer);
	return NULL;
}
Example #7
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;
}
Example #8
0
/* Async. stream output */
static void
fwe_as_input(struct fw_xferq *xferq)
{
	struct mbuf *m;
	struct ether_header *eh;
	struct ifnet *ifp;
	struct fw_xfer *xfer;
	struct fwe_softc *fwe;
	u_char *c;
	int len;
	caddr_t p;

	fwe = (struct fwe_softc *)xferq->sc;
	ifp = &fwe->fwe_if;
#if 0
	FWE_POLL_REGISTER(fwe_poll, fwe, ifp);
#endif
	while ((xfer = STAILQ_FIRST(&xferq->q)) != NULL) {
		STAILQ_REMOVE_HEAD(&xferq->q, link);
		xferq->queued --;
		MGETHDR(m, M_DONTWAIT, MT_DATA);
		if (m == NULL) {
			printf("MGETHDR failed\n");
			fw_xfer_free(xfer);
			return;
		}
		len = xfer->recv.off + xfer->recv.len;
		FWEDEBUG("fwe_as_input len=%d\n", len);
#if __FreeBSD_version >= 500000
		MEXTADD(m, xfer->recv.buf, len, fwe_free, NULL, 0, EXT_NET_DRV);
#else
		m->m_flags |= M_EXT;
		m->m_ext.ext_buf = xfer->recv.buf;
		m->m_ext.ext_size = len;
		m->m_ext.ext_free = fwe_free;
		m->m_ext.ext_ref = fwe_ref;
		*((int *)m->m_ext.ext_buf) = 1;  /* XXX refcount */
#endif
		p = xfer->recv.buf + xfer->recv.off + HDR_LEN + ALIGN_PAD;
		eh = (struct ether_header *)p;
#if __FreeBSD_version >= 500000
		len -= xfer->recv.off + HDR_LEN + ALIGN_PAD;
#else
		p += sizeof(struct ether_header);
		len -= xfer->recv.off + HDR_LEN + ALIGN_PAD
						+ sizeof(struct ether_header);
#endif
		m->m_data = p;
		m->m_len = m->m_pkthdr.len = len;
		m->m_pkthdr.rcvif = ifp;
		c = (char *)eh;
#if 0
		FWEDEBUG("%02x %02x %02x %02x %02x %02x\n"
			 "%02x %02x %02x %02x %02x %02x\n"
			 "%02x %02x %02x %02x\n"
			 "%02x %02x %02x %02x\n"
			 "%02x %02x %02x %02x\n"
			 "%02x %02x %02x %02x\n",
			 c[0], c[1], c[2], c[3], c[4], c[5],
			 c[6], c[7], c[8], c[9], c[10], c[11],
			 c[12], c[13], c[14], c[15],
			 c[16], c[17], c[18], c[19],
			 c[20], c[21], c[22], c[23],
			 c[20], c[21], c[22], c[23]
		 );
#endif
#if __FreeBSD_version >= 500000
		(*ifp->if_input)(ifp, m);
#else
		ether_input(ifp, eh, m);
#endif
		ifp->if_ipackets ++;

		xfer->recv.buf = NULL;
		fw_xfer_free(xfer);
	}
}