예제 #1
0
static int
kue_send(struct kue_softc *sc, struct mbuf *m, int idx)
{
	int			total_len;
	struct kue_chain	*c;
	usbd_status		err;

	DPRINTFN(10,("%s: %s: enter\n", device_xname(sc->kue_dev),__func__));

	c = &sc->kue_cdata.kue_tx_chain[idx];

	/* Frame length is specified in the first 2 bytes of the buffer. */
	le16enc(c->kue_buf, (uint16_t)m->m_pkthdr.len);

	/*
	 * Copy the mbuf data into a contiguous buffer, leaving two
	 * bytes at the beginning to hold the frame length.
	 */
	m_copydata(m, 0, m->m_pkthdr.len, c->kue_buf + 2);

	total_len = 2 + m->m_pkthdr.len;
	total_len = roundup2(total_len, 64);

	usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_TX],
	    c, c->kue_buf, total_len, USBD_NO_COPY, USBD_DEFAULT_TIMEOUT,
	    kue_txeof);

	/* Transmit */
	err = usbd_transfer(c->kue_xfer);
	if (err != USBD_IN_PROGRESS) {
		printf("%s: kue_send error=%s\n", device_xname(sc->kue_dev),
		       usbd_errstr(err));
		kue_stop(sc);
		return (EIO);
	}

	sc->kue_cdata.kue_tx_cnt++;

	return (0);
}
예제 #2
0
int
kue_open_pipes(struct kue_softc *sc)
{
	usbd_status		err;
	struct kue_chain	*c;
	int			i;

	DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));

	/* Open RX and TX pipes. */
	err = usbd_open_pipe(sc->kue_iface, sc->kue_ed[KUE_ENDPT_RX],
	    USBD_EXCLUSIVE_USE, &sc->kue_ep[KUE_ENDPT_RX]);
	if (err) {
		printf("%s: open rx pipe failed: %s\n",
		    sc->kue_dev.dv_xname, usbd_errstr(err));
		return (EIO);
	}

	err = usbd_open_pipe(sc->kue_iface, sc->kue_ed[KUE_ENDPT_TX],
	    USBD_EXCLUSIVE_USE, &sc->kue_ep[KUE_ENDPT_TX]);
	if (err) {
		printf("%s: open tx pipe failed: %s\n",
		    sc->kue_dev.dv_xname, usbd_errstr(err));
		return (EIO);
	}

	/* Start up the receive pipe. */
	for (i = 0; i < KUE_RX_LIST_CNT; i++) {
		c = &sc->kue_cdata.kue_rx_chain[i];
		usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_RX],
		    c, c->kue_buf, KUE_BUFSZ,
		    USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
		    kue_rxeof);
		DPRINTFN(5,("%s: %s: start read\n", sc->kue_dev.dv_xname,
			    __func__));
		usbd_transfer(c->kue_xfer);
	}

	return (0);
}
예제 #3
0
/* General CDC asynchronous transfer function */
static jresult_t cdc_async_transfer(cdc_cmd_priv_t *priv, 
    usbd_pipe_handle pipe, void *membuf, juint32_t size, 
    usbd_xfer_handle xfer)
{
    jresult_t rc;
    usbd_status status;
    juint16_t flags = USBD_SHORT_XFER_OK | USBD_FORCE_SHORT_XFER;
    DECLARE_FNAME("cdc_async_transfer");
    
    DBG_X(DHOST_CDC_GENERAL, ("%s: Entered\n", fname));

    /* Allocate a transfer request object and set up a xfer */
    xfer = usbd_alloc_xfer(priv->sc->device);
    if (!xfer)
    {
        DBG_E(DHOST_CDC_GENERAL, ("%s: Failed to allocate xfer\n", fname));
        rc = JENOMEM;
        goto Error;
    }
    usbd_setup_xfer(xfer, pipe, (void *)priv, membuf, size, flags, 
        CDC_DATA_XFER_TIMEOUT, cdc_data_xfer_complete);

    /* Execute xfer */
    status = usbd_transfer(xfer);
    if (status && status != USBD_IN_PROGRESS) 
    {
        DBG_W(DHOST_CDC_GENERAL, ("%s: failed to setup transfer, %s\n", fname, 
            usbd_errstr(status)));
        rc = status_to_result(status);
        goto Error;
    }
    return 0;

Error:
    if (xfer)
        usbd_free_xfer(xfer);

    return rc;
}
예제 #4
0
파일: udsir.c 프로젝트: ryo/netbsd-src
static usbd_status
udsir_start_read(struct udsir_softc *sc)
{
	usbd_status err;

	DPRINTFN(60, ("%s: sc=%p, size=%d\n", __func__, sc, sc->sc_rd_maxpsz));

	if (sc->sc_dying)
		return USBD_IOERROR;

	if (UDSIR_BLOCK_RX_DATA(sc) || deframe_rd_ur(sc)) {
		/*
		 * Can't start reading just yet.  Since we aren't
		 * going to start a read, have to switch direction to
		 * idle.
		 */
		sc->sc_direction = udir_idle;
		return USBD_NORMAL_COMPLETION;
	}

	/* Starting a read... */
	sc->sc_rd_readinprogress = 1;
	sc->sc_direction = udir_input;

	if (sc->sc_rd_err) {
		sc->sc_rd_err = 0;
		DPRINTFN(0, ("%s: clear stall\n", __func__));
		usbd_clear_endpoint_stall(sc->sc_rd_pipe);
	}

	usbd_setup_xfer(sc->sc_rd_xfer, sc, sc->sc_rd_buf, sc->sc_rd_maxpsz,
	    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, udsir_rd_cb);
	err = usbd_transfer(sc->sc_rd_xfer);
	if (err != USBD_IN_PROGRESS) {
		DPRINTFN(0, ("%s: err=%d\n", __func__, (int)err));
		return err;
	}
	return USBD_NORMAL_COMPLETION;
}
예제 #5
0
void
ubt_recv_acl_start(struct ubt_softc *sc)
{
	usbd_status status;

	DPRINTFN(15, "sc=%p\n", sc);

	if (sc->sc_aclrd_busy || sc->sc_dying) {
		DPRINTF("sc_aclrd_busy=%d, sc_dying=%d\n",
			sc->sc_aclrd_busy,
			sc->sc_dying);

		return;
	}

	sc->sc_refcnt++;
	sc->sc_aclrd_busy = 1;

	usbd_setup_xfer(sc->sc_aclrd_xfer,
			sc->sc_aclrd_pipe,
			sc,
			sc->sc_aclrd_buf,
			UBT_BUFSIZ_ACL,
			USBD_NO_COPY | USBD_SHORT_XFER_OK,
			USBD_NO_TIMEOUT,
			ubt_recv_acl_complete);

	status = usbd_transfer(sc->sc_aclrd_xfer);

	KKASSERT(status != USBD_NORMAL_COMPLETION);

	if (status != USBD_IN_PROGRESS) {
		DPRINTF("usbd_transfer status=%s (%d)\n",
			usbd_errstr(status), status);

		sc->sc_refcnt--;
		sc->sc_aclrd_busy = 0;
	}
}
예제 #6
0
/*
 * Start transfer from internal queue
 */
static int
lgue_start_transfer(struct lgue_softc *sc) {
	usbd_status err;
	struct lgue_queue_entry *entry;
	struct ifnet *ifp;

	if (STAILQ_EMPTY(&sc->lgue_tx_queue))
		return(0);

	ifp = &sc->lgue_arpcom.ac_if;
	entry = STAILQ_FIRST(&sc->lgue_tx_queue);
	STAILQ_REMOVE_HEAD(&sc->lgue_tx_queue, entry_next);

	m_copydata(entry->entry_mbuf, 0, entry->entry_mbuf->m_pkthdr.len,
	    sc->lgue_tx_buf);

	/* Transmit */
	usbd_setup_xfer(sc->lgue_tx_xfer, sc->lgue_ep[LGUE_ENDPT_TX], sc,
	    sc->lgue_tx_buf, entry->entry_mbuf->m_pkthdr.len,
	    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, lgue_txeof);
	err = usbd_transfer(sc->lgue_tx_xfer);
	if (err != USBD_IN_PROGRESS) {
		m_freem(entry->entry_mbuf);
		kfree(entry, M_USBDEV);
		lgue_stop(sc);
		ifq_clr_oactive(&ifp->if_snd);
		return(EIO);
	}

	m_freem(entry->entry_mbuf);
	kfree(entry, M_USBDEV);

	sc->lgue_tx_cnt++;
	ifq_set_oactive(&ifp->if_snd);
	ifp->if_timer = 5;
	return(0);
}
예제 #7
0
파일: emdtv_dtv.c 프로젝트: ryo/netbsd-src
static int
emdtv_dtv_isoc_start(struct emdtv_softc *sc, struct emdtv_isoc_xfer *ix)
{
	int i;

	if (sc->sc_isoc_pipe == NULL)
		return EIO;

	for (i = 0; i < EMDTV_NFRAMES; i++)
		ix->ix_frlengths[i] = sc->sc_isoc_maxpacketsize;

	usbd_setup_isoc_xfer(ix->ix_xfer,
			     ix,
			     ix->ix_frlengths,
			     EMDTV_NFRAMES,
			     USBD_SHORT_XFER_OK,
			     emdtv_dtv_isoc);

	KERNEL_LOCK(1, curlwp);
	usbd_transfer(ix->ix_xfer);
	KERNEL_UNLOCK_ONE(curlwp);

	return 0;
}
예제 #8
0
int
wi_usb_open_pipes(struct wi_usb_softc *sc)
{
	usbd_status		err;
	int			error = 0;
	struct wi_usb_chain	*c;
	int			i;

	DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname,__func__));

	sc->wi_usb_refcnt++;

	/* Open RX and TX pipes. */
	err = usbd_open_pipe(sc->wi_usb_iface, sc->wi_usb_ed[WI_USB_ENDPT_RX],
	    USBD_EXCLUSIVE_USE, &sc->wi_usb_ep[WI_USB_ENDPT_RX]);
	if (err) {
		printf("%s: open rx pipe failed: %s\n",
		    sc->wi_usb_dev.dv_xname, usbd_errstr(err));
		error = EIO;
		goto done;
	}

	err = usbd_open_pipe(sc->wi_usb_iface, sc->wi_usb_ed[WI_USB_ENDPT_TX],
	    USBD_EXCLUSIVE_USE, &sc->wi_usb_ep[WI_USB_ENDPT_TX]);
	if (err) {
		printf("%s: open tx pipe failed: %s\n",
		    sc->wi_usb_dev.dv_xname, usbd_errstr(err));
		error = EIO;
		goto done;
	}

	/* is this used? */
	err = usbd_open_pipe_intr(sc->wi_usb_iface,
	    sc->wi_usb_ed[WI_USB_ENDPT_INTR], USBD_EXCLUSIVE_USE,
	    &sc->wi_usb_ep[WI_USB_ENDPT_INTR], sc, &sc->wi_usb_ibuf,
	    WI_USB_INTR_PKTLEN, wi_usb_intr, WI_USB_INTR_INTERVAL);
	if (err) {
		printf("%s: open intr pipe failed: %s\n",
		    sc->wi_usb_dev.dv_xname, usbd_errstr(err));
		error = EIO;
		goto done;
	}

	/* Start up the receive pipe. */
	for (i = 0; i < WI_USB_RX_LIST_CNT; i++) {
		c = &sc->wi_usb_rx_chain[i];
		usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_RX],
		    c, c->wi_usb_buf, WI_USB_BUFSZ,
		    USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
		    wi_usb_rxeof);
		DPRINTFN(10,("%s: %s: start read\n", sc->wi_usb_dev.dv_xname,
			    __func__));
		usbd_transfer(c->wi_usb_xfer);
	}

done:
	if (--sc->wi_usb_refcnt < 0)
		usb_detach_wakeup(&sc->wi_usb_dev);

	return (error);
}
예제 #9
0
static int
uticom_download_fw(struct uticom_softc *sc, int pipeno,
    struct usbd_device *dev)
{
	u_char *obuf, *firmware;
	size_t firmware_size;
	int buffer_size, pos;
	uint8_t cs = 0, *buffer;
	usbd_status err;
	struct uticom_fw_header *header;
	struct usbd_xfer *oxfer = 0;
	usbd_status error = 0;
	struct usbd_pipe *pipe;

	error = loadfirmware("tusb3410", &firmware, &firmware_size);
	if (error)
		return (error);

	buffer_size = UTICOM_FW_BUFSZ + sizeof(struct uticom_fw_header);
	buffer = malloc(buffer_size, M_USBDEV, M_WAITOK | M_CANFAIL);

	if (!buffer) {
		printf("%s: uticom_download_fw: out of memory\n",
		    sc->sc_dev.dv_xname);
		free(firmware, M_DEVBUF);
		return ENOMEM;
	}

	memcpy(buffer, firmware, firmware_size);
	memset(buffer + firmware_size, 0xff, buffer_size - firmware_size);

	for (pos = sizeof(struct uticom_fw_header); pos < buffer_size; pos++)
		cs = (uint8_t)(cs + buffer[pos]);

	header = (struct uticom_fw_header*)buffer;
	header->length = (uint16_t)(buffer_size -
	    sizeof(struct uticom_fw_header));
	header->checkSum = cs;

	DPRINTF(("%s: downloading firmware ...\n",
	    sc->sc_dev.dv_xname));

	err = usbd_open_pipe(sc->sc_iface, pipeno, USBD_EXCLUSIVE_USE,
	    &pipe);
	if (err) {
		printf("%s: open bulk out error (addr %d): %s\n",
		    sc->sc_dev.dv_xname, pipeno, usbd_errstr(err));
		error = EIO;
		goto finish;
	}

	oxfer = usbd_alloc_xfer(dev);
	if (oxfer == NULL) {
		error = ENOMEM;
		goto finish;
	}

	obuf = usbd_alloc_buffer(oxfer, buffer_size);
	if (obuf == NULL) {
		error = ENOMEM;
		goto finish;
	}

	memcpy(obuf, buffer, buffer_size);

	usbd_setup_xfer(oxfer, pipe, (void *)sc, obuf, buffer_size,
	    USBD_NO_COPY | USBD_SYNCHRONOUS, USBD_NO_TIMEOUT, 0);
	err = usbd_transfer(oxfer);

	if (err != USBD_NORMAL_COMPLETION)
		printf("%s: uticom_download_fw: error: %s\n",
		    sc->sc_dev.dv_xname, usbd_errstr(err));

finish:
	free(firmware, M_DEVBUF);
	usbd_free_buffer(oxfer);
	usbd_free_xfer(oxfer);
	oxfer = NULL;
	usbd_abort_pipe(pipe);
	usbd_close_pipe(pipe);
	free(buffer, M_USBDEV);
	return err;
}
예제 #10
0
usbd_status
umsm_umass_changemode(struct umsm_softc *sc)
{
#define UMASS_CMD_REZERO_UNIT		0x01
#define UMASS_CMD_START_STOP		0x1b
#define UMASS_CMDPARAM_EJECT		0x02
#define UMASS_SERVICE_ACTION_OUT	0x9f
	usb_interface_descriptor_t *id;
	usb_endpoint_descriptor_t *ed;
	struct usbd_xfer *xfer;
	struct usbd_pipe *cmdpipe;
	usbd_status err;
	u_int32_t n;
	void *bufp;
	int target_ep, i;

	struct umass_bbb_cbw cbw;
	static int dCBWTag = 0x12345678;

	USETDW(cbw.dCBWSignature, CBWSIGNATURE);
	USETDW(cbw.dCBWTag, dCBWTag);
	cbw.bCBWLUN   = 0;
	cbw.bCDBLength= 6;
	bzero(cbw.CBWCDB, sizeof(cbw.CBWCDB));

	switch (sc->sc_flag) {
	case DEV_UMASS1:
		USETDW(cbw.dCBWDataTransferLength, 0x0);
		cbw.bCBWFlags = CBWFLAGS_OUT;
		cbw.CBWCDB[0] = UMASS_CMD_REZERO_UNIT;
		cbw.CBWCDB[1] = 0x0;	/* target LUN: 0 */
		break;
	case DEV_UMASS2:
		USETDW(cbw.dCBWDataTransferLength, 0x1);
		cbw.bCBWFlags = CBWFLAGS_IN;
		cbw.CBWCDB[0] = UMASS_CMD_REZERO_UNIT;
		cbw.CBWCDB[1] = 0x0;	/* target LUN: 0 */
		break;
	case DEV_UMASS3: /* longcheer */
		USETDW(cbw.dCBWDataTransferLength, 0x80);
		cbw.bCBWFlags = CBWFLAGS_IN;
		cbw.CBWCDB[0] = 0x06;
		cbw.CBWCDB[1] = 0xf5;
		cbw.CBWCDB[2] = 0x04;
		cbw.CBWCDB[3] = 0x02;
		cbw.CBWCDB[4] = 0x52;
		cbw.CBWCDB[5] = 0x70;
		break;
	case DEV_UMASS4:
		USETDW(cbw.dCBWDataTransferLength, 0x0);
		cbw.bCBWFlags = CBWFLAGS_OUT;
		cbw.CBWCDB[0] = UMASS_CMD_START_STOP;
		cbw.CBWCDB[1] = 0x00;	/* target LUN: 0 */
		cbw.CBWCDB[4] = UMASS_CMDPARAM_EJECT;
		break;
	case DEV_UMASS5:
		cbw.bCBWFlags = CBWFLAGS_OUT;
		cbw.CBWCDB[0] = 0x11;
		cbw.CBWCDB[1] = 0x06;
		break;
	case DEV_UMASS6:	/* ZTE */
		USETDW(cbw.dCBWDataTransferLength, 0x20);
		cbw.bCBWFlags = CBWFLAGS_IN;
		cbw.bCDBLength= 12;
		cbw.CBWCDB[0] = 0x85;
		cbw.CBWCDB[1] = 0x01;
		cbw.CBWCDB[2] = 0x01;
		cbw.CBWCDB[3] = 0x01;
		cbw.CBWCDB[4] = 0x18;
		cbw.CBWCDB[5] = 0x01;
		cbw.CBWCDB[6] = 0x01;
		cbw.CBWCDB[7] = 0x01;
		cbw.CBWCDB[8] = 0x01;
		cbw.CBWCDB[9] = 0x01;
		break;
	case DEV_UMASS7:	/* ZTE */
		USETDW(cbw.dCBWDataTransferLength, 0xc0);
		cbw.bCBWFlags = CBWFLAGS_IN;
		cbw.CBWCDB[0] = UMASS_SERVICE_ACTION_OUT;
		cbw.CBWCDB[1] = 0x03;
		break;
	case DEV_UMASS8:
		USETDW(cbw.dCBWDataTransferLength, 0x0);
		cbw.bCBWFlags = CBWFLAGS_OUT;
		cbw.CBWCDB[0] = 0xf0;
		cbw.CBWCDB[1] = 0x01;
		cbw.CBWCDB[2] = 0x03;
		break;
	default:
		DPRINTF(("%s: unknown device type.\n", sc->sc_dev.dv_xname));
		break;
	}

	/* get command endpoint address */
	id = usbd_get_interface_descriptor(sc->sc_iface);
	for (i = 0; i < id->bNumEndpoints; i++) {
		ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
		if (ed == NULL) {
			return (USBD_IOERROR);
		}

		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
			target_ep = ed->bEndpointAddress;
	}

	/* open command endppoint */
	err = usbd_open_pipe(sc->sc_iface, target_ep,
		USBD_EXCLUSIVE_USE, &cmdpipe);
	if (err) {
		DPRINTF(("%s: open pipe for modem change cmd failed: %s\n",
		    sc->sc_dev.dv_xname, usbd_errstr(err)));
		return (err);
	}

	xfer = usbd_alloc_xfer(sc->sc_udev);
	if (xfer == NULL) {
		usbd_close_pipe(cmdpipe);
		return (USBD_NOMEM);
	} else {
		bufp = usbd_alloc_buffer(xfer, UMASS_BBB_CBW_SIZE);
		if (bufp == NULL)
			err = USBD_NOMEM;
		else {
			n = UMASS_BBB_CBW_SIZE;
			memcpy(bufp, &cbw, UMASS_BBB_CBW_SIZE);
			usbd_setup_xfer(xfer, cmdpipe, 0, bufp, n,
			    USBD_NO_COPY | USBD_SYNCHRONOUS, 0, NULL);
			err = usbd_transfer(xfer);
			if (err) {
				usbd_clear_endpoint_stall(cmdpipe);
				DPRINTF(("%s: send error:%s", __func__,
				    usbd_errstr(err)));
			}
		}
		usbd_close_pipe(cmdpipe);
		usbd_free_buffer(xfer);
		usbd_free_xfer(xfer);
	}

	return (err);
}
예제 #11
0
void
ubt_xmit_sco_start1(struct ubt_softc *sc, struct ubt_isoc_xfer *isoc)
{
	struct mbuf *m;
	uint8_t *buf;
	int num, len, size, space;

	if (sc->sc_dying)
		return;

	space = sc->sc_scowr_size * UBT_NFRAMES;
	buf = isoc->buf;
	len = 0;

	/*
	 * Fill the request buffer with data from the queue,
	 * keeping any leftover packet on our private hook.
	 *
	 * Complete packets are passed back up to the stack
	 * for disposal, since we can't rely on the controller
	 * to tell us when it has finished with them.
	 */

	m = sc->sc_scowr_mbuf;
	while (space > 0) {
		if (m == NULL) {
			crit_enter();
			IF_DEQUEUE(&sc->sc_scowr_queue, m);
			crit_exit();
			if (m == NULL)
				break;

			m_adj(m, 1);	/* packet type */

		}

		if (m->m_pkthdr.len > 0) {
			size = MIN(m->m_pkthdr.len, space);

			m_copydata(m, 0, size, buf);
			m_adj(m, size);

			buf += size;
			len += size;
			space -= size;
		}

		if (m->m_pkthdr.len == 0) {
			sc->sc_stats.sco_tx++;
			if (!hci_complete_sco(sc->sc_unit, m))
				sc->sc_stats.err_tx++;

			m = NULL;
		}
	}
	sc->sc_scowr_mbuf = m;

	DPRINTFN(15, "isoc=%p, len=%d, space=%d\n", isoc, len, space);

	if (len == 0)	/* nothing to send */
	
		return;

	sc->sc_refcnt++;
	sc->sc_scowr_busy = 1;
	sc->sc_stats.byte_tx += len;
	isoc->busy = 1;

	/*
	 * calculate number of isoc frames and sizes
	 */

	for (num = 0 ; len > 0 ; num++) {
		size = MIN(sc->sc_scowr_size, len);

		isoc->size[num] = size;
		len -= size;
	}

	usbd_setup_isoc_xfer(isoc->xfer,
			     sc->sc_scowr_pipe,
			     isoc,
			     isoc->size,
			     num,
			     USBD_NO_COPY | USBD_FORCE_SHORT_XFER,
			     ubt_xmit_sco_complete);

	usbd_transfer(isoc->xfer);
}
예제 #12
0
/*
 * A frame has been uploaded: pass the resulting mbuf chain up to
 * the higher level protocols.
 */
void
kue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
{
	struct kue_chain	*c = priv;
	struct kue_softc	*sc = c->kue_sc;
	struct ifnet		*ifp = GET_IFP(sc);
	struct mbuf		*m;
	int			total_len = 0;
	int			s;

	DPRINTFN(10,("%s: %s: enter status=%d\n", sc->kue_dev.dv_xname,
		     __func__, status));

	if (sc->kue_dying)
		return;

	if (!(ifp->if_flags & IFF_RUNNING))
		return;

	if (status != USBD_NORMAL_COMPLETION) {
		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
			return;
		sc->kue_rx_errs++;
		if (usbd_ratecheck(&sc->kue_rx_notice)) {
			printf("%s: %u usb errors on rx: %s\n",
			    sc->kue_dev.dv_xname, sc->kue_rx_errs,
			    usbd_errstr(status));
			sc->kue_rx_errs = 0;
		}
		if (status == USBD_STALLED)
			usbd_clear_endpoint_stall_async(sc->kue_ep[KUE_ENDPT_RX]);
		goto done;
	}

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

	DPRINTFN(10,("%s: %s: total_len=%d len=%d\n", sc->kue_dev.dv_xname,
		     __func__, total_len,
		     UGETW(mtod(c->kue_mbuf, u_int8_t *))));

	if (total_len <= 1)
		goto done;

	m = c->kue_mbuf;
	/* copy data to mbuf */
	memcpy(mtod(m, char *), c->kue_buf, total_len);

	/* No errors; receive the packet. */
	total_len = UGETW(mtod(m, u_int8_t *));
	m_adj(m, sizeof(u_int16_t));

	if (total_len < sizeof(struct ether_header)) {
		ifp->if_ierrors++;
		goto done;
	}

	ifp->if_ipackets++;
	m->m_pkthdr.len = m->m_len = total_len;

	m->m_pkthdr.rcvif = ifp;

	s = splnet();

	/* XXX ugly */
	if (kue_newbuf(sc, c, NULL) == ENOBUFS) {
		ifp->if_ierrors++;
		goto done1;
	}

#if NBPFILTER > 0
	/*
	 * Handle BPF listeners. Let the BPF user see the packet, but
	 * don't pass it up to the ether_input() layer unless it's
	 * a broadcast packet, multicast packet, matches our ethernet
	 * address or the interface is in promiscuous mode.
	 */
	if (ifp->if_bpf)
		bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
#endif

	DPRINTFN(10,("%s: %s: deliver %d\n", sc->kue_dev.dv_xname,
		    __func__, m->m_len));
	ether_input_mbuf(ifp, m);
 done1:
	splx(s);

 done:

	/* Setup new transfer. */
	usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_RX],
	    c, c->kue_buf, KUE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
	    USBD_NO_TIMEOUT, kue_rxeof);
	usbd_transfer(c->kue_xfer);

	DPRINTFN(10,("%s: %s: start rx\n", sc->kue_dev.dv_xname,
		    __func__));
}
예제 #13
0
파일: if_cdce.c 프로젝트: MarginC/kame
Static void
cdce_init(void *xsc)
{
    struct cdce_softc	*sc = xsc;
    struct ifnet		*ifp = GET_IFP(sc);
    struct ue_chain	*c;
    usbd_status		 err;
    int			 i;

    if (ifp->if_flags & IFF_RUNNING)
        return;

    CDCE_LOCK(sc);
    cdce_reset(sc);

    if (usb_ether_tx_list_init(sc, &sc->cdce_cdata,
                               sc->cdce_udev) == ENOBUFS) {
        printf("%s: tx list init failed\n", USBDEVNAME(sc->cdce_dev));
        CDCE_UNLOCK(sc);
        return;
    }

    if (usb_ether_rx_list_init(sc, &sc->cdce_cdata,
                               sc->cdce_udev) == ENOBUFS) {
        printf("%s: rx list init failed\n", USBDEVNAME(sc->cdce_dev));
        CDCE_UNLOCK(sc);
        return;
    }

    /* Maybe set multicast / broadcast here??? */

    err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no,
                         USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe);
    if (err) {
        printf("%s: open rx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
               usbd_errstr(err));
        CDCE_UNLOCK(sc);
        return;
    }

    err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no,
                         USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe);
    if (err) {
        printf("%s: open tx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
               usbd_errstr(err));
        CDCE_UNLOCK(sc);
        return;
    }

    for (i = 0; i < UE_RX_LIST_CNT; i++) {
        c = &sc->cdce_cdata.ue_rx_chain[i];
        usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkin_pipe, c,
                        mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK,
                        USBD_NO_TIMEOUT, cdce_rxeof);
        usbd_transfer(c->ue_xfer);
    }

    ifp->if_flags |= IFF_RUNNING;
    ifp->if_flags &= ~IFF_OACTIVE;

    CDCE_UNLOCK(sc);

    return;
}
예제 #14
0
void
smsc_init(void *xsc)
{
	struct smsc_softc	*sc = xsc;
	struct ifnet		*ifp = &sc->sc_ac.ac_if;
	struct smsc_chain	*c;
	usbd_status		 err;
	int			 s, i;
	
	s = splnet();

	/* Cancel pending I/O */
	smsc_stop(sc);

	/* Reset the ethernet interface. */
	smsc_reset(sc);

	/* Init RX ring. */
	if (smsc_rx_list_init(sc) == ENOBUFS) {
		printf("%s: rx list init failed\n", sc->sc_dev.dv_xname);
		splx(s);
		return;
	}

	/* Init TX ring. */
	if (smsc_tx_list_init(sc) == ENOBUFS) {
		printf("%s: tx list init failed\n", sc->sc_dev.dv_xname);
		splx(s);
		return;
	}

	/* Program promiscuous mode and multicast filters. */
	smsc_iff(sc);

	/* Open RX and TX pipes. */
	err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[SMSC_ENDPT_RX],
	    USBD_EXCLUSIVE_USE, &sc->sc_ep[SMSC_ENDPT_RX]);
	if (err) {
		printf("%s: open rx pipe failed: %s\n",
		    sc->sc_dev.dv_xname, usbd_errstr(err));
		splx(s);
		return;
	}

	err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[SMSC_ENDPT_TX],
	    USBD_EXCLUSIVE_USE, &sc->sc_ep[SMSC_ENDPT_TX]);
	if (err) {
		printf("%s: open tx pipe failed: %s\n",
		    sc->sc_dev.dv_xname, usbd_errstr(err));
		splx(s);
		return;
	}

	/* Start up the receive pipe. */
	for (i = 0; i < SMSC_RX_LIST_CNT; i++) {
		c = &sc->sc_cdata.rx_chain[i];
		usbd_setup_xfer(c->sc_xfer, sc->sc_ep[SMSC_ENDPT_RX],
		    c, c->sc_buf, sc->sc_bufsz,
		    USBD_SHORT_XFER_OK | USBD_NO_COPY,
		    USBD_NO_TIMEOUT, smsc_rxeof);
		usbd_transfer(c->sc_xfer);
	}

	/* TCP/UDP checksum offload engines. */
	smsc_sethwcsum(sc);

	/* Indicate we are up and running. */
	ifp->if_flags |= IFF_RUNNING;
	ifp->if_flags &= ~IFF_OACTIVE;

	timeout_add_sec(&sc->sc_stat_ch, 1);

	splx(s);
}
예제 #15
0
파일: if_kue.c 프로젝트: ryoon/netbsd-xhci
/*
 * A frame has been uploaded: pass the resulting mbuf chain up to
 * the higher level protocols.
 */
static void
kue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
{
	struct kue_chain	*c = priv;
	struct kue_softc	*sc = c->kue_sc;
	struct ifnet		*ifp = GET_IFP(sc);
	struct mbuf		*m;
	int			total_len, pktlen;
	int			s;

	DPRINTFN(10,("%s: %s: enter status=%d\n", device_xname(sc->kue_dev),
		     __func__, status));

	if (sc->kue_dying)
		return;

	if (!(ifp->if_flags & IFF_RUNNING))
		return;

	if (status != USBD_NORMAL_COMPLETION) {
		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
			return;
		sc->kue_rx_errs++;
		if (usbd_ratecheck(&sc->kue_rx_notice)) {
			printf("%s: %u usb errors on rx: %s\n",
			    device_xname(sc->kue_dev), sc->kue_rx_errs,
			    usbd_errstr(status));
			sc->kue_rx_errs = 0;
		}
		if (status == USBD_STALLED)
			usbd_clear_endpoint_stall_async(sc->kue_ep[KUE_ENDPT_RX]);
		goto done;
	}

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

	DPRINTFN(10,("%s: %s: total_len=%d len=%d\n", device_xname(sc->kue_dev),
		     __func__, total_len,
		     le16dec(c->kue_buf)));

	if (total_len <= 1)
		goto done;

	pktlen = le16dec(c->kue_buf);
	if (pktlen > total_len - 2)
		pktlen = total_len - 2;

	if (pktlen < ETHER_MIN_LEN - ETHER_CRC_LEN ||
	    pktlen > MCLBYTES - ETHER_ALIGN) {
		ifp->if_ierrors++;
		goto done;
	}

	/* No errors; receive the packet. */
	MGETHDR(m, M_DONTWAIT, MT_DATA);
	if (m == NULL) {
		ifp->if_ierrors++;
		goto done;
	}
	if (pktlen > MHLEN - ETHER_ALIGN) {
		MCLGET(m, M_DONTWAIT);
		if ((m->m_flags & M_EXT) == 0) {
			m_freem(m);
			ifp->if_ierrors++;
			goto done;
		}
	}
	m->m_data += ETHER_ALIGN;

	/* copy data to mbuf */
	memcpy(mtod(m, uint8_t *), c->kue_buf + 2, pktlen);

	ifp->if_ipackets++;
	m->m_pkthdr.len = m->m_len = pktlen;
	m->m_pkthdr.rcvif = ifp;

	s = splnet();

	/*
	 * Handle BPF listeners. Let the BPF user see the packet, but
	 * don't pass it up to the ether_input() layer unless it's
	 * a broadcast packet, multicast packet, matches our ethernet
	 * address or the interface is in promiscuous mode.
	 */
	bpf_mtap(ifp, m);

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

	splx(s);

 done:

	/* Setup new transfer. */
	usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_RX],
	    c, c->kue_buf, KUE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
	    USBD_NO_TIMEOUT, kue_rxeof);
	usbd_transfer(c->kue_xfer);

	DPRINTFN(10,("%s: %s: start rx\n", device_xname(sc->kue_dev),
		    __func__));
}
예제 #16
0
파일: ucom.c 프로젝트: appleorange1/bitrig
void
ucomstart(struct tty *tp)
{
	struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)];
	usbd_status err;
	int s;
	u_char *data;
	int cnt;

	if (sc == NULL || usbd_is_dying(sc->sc_uparent))
		return;

	s = spltty();
	if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) {
		DPRINTFN(4,("ucomstart: no go, state=0x%x\n", tp->t_state));
		goto out;
	}
	if (sc->sc_tx_stopped)
		goto out;

	ttwakeupwr(tp);
	if (tp->t_outq.c_cc == 0)
		goto out;

	/* Grab the first contiguous region of buffer space. */
	data = tp->t_outq.c_cf;
	cnt = ndqb(&tp->t_outq, 0);

	if (cnt == 0) {
		DPRINTF(("ucomstart: cnt==0\n"));
		goto out;
	}

	SET(tp->t_state, TS_BUSY);

	if (cnt > sc->sc_obufsize) {
		DPRINTF(("ucomstart: big buffer %d chars\n", cnt));
		cnt = sc->sc_obufsize;
	}
	if (sc->sc_methods->ucom_write != NULL)
		sc->sc_methods->ucom_write(sc->sc_parent, sc->sc_portno,
					   sc->sc_obuf, data, &cnt);
	else
		memcpy(sc->sc_obuf, data, cnt);

	DPRINTFN(4,("ucomstart: %d chars\n", cnt));
#ifdef DIAGNOSTIC
	if (sc->sc_oxfer == NULL) {
		printf("ucomstart: null oxfer\n");
		goto out;
	}
#endif
	if (sc->sc_bulkout_pipe != NULL) {
		usbd_setup_xfer(sc->sc_oxfer, sc->sc_bulkout_pipe,
		    (void *)sc, sc->sc_obuf, cnt,
		    USBD_NO_COPY, USBD_NO_TIMEOUT, ucomwritecb);
	} else {
		usbd_setup_xfer(sc->sc_oxfer, sc->sc_opipe,
		    (void *)sc, sc->sc_obuf, cnt,
		    USBD_NO_COPY, USBD_NO_TIMEOUT, ucomwritecb);
	}
	/* What can we do on error? */
	err = usbd_transfer(sc->sc_oxfer);
#ifdef DIAGNOSTIC
	if (err != USBD_IN_PROGRESS)
		printf("ucomstart: err=%s\n", usbd_errstr(err));
#endif

out:
	splx(s);
}
예제 #17
0
파일: ugen.c 프로젝트: SylvestreG/bitrig
int
ugen_do_write(struct ugen_softc *sc, int endpt, struct uio *uio, int flag)
{
	struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT];
	u_int32_t n;
	int flags, error = 0;
	char buf[UGEN_BBSIZE];
	struct usbd_xfer *xfer;
	usbd_status err;

	DPRINTFN(5, ("%s: ugenwrite: %d\n", sc->sc_dev.dv_xname, endpt));

	if (usbd_is_dying(sc->sc_udev))
		return (EIO);

	if (endpt == USB_CONTROL_ENDPOINT)
		return (ENODEV);

#ifdef DIAGNOSTIC
	if (sce->edesc == NULL) {
		printf("ugenwrite: no edesc\n");
		return (EIO);
	}
	if (sce->pipeh == NULL) {
		printf("ugenwrite: no pipe\n");
		return (EIO);
	}
#endif
	flags = USBD_SYNCHRONOUS;
	if (sce->timeout == 0)
		flags |= USBD_CATCH;

	switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
	case UE_BULK:
		xfer = usbd_alloc_xfer(sc->sc_udev);
		if (xfer == 0)
			return (EIO);
		while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
			error = uiomove(buf, n, uio);
			if (error)
				break;
			DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
			usbd_setup_xfer(xfer, sce->pipeh, 0, buf, n,
			    flags, sce->timeout, NULL);
			err = usbd_transfer(xfer);
			if (err) {
				usbd_clear_endpoint_stall(sce->pipeh);
				if (err == USBD_INTERRUPTED)
					error = EINTR;
				else if (err == USBD_TIMEOUT)
					error = ETIMEDOUT;
				else
					error = EIO;
				break;
			}
		}
		usbd_free_xfer(xfer);
		break;
	case UE_INTERRUPT:
		xfer = usbd_alloc_xfer(sc->sc_udev);
		if (xfer == 0)
			return (EIO);
		while ((n = min(UGETW(sce->edesc->wMaxPacketSize),
		    uio->uio_resid)) != 0) {
			error = uiomove(buf, n, uio);
			if (error)
				break;
			DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
			usbd_setup_xfer(xfer, sce->pipeh, 0, buf, n,
			    flags, sce->timeout, NULL);
			err = usbd_transfer(xfer);
			if (err) {
				usbd_clear_endpoint_stall(sce->pipeh);
				if (err == USBD_INTERRUPTED)
					error = EINTR;
				else if (err == USBD_TIMEOUT)
					error = ETIMEDOUT;
				else
					error = EIO;
				break;
			}
		}
		usbd_free_xfer(xfer);
		break;
	default:
		return (ENXIO);
	}
	return (error);
}
예제 #18
0
파일: ugen.c 프로젝트: SylvestreG/bitrig
int
ugen_do_read(struct ugen_softc *sc, int endpt, struct uio *uio, int flag)
{
	struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN];
	u_int32_t n, tn;
	char buf[UGEN_BBSIZE];
	struct usbd_xfer *xfer;
	usbd_status err;
	int s;
	int flags, error = 0;
	u_char buffer[UGEN_CHUNK];

	DPRINTFN(5, ("%s: ugenread: %d\n", sc->sc_dev.dv_xname, endpt));

	if (usbd_is_dying(sc->sc_udev))
		return (EIO);

	if (endpt == USB_CONTROL_ENDPOINT)
		return (ENODEV);

#ifdef DIAGNOSTIC
	if (sce->edesc == NULL) {
		printf("ugenread: no edesc\n");
		return (EIO);
	}
	if (sce->pipeh == NULL) {
		printf("ugenread: no pipe\n");
		return (EIO);
	}
#endif

	switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
	case UE_INTERRUPT:
		/* Block until activity occurred. */
		s = splusb();
		while (sce->q.c_cc == 0) {
			if (flag & IO_NDELAY) {
				splx(s);
				return (EWOULDBLOCK);
			}
			sce->state |= UGEN_ASLP;
			DPRINTFN(5, ("ugenread: sleep on %p\n", sce));
			error = tsleep(sce, PZERO | PCATCH, "ugenri",
			    (sce->timeout * hz) / 1000);
			sce->state &= ~UGEN_ASLP;
			DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
			if (usbd_is_dying(sc->sc_udev))
				error = EIO;
			if (error == EWOULDBLOCK) {	/* timeout, return 0 */
				error = 0;
				break;
			}
			if (error)
				break;
		}
		splx(s);

		/* Transfer as many chunks as possible. */
		while (sce->q.c_cc > 0 && uio->uio_resid > 0 && !error) {
			n = min(sce->q.c_cc, uio->uio_resid);
			if (n > sizeof(buffer))
				n = sizeof(buffer);

			/* Remove a small chunk from the input queue. */
			q_to_b(&sce->q, buffer, n);
			DPRINTFN(5, ("ugenread: got %d chars\n", n));

			/* Copy the data to the user process. */
			error = uiomove(buffer, n, uio);
			if (error)
				break;
		}
		break;
	case UE_BULK:
		xfer = usbd_alloc_xfer(sc->sc_udev);
		if (xfer == 0)
			return (ENOMEM);
		flags = USBD_SYNCHRONOUS;
		if (sce->state & UGEN_SHORT_OK)
			flags |= USBD_SHORT_XFER_OK;
		if (sce->timeout == 0)
			flags |= USBD_CATCH;
		while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
			DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n));
			usbd_setup_xfer(xfer, sce->pipeh, 0, buf, n,
			    flags, sce->timeout, NULL);
			err = usbd_transfer(xfer);
			if (err) {
				usbd_clear_endpoint_stall(sce->pipeh);
				if (err == USBD_INTERRUPTED)
					error = EINTR;
				else if (err == USBD_TIMEOUT)
					error = ETIMEDOUT;
				else
					error = EIO;
				break;
			}
			usbd_get_xfer_status(xfer, NULL, NULL, &tn, NULL);
			DPRINTFN(1, ("ugenread: got %d bytes\n", tn));
			error = uiomove(buf, tn, uio);
			if (error || tn < n)
				break;
		}
		usbd_free_xfer(xfer);
		break;
	case UE_ISOCHRONOUS:
		s = splusb();
		while (sce->cur == sce->fill) {
			if (flag & IO_NDELAY) {
				splx(s);
				return (EWOULDBLOCK);
			}
			sce->state |= UGEN_ASLP;
			DPRINTFN(5, ("ugenread: sleep on %p\n", sce));
			error = tsleep(sce, PZERO | PCATCH, "ugenri",
			    (sce->timeout * hz) / 1000);
			sce->state &= ~UGEN_ASLP;
			DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
			if (usbd_is_dying(sc->sc_udev))
				error = EIO;
			if (error == EWOULDBLOCK) {	/* timeout, return 0 */
				error = 0;
				break;
			}
			if (error)
				break;
		}

		while (sce->cur != sce->fill && uio->uio_resid > 0 && !error) {
			if(sce->fill > sce->cur)
				n = min(sce->fill - sce->cur, uio->uio_resid);
			else
				n = min(sce->limit - sce->cur, uio->uio_resid);

			DPRINTFN(5, ("ugenread: isoc got %d chars\n", n));

			/* Copy the data to the user process. */
			error = uiomove(sce->cur, n, uio);
			if (error)
				break;
			sce->cur += n;
			if(sce->cur >= sce->limit)
				sce->cur = sce->ibuf;
		}
		splx(s);
		break;


	default:
		return (ENXIO);
	}
	return (error);
}
예제 #19
0
파일: ugen.c 프로젝트: SylvestreG/bitrig
int
ugenopen(dev_t dev, int flag, int mode, struct proc *p)
{
	struct ugen_softc *sc;
	int unit = UGENUNIT(dev);
	int endpt = UGENENDPOINT(dev);
	usb_endpoint_descriptor_t *edesc;
	struct ugen_endpoint *sce;
	int dir, isize;
	usbd_status err;
	struct usbd_xfer *xfer;
	void *buf;
	int i, j;

	if (unit >= ugen_cd.cd_ndevs)
		return (ENXIO);
	sc = ugen_cd.cd_devs[unit];
	if (sc == NULL)
		return (ENXIO);

	DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n",
		     flag, mode, unit, endpt));

	if (sc == NULL || usbd_is_dying(sc->sc_udev))
		return (ENXIO);

	if (sc->sc_is_open[endpt])
		return (EBUSY);

	if (endpt == USB_CONTROL_ENDPOINT) {
		sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1;
		return (0);
	}

	/* Make sure there are pipes for all directions. */
	for (dir = OUT; dir <= IN; dir++) {
		if (flag & (dir == OUT ? FWRITE : FREAD)) {
			sce = &sc->sc_endpoints[endpt][dir];
			if (sce == 0 || sce->edesc == 0)
				return (ENXIO);
		}
	}

	/* Actually open the pipes. */
	/* XXX Should back out properly if it fails. */
	for (dir = OUT; dir <= IN; dir++) {
		if (!(flag & (dir == OUT ? FWRITE : FREAD)))
			continue;
		sce = &sc->sc_endpoints[endpt][dir];
		sce->state = 0;
		sce->timeout = USBD_NO_TIMEOUT;
		DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n",
			     sc, endpt, dir, sce));
		edesc = sce->edesc;
		switch (edesc->bmAttributes & UE_XFERTYPE) {
		case UE_INTERRUPT:
			if (dir == OUT) {
				err = usbd_open_pipe(sce->iface,
				    edesc->bEndpointAddress, 0, &sce->pipeh);
				if (err)
					return (EIO);
				break;
			}
			isize = UGETW(edesc->wMaxPacketSize);
			if (isize == 0)	/* shouldn't happen */
				return (EINVAL);
			sce->ibuf = malloc(isize, M_USBDEV, M_WAITOK);
			DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n",
				     endpt, isize));
			clalloc(&sce->q, UGEN_IBSIZE, 0);
			err = usbd_open_pipe_intr(sce->iface,
				  edesc->bEndpointAddress,
				  USBD_SHORT_XFER_OK, &sce->pipeh, sce,
				  sce->ibuf, isize, ugenintr,
				  USBD_DEFAULT_INTERVAL);
			if (err) {
				free(sce->ibuf, M_USBDEV, 0);
				clfree(&sce->q);
				return (EIO);
			}
			DPRINTFN(5, ("ugenopen: interrupt open done\n"));
			break;
		case UE_BULK:
			err = usbd_open_pipe(sce->iface,
				  edesc->bEndpointAddress, 0, &sce->pipeh);
			if (err)
				return (EIO);
			break;
		case UE_ISOCHRONOUS:
			if (dir == OUT)
				return (EINVAL);
			isize = UGETW(edesc->wMaxPacketSize);
			if (isize == 0)	/* shouldn't happen */
				return (EINVAL);
			sce->ibuf = malloc(isize * UGEN_NISOFRAMES,
				M_USBDEV, M_WAITOK);
			sce->cur = sce->fill = sce->ibuf;
			sce->limit = sce->ibuf + isize * UGEN_NISOFRAMES;
			DPRINTFN(5, ("ugenopen: isoc endpt=%d, isize=%d\n",
				     endpt, isize));
			err = usbd_open_pipe(sce->iface,
				  edesc->bEndpointAddress, 0, &sce->pipeh);
			if (err) {
				free(sce->ibuf, M_USBDEV, 0);
				return (EIO);
			}
			for(i = 0; i < UGEN_NISOREQS; ++i) {
				sce->isoreqs[i].sce = sce;
				xfer = usbd_alloc_xfer(sc->sc_udev);
				if (xfer == 0)
					goto bad;
				sce->isoreqs[i].xfer = xfer;
				buf = usbd_alloc_buffer
					(xfer, isize * UGEN_NISORFRMS);
				if (buf == 0) {
					i++;
					goto bad;
				}
				sce->isoreqs[i].dmabuf = buf;
				for(j = 0; j < UGEN_NISORFRMS; ++j)
					sce->isoreqs[i].sizes[j] = isize;
				usbd_setup_isoc_xfer
					(xfer, sce->pipeh, &sce->isoreqs[i],
					 sce->isoreqs[i].sizes,
					 UGEN_NISORFRMS, USBD_NO_COPY,
					 ugen_isoc_rintr);
				(void)usbd_transfer(xfer);
			}
			DPRINTFN(5, ("ugenopen: isoc open done\n"));
			break;
		bad:
			while (--i >= 0) /* implicit buffer free */
				usbd_free_xfer(sce->isoreqs[i].xfer);
			return (ENOMEM);
		case UE_CONTROL:
			sce->timeout = USBD_DEFAULT_TIMEOUT;
			return (EINVAL);
		}
	}
	sc->sc_is_open[endpt] = 1;
	return (0);
}
예제 #20
0
Static void
ucomstart(struct tty *tp)
{
	struct ucom_softc *sc;
	struct cblock *cbp;
	usbd_status err;
	int s;
	u_char *data;
	int cnt;

	USB_GET_SC(ucom, UCOMUNIT(tp->t_dev), sc);
	DPRINTF(("ucomstart: sc = %p\n", sc));

	if (sc->sc_dying)
		return;

	s = spltty();

	if (tp->t_state & TS_TBLOCK) {
		if (ISSET(sc->sc_mcr, UMCR_RTS) &&
		    ISSET(sc->sc_state, UCS_RTS_IFLOW)) {
			DPRINTF(("ucomstart: clear RTS\n"));
			(void)ucomctl(sc, UMCR_RTS, DMBIC);
		}
	} else {
		if (!ISSET(sc->sc_mcr, UMCR_RTS) &&
		    tp->t_rawq.c_cc <= tp->t_ilowat &&
		    ISSET(sc->sc_state, UCS_RTS_IFLOW)) {
			DPRINTF(("ucomstart: set RTS\n"));
			(void)ucomctl(sc, UMCR_RTS, DMBIS);
		}
	}

	if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) {
		ttwwakeup(tp);
		DPRINTF(("ucomstart: stopped\n"));
		goto out;
	}

	if (tp->t_outq.c_cc <= tp->t_olowat) {
		if (ISSET(tp->t_state, TS_SO_OLOWAT)) {
			CLR(tp->t_state, TS_SO_OLOWAT);
			wakeup(TSA_OLOWAT(tp));
		}
		selwakeup(&tp->t_wsel);
		if (tp->t_outq.c_cc == 0) {
			if (ISSET(tp->t_state, TS_BUSY | TS_SO_OCOMPLETE) ==
			    TS_SO_OCOMPLETE && tp->t_outq.c_cc == 0) {
				CLR(tp->t_state, TS_SO_OCOMPLETE);
				wakeup(TSA_OCOMPLETE(tp));
			}
			goto out;
		}
	}

	/* Grab the first contiguous region of buffer space. */
	data = tp->t_outq.c_cf;
	cbp = (struct cblock *) ((intptr_t) tp->t_outq.c_cf & ~CROUND);
	cnt = min((char *) (cbp+1) - tp->t_outq.c_cf, tp->t_outq.c_cc);

	if (cnt == 0) {
		DPRINTF(("ucomstart: cnt == 0\n"));
		goto out;
	}

	SET(tp->t_state, TS_BUSY);

	if (cnt > sc->sc_obufsize) {
		DPRINTF(("ucomstart: big buffer %d chars\n", cnt));
		cnt = sc->sc_obufsize;
	}
	if (sc->sc_callback->ucom_write != NULL)
		sc->sc_callback->ucom_write(sc->sc_parent, sc->sc_portno,
					    sc->sc_obuf, data, &cnt);
	else
		memcpy(sc->sc_obuf, data, cnt);

	DPRINTF(("ucomstart: %d chars\n", cnt));
	usbd_setup_xfer(sc->sc_oxfer, sc->sc_bulkout_pipe,
			(usbd_private_handle)sc, sc->sc_obuf, cnt,
			USBD_NO_COPY, USBD_NO_TIMEOUT, ucomwritecb);
	/* What can we do on error? */
	err = usbd_transfer(sc->sc_oxfer);
	if (err != USBD_IN_PROGRESS)
		printf("ucomstart: err=%s\n", usbd_errstr(err));

	ttwwakeup(tp);

    out:
	splx(s);
}
예제 #21
0
/*
 * A frame has been uploaded: pass the resulting mbuf chain up to
 * the higher level protocols.
 */
void
ugl_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
{
	struct ugl_chain	*c = priv;
	struct ugl_softc	*sc = c->ugl_sc;
	struct ifnet		*ifp = GET_IFP(sc);
	struct mbuf		*m;
	int			total_len = 0;
	unsigned int		packet_len, packet_count;
	int			s;

	if (usbd_is_dying(sc->sc_udev))
		return;

	if (!(ifp->if_flags & IFF_RUNNING))
		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",
			    sc->sc_dev.dv_xname, sc->sc_rx_errs,
			    usbd_errstr(status));
			sc->sc_rx_errs = 0;
		}
		if (status == USBD_STALLED)
			usbd_clear_endpoint_stall_async(sc->sc_ep[UGL_ENDPT_RX]);
		goto done;
	}

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

	DPRINTFN(9,("%s: %s: enter status=%d length=%d\n",
		    sc->sc_dev.dv_xname, __func__, status, total_len));

	if (total_len < offsetof(struct ugl_packet, pkt_data)) {
		printf("%s: bad header (length=%d)\n",
		    sc->sc_dev.dv_xname, total_len);

		goto done;
	}

	packet_count = UGETDW(c->ugl_buf->pkt_count);
	if (packet_count != UGL_RX_FRAMES) {
		printf("%s: bad packet count (%d)\n",
		    sc->sc_dev.dv_xname, packet_count);

		if (packet_count == 0)
			goto done;
	}

	packet_len = UGETDW(c->ugl_buf->pkt_length);
	if (total_len < packet_len) {
		printf("%s: bad packet size(%d), length=%d\n",
		    sc->sc_dev.dv_xname, packet_len, total_len);

		if (packet_len == 0)
			goto done;
	}

	m = c->ugl_mbuf;
	memcpy(mtod(c->ugl_mbuf, char *), c->ugl_buf->pkt_data, packet_len);

	ifp->if_ipackets++;
	m->m_pkthdr.len = m->m_len = packet_len;

	m->m_pkthdr.rcvif = ifp;

	s = splnet();

	/* XXX ugly */
	if (ugl_newbuf(sc, c, NULL) == ENOBUFS) {
		ifp->if_ierrors++;
		goto done1;
	}

#if NBPFILTER > 0
	/*
	 * Handle BPF listeners. Let the BPF user see the packet, but
	 * don't pass it up to the ether_input() layer unless it's
	 * a broadcast packet, multicast packet, matches our ethernet
	 * address or the interface is in promiscuous mode.
	 */
	if (ifp->if_bpf) {
		bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
	}
#endif

	DPRINTFN(10,("%s: %s: deliver %d\n", sc->sc_dev.dv_xname,
		    __func__, m->m_len));

	ether_input_mbuf(ifp, m);

 done1:
	splx(s);

 done:
	/* Setup new transfer. */
	usbd_setup_xfer(c->ugl_xfer, sc->sc_ep[UGL_ENDPT_RX],
	    c, c->ugl_buf, UGL_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
	    USBD_NO_TIMEOUT, ugl_rxeof);
	usbd_transfer(c->ugl_xfer);

	DPRINTFN(10,("%s: %s: start rx\n", sc->sc_dev.dv_xname,
		    __func__));
}
예제 #22
0
/*
 * A frame has been received.
 */
void
wi_usb_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
{
	struct wi_usb_chain	*c = priv;
	struct wi_usb_softc	*sc = c->wi_usb_sc;
	wi_usb_usbin		*uin;
	int			total_len = 0;
	u_int16_t		rtype;

	if (usbd_is_dying(sc->wi_usb_udev))
		return;

	DPRINTFN(10,("%s: %s: enter status=%d\n", sc->wi_usb_dev.dv_xname,
		    __func__, status));


	if (status != USBD_NORMAL_COMPLETION) {
		if (status == USBD_NOT_STARTED || status == USBD_IOERROR
		    || status == USBD_CANCELLED) {
			printf("%s: %u usb errors on rx: %s\n",
			    sc->wi_usb_dev.dv_xname, 1,
			    /* sc->wi_usb_rx_errs, */
			    usbd_errstr(status));
			return;
		}
#if 0
		sc->wi_usb_rx_errs++;
		if (usbd_ratecheck(&sc->wi_usb_rx_notice)) {
			printf("%s: %u usb errors on rx: %s\n",
			    sc->wi_usb_dev.dv_xname, sc->wi_usb_rx_errs,
			    usbd_errstr(status));
			sc->wi_usb_rx_errs = 0;
		}
#endif
		if (status == USBD_STALLED) {
			sc->wi_usb_refcnt++;
			usbd_clear_endpoint_stall_async(
			    sc->wi_usb_ep[WI_USB_ENDPT_RX]);
			if (--sc->wi_usb_refcnt < 0)
				usb_detach_wakeup(&sc->wi_usb_dev);
		}
		goto done;
	}

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

	if (total_len < 6) /* short XXX */
		goto done;

	uin = (wi_usb_usbin *)(c->wi_usb_buf);

	rtype = letoh16(uin->type);


#if 0
	wi_dump_data(c->wi_usb_buf, total_len);
#endif

	if (WI_USB_ISRXFRM(rtype)) {
		wi_usb_rxfrm(sc, uin, total_len);
		goto done;
	}
	if (WI_USB_ISTXFRM(rtype)) {
		DPRINTFN(2,("%s: %s: txfrm type %x\n",
		    sc->wi_usb_dev.dv_xname, __func__, rtype));
		wi_usb_txfrm(sc, uin, total_len);
		goto done;
	}

	switch (rtype) {
	case WI_USB_INFOFRM:
		/* info packet, INFO_FID hmm */
		DPRINTFN(10,("%s: %s: infofrm type %x\n",
		    sc->wi_usb_dev.dv_xname, __func__, rtype));
		wi_usb_infofrm(c, total_len);
		break;
	case WI_USB_CMDRESP:
		wi_usb_cmdresp(c);
		break;
	case WI_USB_WRIDRESP:
		wi_usb_wridresp(c);
		break;
	case WI_USB_RRIDRESP:
		wi_usb_rridresp(c);
		break;
	case WI_USB_WMEMRESP:
		/* Not currently used */
		DPRINTFN(2,("%s: %s: wmemresp type %x\n",
		    sc->wi_usb_dev.dv_xname, __func__, rtype));
		break;
	case WI_USB_RMEMRESP:
		/* Not currently used */
		DPRINTFN(2,("%s: %s: rmemresp type %x\n",
		    sc->wi_usb_dev.dv_xname, __func__, rtype));
		break;
	case WI_USB_BUFAVAIL:
		printf("wi_usb: received USB_BUFAVAIL packet\n"); /* XXX */
		break;
	case WI_USB_ERROR:
		printf("wi_usb: received USB_ERROR packet\n"); /* XXX */
		break;
#if 0
	default:
		printf("wi_usb: received Unknown packet 0x%x len %x\n",
		    rtype, total_len);
		wi_dump_data(c->wi_usb_buf, total_len);
#endif
	}

 done:
	/* Setup new transfer. */
	usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_RX],
	    c, c->wi_usb_buf, WI_USB_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
	    USBD_NO_TIMEOUT, wi_usb_rxeof);
	sc->wi_usb_refcnt++;
	usbd_transfer(c->wi_usb_xfer);
	if (--sc->wi_usb_refcnt < 0)
		usb_detach_wakeup(&sc->wi_usb_dev);

	DPRINTFN(10,("%s: %s: start rx\n", sc->wi_usb_dev.dv_xname,
		    __func__));
}
예제 #23
0
int
wi_send_packet(struct wi_usb_softc *sc, int id)
{
	struct wi_usb_chain	*c;
	struct wi_frame		*wibuf;
	int			total_len, rnd_len;
	int			err;

	c = &sc->wi_usb_tx_chain[0];

	DPRINTFN(10,("%s: %s: id=%x\n",
	    sc->wi_usb_dev.dv_xname, __func__, id));

	/* assemble packet from write_data buffer */
	if (id == 0 || id == 1) {
		/* tx_lock acquired before wi_start() */
		wibuf = sc->wi_usb_txmem[id];

		total_len = sizeof (struct wi_frame) +
		    letoh16(wibuf->wi_dat_len);
		rnd_len = ROUNDUP64(total_len);
		if ((total_len > sc->wi_usb_txmemsize[id]) ||
		   (rnd_len > WI_USB_BUFSZ )){
			printf("invalid packet len: %x memsz %x max %x\n",
			    total_len, sc->wi_usb_txmemsize[id], WI_USB_BUFSZ);

			err = EIO;
			goto err_ret;
		}

		sc->txresp = WI_CMD_TX;
		sc->txresperr = 0;

		bcopy(wibuf, c->wi_usb_buf, total_len);

		bzero(((char *)c->wi_usb_buf)+total_len,
		    rnd_len - total_len);

		/* zero old packet for next TX */
		bzero(wibuf, total_len);

		total_len = rnd_len;

		DPRINTFN(5,("%s: %s: id=%x len=%x\n",
		    sc->wi_usb_dev.dv_xname, __func__, id, total_len));

		usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_TX],
		    c, c->wi_usb_buf, rnd_len,
		    USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
		    WI_USB_TX_TIMEOUT, wi_usb_txeof_frm);

		err = usbd_transfer(c->wi_usb_xfer);
		if (err != USBD_IN_PROGRESS && err != USBD_NORMAL_COMPLETION) {
			printf("%s: %s: error=%s\n",
			    sc->wi_usb_dev.dv_xname, __func__,
			    usbd_errstr(err));
			/* Stop the interface from process context. */
			wi_usb_stop(sc);
			err = EIO;
		} else {
			err = 0;
		}

		DPRINTFN(5,("%s: %s: exit err=%x\n",
		    sc->wi_usb_dev.dv_xname, __func__, err));
err_ret:
		return err;
	}
	printf("%s:%s: invalid packet id sent %x\n",
	    sc->wi_usb_dev.dv_xname, __func__, id);
	return 0;
}
예제 #24
0
파일: if_smsc.c 프로젝트: ryoon/netbsd-xhci
int
smsc_init(struct ifnet *ifp)
{
    struct smsc_softc	*sc = ifp->if_softc;
    struct smsc_chain	*c;
    usbd_status		 err;
    int			 s, i;

    if (sc->sc_dying)
        return EIO;

    s = splnet();

    /* Cancel pending I/O */
    if (ifp->if_flags & IFF_RUNNING)
        smsc_stop(ifp, 1);

    /* Reset the ethernet interface. */
    smsc_reset(sc);

    /* Init RX ring. */
    if (smsc_rx_list_init(sc) == ENOBUFS) {
        aprint_error_dev(sc->sc_dev, "rx list init failed\n");
        splx(s);
        return EIO;
    }

    /* Init TX ring. */
    if (smsc_tx_list_init(sc) == ENOBUFS) {
        aprint_error_dev(sc->sc_dev, "tx list init failed\n");
        splx(s);
        return EIO;
    }

    /* Load the multicast filter. */
    smsc_setmulti(sc);

    /* TCP/UDP checksum offload engines. */
    smsc_sethwcsum(sc);

    /* Open RX and TX pipes. */
    err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[SMSC_ENDPT_RX],
                         USBD_EXCLUSIVE_USE, &sc->sc_ep[SMSC_ENDPT_RX]);
    if (err) {
        printf("%s: open rx pipe failed: %s\n",
               device_xname(sc->sc_dev), usbd_errstr(err));
        splx(s);
        return EIO;
    }

    err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[SMSC_ENDPT_TX],
                         USBD_EXCLUSIVE_USE, &sc->sc_ep[SMSC_ENDPT_TX]);
    if (err) {
        printf("%s: open tx pipe failed: %s\n",
               device_xname(sc->sc_dev), usbd_errstr(err));
        splx(s);
        return EIO;
    }

    /* Start up the receive pipe. */
    for (i = 0; i < SMSC_RX_LIST_CNT; i++) {
        c = &sc->sc_cdata.rx_chain[i];
        usbd_setup_xfer(c->sc_xfer, sc->sc_ep[SMSC_ENDPT_RX],
                        c, c->sc_buf, sc->sc_bufsz,
                        USBD_SHORT_XFER_OK | USBD_NO_COPY,
                        USBD_NO_TIMEOUT, smsc_rxeof);
        usbd_transfer(c->sc_xfer);
    }

    /* Indicate we are up and running. */
    ifp->if_flags |= IFF_RUNNING;
    ifp->if_flags &= ~IFF_OACTIVE;

    splx(s);

    callout_reset(&sc->sc_stat_ch, hz, smsc_tick, sc);

    return 0;
}
예제 #25
0
파일: ulpt.c 프로젝트: appleorange1/bitrig
/*
 * Reset the printer, then wait until it's selected and not busy.
 */
int
ulptopen(dev_t dev, int flag, int mode, struct proc *p)
{
	u_char flags = ULPTFLAGS(dev);
	struct ulpt_softc *sc;
	usbd_status err;
	int error;

	if (ULPTUNIT(dev) >= ulpt_cd.cd_ndevs)
		return (ENXIO);
	sc = ulpt_cd.cd_devs[ULPTUNIT(dev)];
	if (sc == NULL)
		return (ENXIO);

	if (sc == NULL || sc->sc_iface == NULL || usbd_is_dying(sc->sc_udev))
		return (ENXIO);

	if (sc->sc_state)
		return (EBUSY);

	sc->sc_state = ULPT_INIT;
	sc->sc_flags = flags;
	DPRINTF(("ulptopen: flags=0x%x\n", (unsigned)flags));

	error = 0;
	sc->sc_refcnt++;

	if ((flags & ULPT_NOPRIME) == 0) {
		ulpt_reset(sc);
		if (usbd_is_dying(sc->sc_udev)) {
			error = ENXIO;
			sc->sc_state = 0;
			goto done;
		}
	}

	err = usbd_open_pipe(sc->sc_iface, sc->sc_out, 0, &sc->sc_out_pipe);
	if (err) {
		sc->sc_state = 0;
		error = EIO;
		goto done;
	}
	if (ulptusein && sc->sc_in != -1) {
		DPRINTF(("ulpt_open: open input pipe\n"));
		err = usbd_open_pipe(sc->sc_iface, sc->sc_in,0,&sc->sc_in_pipe);
		if (err) {
			error = EIO;
			usbd_close_pipe(sc->sc_out_pipe);
			sc->sc_out_pipe = NULL;
			sc->sc_state = 0;
			goto done;
		}
		sc->sc_in_xfer1 = usbd_alloc_xfer(sc->sc_udev);
		sc->sc_in_xfer2 = usbd_alloc_xfer(sc->sc_udev);
		if (sc->sc_in_xfer1 == NULL || sc->sc_in_xfer2 == NULL) {
			error = ENOMEM;
			if (sc->sc_in_xfer1 != NULL) {
				usbd_free_xfer(sc->sc_in_xfer1);
				sc->sc_in_xfer1 = NULL;
			}
			if (sc->sc_in_xfer2 != NULL) {
				usbd_free_xfer(sc->sc_in_xfer2);
				sc->sc_in_xfer2 = NULL;
			}
			usbd_close_pipe(sc->sc_out_pipe);
			sc->sc_out_pipe = NULL;
			usbd_close_pipe(sc->sc_in_pipe);
			sc->sc_in_pipe = NULL;
			sc->sc_state = 0;
			goto done;
		}
		usbd_setup_xfer(sc->sc_in_xfer1, sc->sc_in_pipe, sc,
		    sc->sc_junk, sizeof sc->sc_junk, USBD_SHORT_XFER_OK,
		    USBD_NO_TIMEOUT, ulpt_input);
		usbd_setup_xfer(sc->sc_in_xfer2, sc->sc_in_pipe, sc,
		    sc->sc_junk, sizeof sc->sc_junk, USBD_SHORT_XFER_OK,
		    USBD_NO_TIMEOUT, ulpt_input);
		usbd_transfer(sc->sc_in_xfer1); /* ignore failed start */
	}

	sc->sc_state = ULPT_OPEN;

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

	DPRINTF(("ulptopen: done, error=%d\n", error));
	return (error);
}
예제 #26
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",
		       USBDEVNAME(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",
		       USBDEVNAME(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, URL_INTR_INTERVAL);
	if (err) {
		printf("%s: open intr pipe failed: %s\n",
		       USBDEVNAME(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", USBDEVNAME(sc->sc_dev),
			 __func__));
	}

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

	return (error);
}
예제 #27
0
파일: if_cdce.c 프로젝트: MarginC/kame
Static void
cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
{
    struct ue_chain	*c = priv;
    struct cdce_softc	*sc = c->ue_sc;
    struct ifnet		*ifp;
    struct mbuf		*m;
    int			 total_len = 0;

    CDCE_LOCK(sc);
    ifp = GET_IFP(sc);

    if (sc->cdce_dying || !(ifp->if_flags & IFF_RUNNING)) {
        CDCE_UNLOCK(sc);
        return;
    }

    if (status != USBD_NORMAL_COMPLETION) {
        if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
            CDCE_UNLOCK(sc);
            return;
        }
        if (sc->cdce_rxeof_errors == 0)
            printf("%s: usb error on rx: %s\n",
                   USBDEVNAME(sc->cdce_dev), usbd_errstr(status));
        if (status == USBD_STALLED)
            usbd_clear_endpoint_stall(sc->cdce_bulkin_pipe);
        DELAY(sc->cdce_rxeof_errors * 10000);
        sc->cdce_rxeof_errors++;
        goto done;
    }

    sc->cdce_rxeof_errors = 0;

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

    if (sc->cdce_flags & CDCE_ZAURUS)
        total_len -= 4;	/* Strip off CRC added by Zaurus */

    m = c->ue_mbuf;

    if (total_len < sizeof(struct ether_header)) {
        ifp->if_ierrors++;
        goto done;
    }

    ifp->if_ipackets++;
    m->m_pkthdr.rcvif = (struct ifnet *)&sc->q;
    m->m_pkthdr.len = m->m_len = total_len;

    /* Put the packet on the special USB input queue. */
    usb_ether_input(m);
    CDCE_UNLOCK(sc);

    return;

done:
    /* Setup new transfer. */
    usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkin_pipe, c,
                    mtod(c->ue_mbuf, char *),
                    UE_BUFSZ, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT,
                    cdce_rxeof);
    usbd_transfer(c->ue_xfer);
    CDCE_UNLOCK(sc);

    return;
}
예제 #28
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", USBDEVNAME(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",
			       USBDEVNAME(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_wakeup(USBDEV(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",
		 USBDEVNAME(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;
	}

#if NBPFILTER > 0
	if (ifp->if_bpf)
		bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
#endif

	DPRINTF(("%s: %s: deliver %d\n", USBDEVNAME(sc->sc_dev),
		 __func__, m->m_len));
	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_wakeup(USBDEV(sc->sc_dev));

	DPRINTF(("%s: %s: start rx\n", USBDEVNAME(sc->sc_dev), __func__));
}
예제 #29
0
파일: udbp.c 프로젝트: MarginC/kame
Static int
udbp_setup_out_transfer(udbp_p sc)
{
	void *priv = sc;	/* XXX this should probably be some pointer to
				 * struct describing the transfer (mbuf?)
				 * See also below.
				 */
	int pktlen;
	usbd_status err;
	int s, s1;
	struct mbuf *m;


	s = splusb();
	if (sc->flags & OUT_BUSY)
		panic("out transfer already in use, we should add queuing");
	sc->flags |= OUT_BUSY;
	splx(s);
	s1 = splimp(); /* Queueing happens at splnet */
	IF_DEQUEUE(&sc->xmitq_hipri, m);
	if (m == NULL) {
		IF_DEQUEUE(&sc->xmitq, m);
	}
	splx(s1);

	if (!m) {
		sc->flags &= ~OUT_BUSY;
		return (USBD_NORMAL_COMPLETION);
	}

	pktlen = m->m_pkthdr.len;
	if (pktlen > sc->sc_bulkout_bufferlen) {
		printf("%s: Packet too large, %d > %d\n",
			USBDEVNAME(sc->sc_dev), pktlen,
			sc->sc_bulkout_bufferlen);
		return (USBD_IOERROR);
	}

	m_copydata(m, 0, pktlen, sc->sc_bulkout_buffer);
	m_freem(m);

	/* Initialise a USB transfer and then schedule it */

	(void) usbd_setup_xfer( sc->sc_bulkout_xfer,
				sc->sc_bulkout_pipe,
				priv,
				sc->sc_bulkout_buffer,
				pktlen,
				USBD_SHORT_XFER_OK,
				UDBP_TIMEOUT,
				udbp_out_transfer_cb);

	err = usbd_transfer(sc->sc_bulkout_xfer);
	if (err && err != USBD_IN_PROGRESS) {
		DPRINTF(("%s: failed to setup out-transfer, %s\n",
			USBDEVNAME(sc->sc_dev), usbd_errstr(err)));
		return(err);
	}

	return (USBD_NORMAL_COMPLETION);
}
예제 #30
0
void
ueagle_loadpage(void *xsc)
{
	struct ueagle_softc *sc = xsc;
	struct usbd_xfer *xfer;
	struct ueagle_block_info bi;
	uint16_t pageno = sc->pageno;
	uint16_t ovl = sc->ovl;
	uint8_t pagecount, blockcount;
	uint16_t blockaddr, blocksize;
	uint32_t pageoffset;
	uint8_t *p;
	int i;

	if (usbd_is_dying(sc->sc_udev))
		return;

	p = sc->dsp;
	pagecount = *p++;

	if (pageno >= pagecount) {
		printf("%s: invalid page number %u requested\n",
		    sc->sc_dev.dv_xname, pageno);
		return;
	}

	p += 4 * pageno;
	pageoffset = UGETDW(p);
	if (pageoffset == 0)
		return;

	p = sc->dsp + pageoffset;
	blockcount = *p++;

	DPRINTF(("%s: sending %u blocks for fw page %u\n",
	    sc->sc_dev.dv_xname, blockcount, pageno));

	if ((xfer = usbd_alloc_xfer(sc->sc_udev)) == NULL) {
		printf("%s: could not allocate xfer\n",
		    sc->sc_dev.dv_xname);
		return;
	}

	USETW(bi.wHdr, UEAGLE_BLOCK_INFO_HDR);
	USETW(bi.wOvl, ovl);
	USETW(bi.wOvlOffset, ovl | 0x8000);

	for (i = 0; i < blockcount; i++) {
		blockaddr = UGETW(p); p += 2;
		blocksize = UGETW(p); p += 2;

		USETW(bi.wSize, blocksize);
		USETW(bi.wAddress, blockaddr);
		USETW(bi.wLast, (i == blockcount - 1) ? 1 : 0);

		/* send block info through the IDMA pipe */
		usbd_setup_xfer(xfer, sc->pipeh_idma, sc, &bi, sizeof bi,
		    USBD_SYNCHRONOUS, UEAGLE_IDMA_TIMEOUT, NULL);
		if (usbd_transfer(xfer) != 0) {
			printf("%s: could not transfer block info\n",
			    sc->sc_dev.dv_xname);
			break;
		}

		/* send block data through the IDMA pipe */
		usbd_setup_xfer(xfer, sc->pipeh_idma, sc, p, blocksize,
		    USBD_SYNCHRONOUS, UEAGLE_IDMA_TIMEOUT, NULL);
		if (usbd_transfer(xfer) != 0) {
			printf("%s: could not transfer block data\n",
			    sc->sc_dev.dv_xname);
			break;
		}

		p += blocksize;
	}

	usbd_free_xfer(xfer);
}