Exemplo n.º 1
0
int
uriowrite(dev_t dev, struct uio *uio, int flag)
{
	struct urio_softc *sc;
	usbd_xfer_handle xfer;
	usbd_status err;
	void *bufp;
	u_int32_t n;
	int error = 0;

	sc = device_lookup_private(&urio_cd, URIOUNIT(dev));

	DPRINTFN(5, ("uriowrite: unit=%d, len=%ld\n", URIOUNIT(dev),
		     (long)uio->uio_resid));

	if (sc->sc_dying)
		return (EIO);

	xfer = usbd_alloc_xfer(sc->sc_udev);
	if (xfer == NULL)
		return (ENOMEM);
	bufp = usbd_alloc_buffer(xfer, URIO_BSIZE);
	if (bufp == NULL) {
		usbd_free_xfer(xfer);
		return (ENOMEM);
	}

	sc->sc_refcnt++;

	while ((n = min(URIO_BSIZE, uio->uio_resid)) != 0) {
		error = uiomove(bufp, n, uio);
		if (error)
			break;

		DPRINTFN(1, ("uriowrite: transfer %d bytes\n", n));

		err = usbd_bulk_transfer(xfer, sc->sc_out_pipe, USBD_NO_COPY,
			  URIO_RW_TIMEOUT, bufp, &n, "uriowr");
		DPRINTFN(2, ("uriowrite: err=%d\n", err));
		if (err) {
			if (err == USBD_INTERRUPTED)
				error = EINTR;
			else if (err == USBD_TIMEOUT)
				error = ETIMEDOUT;
			else
				error = EIO;
			break;
		}
	}

	usbd_free_xfer(xfer);

	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);

	DPRINTFN(5, ("uriowrite: done unit=%d, error=%d\n", URIOUNIT(dev),
		     error));

	return (error);
}
Exemplo n.º 2
0
int
stuirda_write(void *h, struct uio *uio, int flag)
{
	struct uirda_softc *sc = h;
	usbd_status err;
	u_int32_t n;
	int error = 0;

	DPRINTFN(1,("%s: sc=%p\n", __func__, sc));

	if (sc->sc_dying)
		return (EIO);

#ifdef DIAGNOSTIC
	if (sc->sc_wr_buf == NULL)
		return (EINVAL);
#endif

	n = uio->uio_resid;
	if (n > sc->sc_params.maxsize)
		return (EINVAL);

	sc->sc_refcnt++;
	mutex_enter(&sc->sc_wr_buf_lk);

	sc->sc_wr_buf[0] = UIRDA_EB_NO_CHANGE | UIRDA_NO_SPEED;

	sc->sc_wr_buf[1] = 0;
	sc->sc_wr_buf[2] = 7; /* XXX turnaround - maximum for now */
	if ((n > 0 && (n % 128) == 0 && (n % 512) != 0)) {
		sc->sc_wr_buf[1] = 1;
	}

	error = uiomove(sc->sc_wr_buf + STUIRDA_HEADER_SIZE, n, uio);
	if (!error) {
		DPRINTFN(1, ("uirdawrite: transfer %d bytes\n", n));

		n += STUIRDA_HEADER_SIZE + sc->sc_wr_buf[1];
		err = usbd_bulk_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe,
			  USBD_FORCE_SHORT_XFER|USBD_NO_COPY,
			  UIRDA_WR_TIMEOUT,
			  sc->sc_wr_buf, &n, "uirdawr");
		DPRINTFN(2, ("uirdawrite: err=%d\n", err));
		if (err) {
			if (err == USBD_INTERRUPTED)
				error = EINTR;
			else if (err == USBD_TIMEOUT)
				error = ETIMEDOUT;
			else
				error = EIO;
		}
	}

	mutex_exit(&sc->sc_wr_buf_lk);
	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);

	DPRINTFN(1,("%s: sc=%p done\n", __func__, sc));
	return (error);
}
Exemplo n.º 3
0
int
umass_atapi_attach(struct umass_softc *sc)
{
	struct umass_scsipi_softc *scbus;

	scbus = umass_scsipi_setup(sc);
	scbus->sc_atapi_adapter.atapi_probe_device =  umass_atapi_probe_device;

	scbus->sc_channel.chan_bustype = &umass_atapi_bustype;
	scbus->sc_channel.chan_ntargets = 2;
	scbus->sc_channel.chan_nluns = 1;

	scbus->sc_channel.chan_defquirks |= sc->sc_busquirks;
	DPRINTF(UDMASS_USB, ("%s: umass_attach_bus: ATAPI\n",
			     device_xname(sc->sc_dev)));

	sc->sc_refcnt++;
	scbus->base.sc_child =
	    config_found_ia(sc->sc_dev, "atapi", &scbus->sc_channel,
		atapiprint);
	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);

	return (0);
}
Exemplo n.º 4
0
int
urioread(dev_t dev, struct uio *uio, int flag)
{
	struct urio_softc *sc;
	usbd_xfer_handle xfer;
	usbd_status err;
	void *bufp;
	u_int32_t n, tn;
	int error = 0;

	sc = device_lookup_private(&urio_cd, URIOUNIT(dev));

	DPRINTFN(5, ("urioread: %d\n", URIOUNIT(dev)));

	if (sc->sc_dying)
		return (EIO);

	xfer = usbd_alloc_xfer(sc->sc_udev);
	if (xfer == NULL)
		return (ENOMEM);
	bufp = usbd_alloc_buffer(xfer, URIO_BSIZE);
	if (bufp == NULL) {
		usbd_free_xfer(xfer);
		return (ENOMEM);
	}

	sc->sc_refcnt++;

	while ((n = min(URIO_BSIZE, uio->uio_resid)) != 0) {
		DPRINTFN(1, ("urioread: start transfer %d bytes\n", n));
		tn = n;
		err = usbd_bulk_transfer(xfer, sc->sc_in_pipe, USBD_NO_COPY,
			  URIO_RW_TIMEOUT, bufp, &tn, "uriors");
		if (err) {
			if (err == USBD_INTERRUPTED)
				error = EINTR;
			else if (err == USBD_TIMEOUT)
				error = ETIMEDOUT;
			else
				error = EIO;
			break;
		}

		DPRINTFN(1, ("urioread: got %d bytes\n", tn));

		error = uiomove(bufp, tn, uio);
		if (error || tn < n)
			break;
	}
	usbd_free_xfer(xfer);

	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);

	return (error);
}
Exemplo n.º 5
0
Static void
url_unlock_mii(struct url_softc *sc)
{
	DPRINTFN(0xff, ("%s: %s: enter\n", device_xname(sc->sc_dev),
		       __func__));

	rw_exit(&sc->sc_mii_rwlock);
	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);
}
Exemplo n.º 6
0
/* ARGSUSED */
static int
udsir_close(void *h, int flag, int mode, struct lwp *l)
{
	struct udsir_softc *sc = h;

	DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));

	sc->sc_refcnt++;

	sc->sc_rd_readinprogress = 1;
	sc->sc_closing = 1;

	wakeup(&sc->sc_thread);

	while (sc->sc_thread != NULL)
		tsleep(&sc->sc_closing, PWAIT, "usircl", 0);

	if (sc->sc_rd_pipe != NULL) {
		usbd_abort_pipe(sc->sc_rd_pipe);
	}
	if (sc->sc_wr_pipe != NULL) {
		usbd_abort_pipe(sc->sc_wr_pipe);
	}
	if (sc->sc_rd_xfer != NULL) {
		usbd_destroy_xfer(sc->sc_rd_xfer);
		sc->sc_rd_xfer = NULL;
		sc->sc_rd_buf = NULL;
	}
	if (sc->sc_wr_xfer != NULL) {
		usbd_destroy_xfer(sc->sc_wr_xfer);
		sc->sc_wr_xfer = NULL;
		sc->sc_wr_buf = NULL;
	}
	if (sc->sc_rd_pipe != NULL) {
		usbd_close_pipe(sc->sc_rd_pipe);
		sc->sc_rd_pipe = NULL;
	}
	if (sc->sc_wr_pipe != NULL) {
		usbd_close_pipe(sc->sc_wr_pipe);
		sc->sc_wr_pipe = NULL;
	}
	if (sc->sc_ur_buf != NULL) {
		kmem_free(sc->sc_ur_buf, IRDA_MAX_FRAME_SIZE);
		sc->sc_ur_buf = NULL;
	}

	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);

	return 0;
}
Exemplo n.º 7
0
int
uscannerwrite(dev_t dev, struct uio *uio, int flag)
{
	struct uscanner_softc *sc;
	int error;

	sc = device_lookup_private(&uscanner_cd, USCANNERUNIT(dev));

	sc->sc_refcnt++;
	error = uscanner_do_write(sc, uio, flag);
	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);
	return (error);
}
Exemplo n.º 8
0
int
ucomioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
{
	struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
	int error;

	if (sc == NULL || sc->sc_dying)
		return (EIO);

	sc->sc_refcnt++;
	error = ucom_do_ioctl(sc, cmd, data, flag, l);
	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);
	return (error);
}
Exemplo n.º 9
0
Static void
url_txeof(usbd_xfer_handle xfer, usbd_private_handle priv,
    usbd_status status)
{
	struct url_chain *c = priv;
	struct url_softc *sc = c->url_sc;
	struct ifnet *ifp = GET_IFP(sc);
	int s;

	if (sc->sc_dying)
		return;

	s = splnet();

	DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));

	ifp->if_timer = 0;
	ifp->if_flags &= ~IFF_OACTIVE;

	if (status != USBD_NORMAL_COMPLETION) {
		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
			splx(s);
			return;
		}
		ifp->if_oerrors++;
		printf("%s: usb error on tx: %s\n", device_xname(sc->sc_dev),
		       usbd_errstr(status));
		if (status == USBD_STALLED) {
			sc->sc_refcnt++;
			usbd_clear_endpoint_stall_async(sc->sc_pipe_tx);
			if (--sc->sc_refcnt < 0)
				usb_detach_wakeupold(sc->sc_dev);
		}
		splx(s);
		return;
	}

	ifp->if_opackets++;

	m_freem(c->url_mbuf);
	c->url_mbuf = NULL;

	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
		url_start(ifp);

	splx(s);
}
Exemplo n.º 10
0
Static int
url_send(struct url_softc *sc, struct mbuf *m, int idx)
{
	int total_len;
	struct url_chain *c;
	usbd_status err;

	DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev),__func__));

	c = &sc->sc_cdata.url_tx_chain[idx];

	/* Copy the mbuf data into a contiguous buffer */
	m_copydata(m, 0, m->m_pkthdr.len, c->url_buf);
	c->url_mbuf = m;
	total_len = m->m_pkthdr.len;

	if (total_len < URL_MIN_FRAME_LEN) {
		memset(c->url_buf + total_len, 0,
		    URL_MIN_FRAME_LEN - total_len);
		total_len = URL_MIN_FRAME_LEN;
	}
	usbd_setup_xfer(c->url_xfer, sc->sc_pipe_tx, c, c->url_buf, total_len,
			USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
			URL_TX_TIMEOUT, url_txeof);

	/* Transmit */
	sc->sc_refcnt++;
	err = usbd_transfer(c->url_xfer);
	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);
	if (err != USBD_IN_PROGRESS) {
		printf("%s: url_send error=%s\n", device_xname(sc->sc_dev),
		       usbd_errstr(err));
		/* Stop the interface */
		usb_add_task(sc->sc_udev, &sc->sc_stop_task,
		    USB_TASKQ_DRIVER);
		return (EIO);
	}

	DPRINTF(("%s: %s: send %d bytes\n", device_xname(sc->sc_dev),
		 __func__, total_len));

	sc->sc_cdata.url_tx_cnt++;

	return (0);
}
Exemplo n.º 11
0
int
ucomwrite(dev_t dev, struct uio *uio, int flag)
{
	struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
	struct tty *tp;
	int error;

	if (sc == NULL || sc->sc_dying)
		return (EIO);

	tp = sc->sc_tty;

	sc->sc_refcnt++;
	error = ((*tp->t_linesw->l_write)(tp, uio, flag));
	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);
	return (error);
}
Exemplo n.º 12
0
int
ucompoll(dev_t dev, int events, struct lwp *l)
{
	struct ucom_softc *sc;
	struct tty *tp;
	int revents;

	sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
	if (sc == NULL || sc->sc_dying)
		return (POLLHUP);

	tp = sc->sc_tty;

	sc->sc_refcnt++;
	revents = ((*tp->t_linesw->l_poll)(tp, events, l));
	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);
	return (revents);
}
Exemplo n.º 13
0
int
ucomclose(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
	struct tty *tp;
	int s;

	DPRINTF(("ucomclose: unit=%d\n", UCOMUNIT(dev)));

	if (sc == NULL)
		return 0;

	tp = sc->sc_tty;

	if (!ISSET(tp->t_state, TS_ISOPEN))
		return (0);

	s = spltty();
	sc->sc_refcnt++;

	(*tp->t_linesw->l_close)(tp, flag);
	ttyclose(tp);

	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
		/*
		 * Although we got a last close, the device may still be in
		 * use; e.g. if this was the dialout node, and there are still
		 * processes waiting for carrier on the non-dialout node.
		 */
		ucom_cleanup(sc);
	}

	if (sc->sc_methods->ucom_close != NULL)
		sc->sc_methods->ucom_close(sc->sc_parent, sc->sc_portno);

	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);
	splx(s);

	return (0);
}
Exemplo n.º 14
0
int
umass_scsi_attach(struct umass_softc *sc)
{
	struct umass_scsipi_softc *scbus;

	scbus = umass_scsipi_setup(sc);

	scbus->sc_channel.chan_bustype = &scsi_bustype;
	scbus->sc_channel.chan_ntargets = 2;
	scbus->sc_channel.chan_nluns = sc->maxlun + 1;
	scbus->sc_channel.chan_id = scbus->sc_channel.chan_ntargets - 1;
	DPRINTF(UDMASS_USB, ("%s: umass_attach_bus: SCSI\n",
			     device_xname(sc->sc_dev)));

	sc->sc_refcnt++;
	scbus->base.sc_child =
	    config_found_ia(sc->sc_dev, "scsi", &scbus->sc_channel,
		scsiprint);
	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);

	return (0);
}
Exemplo n.º 15
0
static void
udsir_thread(void *arg)
{
	struct udsir_softc *sc = arg;
	int error;

	DPRINTFN(20, ("%s: starting polling thread\n", __func__));

	while (!sc->sc_closing) {
		if (!sc->sc_rd_readinprogress && !UDSIR_BLOCK_RX_DATA(sc))
			udsir_periodic(sc);

		if (!sc->sc_closing) {
			error = tsleep(&sc->sc_thread, PWAIT, "udsir", hz / 10);
			if (error == EWOULDBLOCK &&
			    sc->sc_rd_expectdataticks > 0)
				/*
				 * After a timeout decrement the tick
				 * counter within which time we expect
				 * data to arrive if we are receiving
				 * data...
				 */
				sc->sc_rd_expectdataticks--;
		}
	}

	DPRINTFN(20, ("%s: exiting polling thread\n", __func__));

	sc->sc_thread = NULL;

	wakeup(&sc->sc_closing);

	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);

	kthread_exit(0);
}
Exemplo n.º 16
0
/* read/write memory */
Static int
url_mem(struct url_softc *sc, int cmd, int offset, void *buf, int len)
{
	usb_device_request_t req;
	usbd_status err;

	if (sc == NULL)
		return (0);

	DPRINTFN(0x200,
		("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));

	if (sc->sc_dying)
		return (0);

	if (cmd == URL_CMD_READMEM)
		req.bmRequestType = UT_READ_VENDOR_DEVICE;
	else
		req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
	req.bRequest = URL_REQ_MEM;
	USETW(req.wValue, offset);
	USETW(req.wIndex, 0x0000);
	USETW(req.wLength, len);

	sc->sc_refcnt++;
	err = usbd_do_request(sc->sc_udev, &req, buf);
	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);
	if (err) {
		DPRINTF(("%s: url_mem(): %s failed. off=%04x, err=%d\n",
			 device_xname(sc->sc_dev),
			 cmd == URL_CMD_READMEM ? "read" : "write",
			 offset, err));
	}

	return (err);
}
Exemplo n.º 17
0
Static int
url_openpipes(struct url_softc *sc)
{
	struct url_chain *c;
	usbd_status err;
	int i;
	int error = 0;

	if (sc->sc_dying)
		return (EIO);

	sc->sc_refcnt++;

	/* Open RX pipe */
	err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkin_no,
			     USBD_EXCLUSIVE_USE, &sc->sc_pipe_rx);
	if (err) {
		printf("%s: open rx pipe failed: %s\n",
		       device_xname(sc->sc_dev), usbd_errstr(err));
		error = EIO;
		goto done;
	}

	/* Open TX pipe */
	err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkout_no,
			     USBD_EXCLUSIVE_USE, &sc->sc_pipe_tx);
	if (err) {
		printf("%s: open tx pipe failed: %s\n",
		       device_xname(sc->sc_dev), usbd_errstr(err));
		error = EIO;
		goto done;
	}

#if 0
	/* XXX: interrupt endpoint is not yet supported */
	/* Open Interrupt pipe */
	err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_intrin_no,
				  USBD_EXCLUSIVE_USE, &sc->sc_pipe_intr, sc,
				  &sc->sc_cdata.url_ibuf, URL_INTR_PKGLEN,
				  url_intr, USBD_DEFAULT_INTERVAL);
	if (err) {
		printf("%s: open intr pipe failed: %s\n",
		       device_xname(sc->sc_dev), usbd_errstr(err));
		error = EIO;
		goto done;
	}
#endif


	/* Start up the receive pipe. */
	for (i = 0; i < URL_RX_LIST_CNT; i++) {
		c = &sc->sc_cdata.url_rx_chain[i];
		usbd_setup_xfer(c->url_xfer, sc->sc_pipe_rx,
				c, c->url_buf, URL_BUFSZ,
				USBD_SHORT_XFER_OK | USBD_NO_COPY,
				USBD_NO_TIMEOUT, url_rxeof);
		(void)usbd_transfer(c->url_xfer);
		DPRINTF(("%s: %s: start read\n", device_xname(sc->sc_dev),
			 __func__));
	}

 done:
	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);

	return (error);
}
Exemplo n.º 18
0
/* ARGSUSED */
static int
udsir_write(void *h, struct uio *uio, int flag)
{
	struct udsir_softc *sc = h;
	usbd_status err;
	uint32_t wrlen;
	int error, sirlength;
	uint8_t *wrbuf;
	int s;

	DPRINTFN(1, ("%s: sc=%p\n", __func__, sc));

	if (sc->sc_dying)
		return EIO;

#ifdef DIAGNOSTIC
	if (sc->sc_wr_buf == NULL)
		return EINVAL;
#endif

	wrlen = uio->uio_resid;
	if (wrlen > sc->sc_wr_maxpsz)
		return EINVAL;

	sc->sc_refcnt++;

	if (!UDSIR_BLOCK_RX_DATA(sc)) {
		/*
		 * If reads are not blocked, determine what action we
		 * should potentially take...
		 */
		if (sc->sc_direction == udir_output) {
			/*
			 * If the last operation was an output, wait for the
			 * polling thread to check for incoming data.
			 */
			sc->sc_wr_stalewrite = 1;
			wakeup(&sc->sc_thread);
		} else if (!sc->sc_rd_readinprogress &&
			   (sc->sc_direction == udir_idle ||
			    sc->sc_direction == udir_input)) {
			/* If idle, check for input before outputting */
			udsir_start_read(sc);
		}
	}

	s = splusb();
	while (sc->sc_wr_stalewrite ||
	       (sc->sc_direction != udir_output &&
		sc->sc_direction != udir_idle)) {
		DPRINTFN(5, ("%s: sc=%p stalewrite=%d direction=%d, "
			     "calling tsleep()\n",
			     __func__, sc, sc->sc_wr_stalewrite,
			     sc->sc_direction));
		error = tsleep(&sc->sc_wr_buf, PZERO | PCATCH, "usirwr", 0);
		if (sc->sc_dying)
			error = EIO;
		if (error) {
			splx(s);
			DPRINTFN(0, ("%s: tsleep() = %d\n", __func__, error));
			goto ret;
		}
	}
	splx(s);

	wrbuf = sc->sc_wr_buf;

	sirlength = irda_sir_frame(wrbuf, MAX_UDSIR_OUTPUT_FRAME,
	    uio, sc->sc_params.ebofs);
	if (sirlength < 0)
		error = -sirlength;
	else {
		uint32_t btlen;

		DPRINTFN(1, ("%s: transfer %u bytes\n",
			     __func__, (unsigned int)wrlen));

		btlen = sirlength;

		sc->sc_direction = udir_output;

#ifdef UDSIR_DEBUG
		if (udsirdebug >= 20)
			udsir_dumpdata(wrbuf, btlen, __func__);
#endif

		err = usbd_intr_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe,
		     USBD_FORCE_SHORT_XFER, UDSIR_WR_TIMEOUT,
		     wrbuf, &btlen);
		DPRINTFN(2, ("%s: err=%d\n", __func__, err));
		if (err != USBD_NORMAL_COMPLETION) {
			if (err == USBD_INTERRUPTED)
				error = EINTR;
			else if (err == USBD_TIMEOUT)
				error = ETIMEDOUT;
			else
				error = EIO;
		} else
			error = 0;
	}

 ret:
	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);

	DPRINTFN(1, ("%s: sc=%p done\n", __func__, sc));
	return error;
}
Exemplo n.º 19
0
/* ARGSUSED */
static int
udsir_read(void *h, struct uio *uio, int flag)
{
	struct udsir_softc *sc = h;
	int s;
	int error;
	u_int uframelen;

	DPRINTFN(1, ("%s: sc=%p\n", __func__, sc));

	if (sc->sc_dying)
		return EIO;

#ifdef DIAGNOSTIC
	if (sc->sc_rd_buf == NULL)
		return EINVAL;
#endif

	sc->sc_refcnt++;

	if (!sc->sc_rd_readinprogress && !UDSIR_BLOCK_RX_DATA(sc))
		/* Possibly wake up polling thread */
		wakeup(&sc->sc_thread);

	do {
		s = splusb();
		while (sc->sc_ur_framelen == 0) {
			DPRINTFN(5, ("%s: calling tsleep()\n", __func__));
			error = tsleep(&sc->sc_ur_framelen, PZERO | PCATCH,
				       "usirrd", 0);
			if (sc->sc_dying)
				error = EIO;
			if (error) {
				splx(s);
				DPRINTFN(0, ("%s: tsleep() = %d\n",
					     __func__, error));
				goto ret;
			}
		}
		splx(s);

		uframelen = sc->sc_ur_framelen;
		DPRINTFN(1, ("%s: sc=%p framelen=%u, hdr=0x%02x\n",
			     __func__, sc, uframelen, sc->sc_ur_buf[0]));
		if (uframelen > uio->uio_resid)
			error = EINVAL;
		else
			error = uiomove(sc->sc_ur_buf, uframelen, uio);
		sc->sc_ur_framelen = 0;

		if (deframe_rd_ur(sc) == 0 && uframelen > 0) {
			/*
			 * Need to wait for another read to obtain a
			 * complete frame...  If we also obtained
			 * actual data, wake up the possibly sleeping
			 * thread immediately...
			 */
			wakeup(&sc->sc_thread);
		}
	} while (uframelen == 0);

	DPRINTFN(1, ("%s: return %d\n", __func__, error));

 ret:
	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);
	return error;
}
Exemplo n.º 20
0
int
urioioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
{
	struct urio_softc * sc;
	int unit = URIOUNIT(dev);
	struct urio_command *rcmd;
	int requesttype, len;
	struct iovec iov;
	struct uio uio;
	usb_device_request_t req;
	usbd_status err;
	int req_flags = 0;
	u_int32_t req_actlen = 0;
	void *ptr = NULL;
	int error = 0;

	sc = device_lookup_private(&urio_cd, unit);

	if (sc->sc_dying)
		return (EIO);

	rcmd = (struct urio_command *)addr;

	switch (cmd) {
	case URIO_RECV_COMMAND:
		requesttype = rcmd->requesttype | UT_READ_VENDOR_DEVICE;
		break;

	case URIO_SEND_COMMAND:
		requesttype = rcmd->requesttype | UT_WRITE_VENDOR_DEVICE;
		break;

	default:
		return (EINVAL);
		break;
	}

	if (!(flag & FWRITE))
		return (EPERM);
	len = rcmd->length;

	DPRINTFN(1,("urio_ioctl: cmd=0x%08lx reqtype=0x%0x req=0x%0x "
		    "value=0x%0x index=0x%0x len=0x%0x\n",
		    cmd, requesttype, rcmd->request, rcmd->value,
		    rcmd->index, len));

	/* Send rio control message */
	req.bmRequestType = requesttype;
	req.bRequest = rcmd->request;
	USETW(req.wValue, rcmd->value);
	USETW(req.wIndex, rcmd->index);
	USETW(req.wLength, len);

	if (len < 0 || len > 32767)
		return (EINVAL);
	if (len != 0) {
		iov.iov_base = (void *)rcmd->buffer;
		iov.iov_len = len;
		uio.uio_iov = &iov;
		uio.uio_iovcnt = 1;
		uio.uio_resid = len;
		uio.uio_offset = 0;
		uio.uio_rw = req.bmRequestType & UT_READ ?
			     UIO_READ : UIO_WRITE;
		uio.uio_vmspace = l->l_proc->p_vmspace;
		ptr = malloc(len, M_TEMP, M_WAITOK);
		if (uio.uio_rw == UIO_WRITE) {
			error = uiomove(ptr, len, &uio);
			if (error)
				goto ret;
		}
	}

	sc->sc_refcnt++;

	err = usbd_do_request_flags(sc->sc_udev, &req, ptr, req_flags,
		  &req_actlen, USBD_DEFAULT_TIMEOUT);

	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);

	if (err) {
		error = EIO;
	} else {
		if (len != 0 && uio.uio_rw == UIO_READ)
			error = uiomove(ptr, len, &uio);
	}

ret:
	if (ptr != NULL)
		free(ptr, M_TEMP);
	return (error);
}
Exemplo n.º 21
0
Static void
url_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
{
	struct url_chain *c = priv;
	struct url_softc *sc = c->url_sc;
	struct ifnet *ifp = GET_IFP(sc);
	struct mbuf *m;
	u_int32_t total_len;
	url_rxhdr_t rxhdr;
	int s;

	DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev),__func__));

	if (sc->sc_dying)
		return;

	if (status != USBD_NORMAL_COMPLETION) {
		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
			return;
		sc->sc_rx_errs++;
		if (usbd_ratecheck(&sc->sc_rx_notice)) {
			printf("%s: %u usb errors on rx: %s\n",
			       device_xname(sc->sc_dev), sc->sc_rx_errs,
			       usbd_errstr(status));
			sc->sc_rx_errs = 0;
		}
		if (status == USBD_STALLED) {
			sc->sc_refcnt++;
			usbd_clear_endpoint_stall_async(sc->sc_pipe_rx);
			if (--sc->sc_refcnt < 0)
				usb_detach_wakeupold(sc->sc_dev);
		}
		goto done;
	}

	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);

	memcpy(mtod(c->url_mbuf, char *), c->url_buf, total_len);

	if (total_len <= ETHER_CRC_LEN) {
		ifp->if_ierrors++;
		goto done;
	}

	memcpy(&rxhdr, c->url_buf + total_len - ETHER_CRC_LEN, sizeof(rxhdr));

	DPRINTF(("%s: RX Status: %dbytes%s%s%s%s packets\n",
		 device_xname(sc->sc_dev),
		 UGETW(rxhdr) & URL_RXHDR_BYTEC_MASK,
		 UGETW(rxhdr) & URL_RXHDR_VALID_MASK ? ", Valid" : "",
		 UGETW(rxhdr) & URL_RXHDR_RUNTPKT_MASK ? ", Runt" : "",
		 UGETW(rxhdr) & URL_RXHDR_PHYPKT_MASK ? ", Physical match" : "",
		 UGETW(rxhdr) & URL_RXHDR_MCASTPKT_MASK ? ", Multicast" : ""));

	if ((UGETW(rxhdr) & URL_RXHDR_VALID_MASK) == 0) {
		ifp->if_ierrors++;
		goto done;
	}

	ifp->if_ipackets++;
	total_len -= ETHER_CRC_LEN;

	m = c->url_mbuf;
	m->m_pkthdr.len = m->m_len = total_len;
	m->m_pkthdr.rcvif = ifp;

	s = splnet();

	if (url_newbuf(sc, c, NULL) == ENOBUFS) {
		ifp->if_ierrors++;
		goto done1;
	}

	bpf_mtap(ifp, m);

	DPRINTF(("%s: %s: deliver %d\n", device_xname(sc->sc_dev),
		 __func__, m->m_len));
	(*(ifp)->if_input)((ifp), (m));

 done1:
	splx(s);

 done:
	/* Setup new transfer */
	usbd_setup_xfer(xfer, sc->sc_pipe_rx, c, c->url_buf, URL_BUFSZ,
			USBD_SHORT_XFER_OK | USBD_NO_COPY,
			USBD_NO_TIMEOUT, url_rxeof);
	sc->sc_refcnt++;
	usbd_transfer(xfer);
	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);

	DPRINTF(("%s: %s: start rx\n", device_xname(sc->sc_dev), __func__));
}