示例#1
0
static int
atausb_bbb_start(struct ata_request *request)
{
    struct atausb_softc *sc = 
	device_get_softc(device_get_parent(request->parent));
    struct ata_channel *ch = device_get_softc(request->parent);

    sc->timeout = (request->timeout * 1000) + 5000;
    USETDW(sc->cbw.signature, CBWSIGNATURE);
    USETDW(sc->cbw.tag, UGETDW(sc->cbw.tag) + 1);
    USETDW(sc->cbw.transfer_length, request->bytecount);
    sc->cbw.flags = (request->flags & ATA_R_READ) ? CBWFLAGS_IN : CBWFLAGS_OUT;
    sc->cbw.lun = ch->unit;
    sc->cbw.length = 16;
    bzero(sc->cbw.cdb, 16);
    bcopy(request->u.atapi.ccb, sc->cbw.cdb, 12); /* XXX SOS */
    sc->state = ATAUSB_S_BBB_COMMAND;
    if (atausb_start(sc, sc->bulkout_pipe, &sc->cbw, sizeof(struct bbb_cbw),
		     0, sc->transfer[ATAUSB_T_BBB_CBW])) {
	request->result = EIO;
        if (atausbdebug)
	    device_printf(request->dev, "cannot setup USB transfer\n");
        atausb_bbb_reset(sc);
	return ATA_OP_FINISHED;
    }
    return ATA_OP_CONTINUES;
}
示例#2
0
usbd_status
uplcom_set_line_coding(struct uplcom_softc *sc, usb_cdc_line_state_t *state)
{
	usb_device_request_t req;
	usbd_status err;

	DPRINTF(("uplcom_set_line_coding: rate=%d fmt=%d parity=%d bits=%d\n",
		UGETDW(state->dwDTERate), state->bCharFormat,
		state->bParityType, state->bDataBits));

	if (memcmp(state, &sc->sc_line_state, UCDC_LINE_STATE_LENGTH) == 0) {
		DPRINTF(("uplcom_set_line_coding: already set\n"));
		return (USBD_NORMAL_COMPLETION);
	}

	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
	req.bRequest = UCDC_SET_LINE_CODING;
	USETW(req.wValue, 0);
	USETW(req.wIndex, sc->sc_iface_number);
	USETW(req.wLength, UCDC_LINE_STATE_LENGTH);

	err = usbd_do_request(sc->sc_udev, &req, state);
	if (err) {
		DPRINTF(("uplcom_set_line_coding: failed, err=%s\n",
			usbd_errstr(err)));
		return (err);
	}

	sc->sc_line_state = *state;

	return (USBD_NORMAL_COMPLETION);
}
示例#3
0
/*
 * Global Item
 */
void
hid_global_item(int tag, uint8_t *buffer, size_t bufsize)
{
	const char *name;
	uint32_t val = 0;
	int i;

	switch (bufsize) {
	case 1:
		val = *buffer;
		break;
	case 2:
		val = UGETW(buffer);
		break;
	case 4:
		val = UGETDW(buffer);
		break;
	default:
		break;
	}

	switch (tag) {
	case HID_GLOBAL_ITEM_USAGE_PAGE:
		for (usage_page = 0, i = 0 ; (size_t)i < bufsize ; i++)
			usage_page |= (uint32_t)(buffer[i] << (8 * i));

		printf("(");

		if ((name = hid_get_page_name(usage_page)) != NULL)
			printf("%s", name);
		else
			printf("%d", usage_page);

		printf(")\n");
		return;
	}

	if (bufsize > 0) {
		if (relative)
			printf(": %d", (int32_t)val);
		else
			printf(": %u", (uint32_t)val);
	}

	printf("\n");
}
示例#4
0
/*------------------------------------------------------------------------*
 *	cdce_ncm_init
 *
 * Return values:
 * 0: Success
 * Else: Failure
 *------------------------------------------------------------------------*/
static uint8_t
cdce_ncm_init(struct cdce_softc *sc)
{
	struct usb_ncm_parameters temp;
	struct usb_device_request req;
	struct usb_ncm_func_descriptor *ufd;
	uint8_t value[8];
	int err;

	ufd = usbd_find_descriptor(sc->sc_ue.ue_udev, NULL,
	    sc->sc_ifaces_index[1], UDESC_CS_INTERFACE, 0 - 1,
	    UCDC_NCM_FUNC_DESC_SUBTYPE, 0 - 1);

	/* verify length of NCM functional descriptor */
	if (ufd != NULL) {
		if (ufd->bLength < sizeof(*ufd))
			ufd = NULL;
		else
			DPRINTFN(1, "Found NCM functional descriptor.\n");
	}

	req.bmRequestType = UT_READ_CLASS_INTERFACE;
	req.bRequest = UCDC_NCM_GET_NTB_PARAMETERS;
	USETW(req.wValue, 0);
	req.wIndex[0] = sc->sc_ifaces_index[1];
	req.wIndex[1] = 0;
	USETW(req.wLength, sizeof(temp));

	err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req,
	    &temp, 0, NULL, 1000 /* ms */);
	if (err)
		return (1);

	/* Read correct set of parameters according to device mode */

	if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) {
		sc->sc_ncm.rx_max = UGETDW(temp.dwNtbInMaxSize);
		sc->sc_ncm.tx_max = UGETDW(temp.dwNtbOutMaxSize);
		sc->sc_ncm.tx_remainder = UGETW(temp.wNdpOutPayloadRemainder);
		sc->sc_ncm.tx_modulus = UGETW(temp.wNdpOutDivisor);
		sc->sc_ncm.tx_struct_align = UGETW(temp.wNdpOutAlignment);
		sc->sc_ncm.tx_nframe = UGETW(temp.wNtbOutMaxDatagrams);
	} else {
		sc->sc_ncm.rx_max = UGETDW(temp.dwNtbOutMaxSize);
		sc->sc_ncm.tx_max = UGETDW(temp.dwNtbInMaxSize);
		sc->sc_ncm.tx_remainder = UGETW(temp.wNdpInPayloadRemainder);
		sc->sc_ncm.tx_modulus = UGETW(temp.wNdpInDivisor);
		sc->sc_ncm.tx_struct_align = UGETW(temp.wNdpInAlignment);
		sc->sc_ncm.tx_nframe = UGETW(temp.wNtbOutMaxDatagrams);
	}

	/* Verify maximum receive length */

	if ((sc->sc_ncm.rx_max < 32) || 
	    (sc->sc_ncm.rx_max > CDCE_NCM_RX_MAXLEN)) {
		DPRINTFN(1, "Using default maximum receive length\n");
		sc->sc_ncm.rx_max = CDCE_NCM_RX_MAXLEN;
	}

	/* Verify maximum transmit length */

	if ((sc->sc_ncm.tx_max < 32) ||
	    (sc->sc_ncm.tx_max > CDCE_NCM_TX_MAXLEN)) {
		DPRINTFN(1, "Using default maximum transmit length\n");
		sc->sc_ncm.tx_max = CDCE_NCM_TX_MAXLEN;
	}

	/* 
	 * Verify that the structure alignment is:
	 * - power of two
	 * - not greater than the maximum transmit length
	 * - not less than four bytes
	 */
	if ((sc->sc_ncm.tx_struct_align < 4) ||
	    (sc->sc_ncm.tx_struct_align != 
	     ((-sc->sc_ncm.tx_struct_align) & sc->sc_ncm.tx_struct_align)) ||
	    (sc->sc_ncm.tx_struct_align >= sc->sc_ncm.tx_max)) {
		DPRINTFN(1, "Using default other alignment: 4 bytes\n");
		sc->sc_ncm.tx_struct_align = 4;
	}

	/* 
	 * Verify that the payload alignment is:
	 * - power of two
	 * - not greater than the maximum transmit length
	 * - not less than four bytes
	 */
	if ((sc->sc_ncm.tx_modulus < 4) ||
	    (sc->sc_ncm.tx_modulus !=
	     ((-sc->sc_ncm.tx_modulus) & sc->sc_ncm.tx_modulus)) ||
	    (sc->sc_ncm.tx_modulus >= sc->sc_ncm.tx_max)) {
		DPRINTFN(1, "Using default transmit modulus: 4 bytes\n");
		sc->sc_ncm.tx_modulus = 4;
	}

	/* Verify that the payload remainder */

	if ((sc->sc_ncm.tx_remainder >= sc->sc_ncm.tx_modulus)) {
		DPRINTFN(1, "Using default transmit remainder: 0 bytes\n");
		sc->sc_ncm.tx_remainder = 0;
	}

	/*
	 * Offset the TX remainder so that IP packet payload starts at
	 * the tx_modulus. This is not too clear in the specification.
	 */

	sc->sc_ncm.tx_remainder = 
	    (sc->sc_ncm.tx_remainder - ETHER_HDR_LEN) &
	    (sc->sc_ncm.tx_modulus - 1);

	/* Verify max datagrams */

	if (sc->sc_ncm.tx_nframe == 0 ||
	    sc->sc_ncm.tx_nframe > (CDCE_NCM_SUBFRAMES_MAX - 1)) {
		DPRINTFN(1, "Using default max "
		    "subframes: %u units\n", CDCE_NCM_SUBFRAMES_MAX - 1);
		/* need to reserve one entry for zero padding */
		sc->sc_ncm.tx_nframe = (CDCE_NCM_SUBFRAMES_MAX - 1);
	}

	/* Additional configuration, will fail in device side mode, which is OK. */

	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
	req.bRequest = UCDC_NCM_SET_NTB_INPUT_SIZE;
	USETW(req.wValue, 0);
	req.wIndex[0] = sc->sc_ifaces_index[1];
	req.wIndex[1] = 0;

	if (ufd != NULL &&
	    (ufd->bmNetworkCapabilities & UCDC_NCM_CAP_MAX_DGRAM)) {
		USETW(req.wLength, 8);
		USETDW(value, sc->sc_ncm.rx_max);
		USETW(value + 4, (CDCE_NCM_SUBFRAMES_MAX - 1));
		USETW(value + 6, 0);
	} else {
		USETW(req.wLength, 4);
		USETDW(value, sc->sc_ncm.rx_max);
 	}

	err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req,
	    &value, 0, NULL, 1000 /* ms */);
	if (err) {
		DPRINTFN(1, "Setting input size "
		    "to %u failed.\n", sc->sc_ncm.rx_max);
	}

	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
	req.bRequest = UCDC_NCM_SET_CRC_MODE;
	USETW(req.wValue, 0);	/* no CRC */
	req.wIndex[0] = sc->sc_ifaces_index[1];
	req.wIndex[1] = 0;
	USETW(req.wLength, 0);

	err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req,
	    NULL, 0, NULL, 1000 /* ms */);
	if (err) {
		DPRINTFN(1, "Setting CRC mode to off failed.\n");
	}

	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
	req.bRequest = UCDC_NCM_SET_NTB_FORMAT;
	USETW(req.wValue, 0);	/* NTB-16 */
	req.wIndex[0] = sc->sc_ifaces_index[1];
	req.wIndex[1] = 0;
	USETW(req.wLength, 0);

	err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req,
	    NULL, 0, NULL, 1000 /* ms */);
	if (err) {
		DPRINTFN(1, "Setting NTB format to 16-bit failed.\n");
	}

	return (0);		/* success */
}
示例#5
0
static void
atausb_bbb_finish(usbd_xfer_handle xfer, usbd_private_handle priv,
		 usbd_status err)
{
    struct atausb_softc *sc = (struct atausb_softc *)priv;
    struct ata_request *request = sc->ata_request;
    usbd_xfer_handle next_xfer;

    /* device_printf(sc->dev, "BBB state %d: %s\n", sc->state,
       usbd_errstr(err)); */

    if (sc->state == ATAUSB_S_DETACH) {
        device_printf(sc->dev, "WARNING - device has been removed\n");
	return;
    }

    switch (sc->state) {
    case ATAUSB_S_BBB_COMMAND:	/* command transport phase */
	if (err) {
            if (atausbdebug)
	        device_printf(sc->dev, "failed to send CBW\n");
	    request->result = EIO;
	    atausb_bbb_reset(sc);
	    return;
	}

	/* next is data transport phase, setup transfer */
	sc->state = ATAUSB_S_BBB_DATA;
	if (request->flags & ATA_R_READ) {
	    if (atausb_start(sc, sc->bulkin_pipe,
			     request->data, request->bytecount,
			     USBD_SHORT_XFER_OK,
			     sc->transfer[ATAUSB_T_BBB_DATA])) {
	        request->result = EIO;
		atausb_bbb_reset(sc);
	    }
	    return;
	}
	if (request->flags & ATA_R_WRITE) {
	    if (atausb_start(sc, sc->bulkout_pipe,
			     request->data, request->bytecount,
			     0, sc->transfer[ATAUSB_T_BBB_DATA])) {
	        request->result = EIO;
		atausb_bbb_reset(sc);
	    }
	    return;
	}
	/* FALLTHROUGH */

    case ATAUSB_S_BBB_DATA:	/* data transport phase */
	if (request->flags & (ATA_R_READ | ATA_R_WRITE)) {
	    usbd_get_xfer_status(xfer, NULL, NULL, &request->donecount, NULL);
	    if (err) {
                if (atausbdebug)
		    device_printf(sc->dev, "data %s count %d failed: %s\n",
		       	          (request->flags & ATA_R_READ?"read":"write"),
		                  request->bytecount, usbd_errstr(err));
		if (err == USBD_STALLED) {
		    atausb_clear_stall(sc,
				       (request->flags & ATA_R_READ ?
					sc->bulkin : sc->bulkout),
			  	       (request->flags & ATA_R_READ ?
			   	        sc->bulkin_pipe : sc->bulkout_pipe),
			  	       ATAUSB_S_BBB_DCLEAR,
			  	       sc->transfer[ATAUSB_T_BBB_DCLEAR]);
		}
		else {
	            request->result = EIO;
		    atausb_bbb_reset(sc);
		}
		return;
	    }
	}
	/* FALLTHROUGH */

    case ATAUSB_S_BBB_DCLEAR:	/* stall clear after data phase */
    case ATAUSB_S_BBB_SCLEAR:	/* stall clear after status phase */
	if (err) {
            if (atausbdebug)
	        device_printf(sc->dev, "bulk%s stall clear failed %s\n",
		   	      (request->flags & ATA_R_READ ? "in" : "out"),
		   	      usbd_errstr(err));
	    request->result = EIO;
	    atausb_bbb_reset(sc);
	    return;
	}

	if (sc->state == ATAUSB_S_BBB_COMMAND ||
	    sc->state == ATAUSB_S_BBB_DATA ||
	    sc->state == ATAUSB_S_BBB_DCLEAR) {
	    /* first attempt on status transport phase setup transfer */
	    sc->state = ATAUSB_S_BBB_STATUS1;
	    next_xfer = sc->transfer[ATAUSB_T_BBB_CSW1];
	}
	else {
	    /* second attempt of fetching status */
	    sc->state = ATAUSB_S_BBB_STATUS2;
	    next_xfer = sc->transfer[ATAUSB_T_BBB_CSW2];
	}
	if (atausb_start(sc, sc->bulkin_pipe, &sc->csw, sizeof(struct bbb_csw),
			 USBD_SHORT_XFER_OK, next_xfer)) {
	    request->result = EIO;
	    atausb_bbb_reset(sc);
	}
	return;

    case ATAUSB_S_BBB_STATUS1:	/* status transfer first attempt */
    case ATAUSB_S_BBB_STATUS2:	/* status transfer second attempt */
	if (err) {
            if (atausbdebug)
	        device_printf(sc->dev, "cannot get CSW, %s%s\n",
			      usbd_errstr(err),
		   	      sc->state == ATAUSB_S_BBB_STATUS1 ? ", retry":"");
	    if (sc->state == ATAUSB_S_BBB_STATUS1) {
		atausb_clear_stall(sc, sc->bulkin, sc->bulkin_pipe,
				   ATAUSB_S_BBB_SCLEAR,
				   sc->transfer[ATAUSB_T_BBB_SCLEAR]);
	    }
	    else {
	        request->result = EIO;
		atausb_bbb_reset(sc);
	    }
	    return;
	}

	int residue = UGETDW(sc->csw.residue);

	if (!residue &&
	    (request->bytecount - request->donecount))
	    residue = request->bytecount - request->donecount;

	/* check CSW and handle eventual error */
	if (UGETDW(sc->csw.signature) != CSWSIGNATURE) {
            if (atausbdebug)
	        device_printf(sc->dev, "bad CSW signature 0x%08x != 0x%08x\n",
		              UGETDW(sc->csw.signature), CSWSIGNATURE);
	    request->result = EIO;
	    atausb_bbb_reset(sc);
	    return;
	}
	else if (UGETDW(sc->csw.tag) != UGETDW(sc->cbw.tag)) {
            if (atausbdebug)
	        device_printf(sc->dev, "bad CSW tag %d != %d\n",
		              UGETDW(sc->csw.tag), UGETDW(sc->cbw.tag));
	    request->result = EIO;
	    atausb_bbb_reset(sc);
	    return;
	}
	else if (sc->csw.status > CSWSTATUS_PHASE) {
            if (atausbdebug)
	        device_printf(sc->dev, "bad CSW status %d > %d\n",
		    	      sc->csw.status, CSWSTATUS_PHASE);
	    request->result = EIO;
	    atausb_bbb_reset(sc);
	    return;
	}
	else if (sc->csw.status == CSWSTATUS_PHASE) {
            if (atausbdebug)
	        device_printf(sc->dev, "phase error residue = %d\n", residue);
	    request->result = EIO;
	    atausb_bbb_reset(sc);
	    return;
	}
	else if (request->donecount > request->bytecount) {
            if (atausbdebug)
	        device_printf(sc->dev, "buffer overrun %d > %d",
		             request->donecount, request->bytecount);
	    request->result = EIO;
	    atausb_bbb_reset(sc);
	    return;
	}
	else if (sc->csw.status == CSWSTATUS_FAILED) {
            if (atausbdebug)
	        device_printf(sc->dev, "CSWSTATUS_FAILED\n");
	    request->error = ATA_E_ATAPI_SENSE_MASK ;
	    sc->state = ATAUSB_S_IDLE;
	    ata_interrupt(device_get_softc(request->parent));
	    return;
	}
	else {
	    sc->state = ATAUSB_S_IDLE;
	    ata_interrupt(device_get_softc(request->parent));
	    return;
	}
	/* NOT REACHED */

    case ATAUSB_S_BBB_RESET1:
	if (err)
            if (atausbdebug)
	        device_printf(sc->dev,
			      "BBB reset failure: %s\n", usbd_errstr(err));
	atausb_clear_stall(sc, sc->bulkin, sc->bulkin_pipe,
			   ATAUSB_S_BBB_RESET2,
			   sc->transfer[ATAUSB_T_BBB_RESET2]);
	return;

    case ATAUSB_S_BBB_RESET2:
	if (err)
            if (atausbdebug)
	        device_printf(sc->dev, "BBB bulkin clear stall failure: %s\n",
		  	      usbd_errstr(err));
	atausb_clear_stall(sc, sc->bulkout, sc->bulkout_pipe,
			   ATAUSB_S_BBB_RESET3,
			   sc->transfer[ATAUSB_T_BBB_RESET3]);
	return;

    case ATAUSB_S_BBB_RESET3:
	if (err)
            if (atausbdebug)
	        device_printf(sc->dev, "BBB bulk-out clear stall failure: %s\n",
		   	      usbd_errstr(err));
	sc->state = ATAUSB_S_IDLE;
	if (request) {
	    if (err)
	        request->result = ENXIO;
	    else
	        request->result = EIO;
	    ata_interrupt(device_get_softc(request->parent));
	}
	return;

    default:
        if (atausbdebug)
	    device_printf(sc->dev, "unknown state %d", sc->state);
    }
}
示例#6
0
static uint8_t
do_msc_cmd(uint8_t *pcmd, uint8_t cmdlen, void *pdata, uint32_t datalen,
    uint8_t isread, uint8_t isshort, uint8_t lun, uint8_t flags)
{
	umass_bbb_cbw_t cbw;
	umass_bbb_csw_t csw;
	struct libusb20_transfer *xfer_io;
	uint32_t actlen;
	uint32_t timeout;
	int error;

	memset(&cbw, 0, sizeof(cbw));

	USETDW(cbw.dCBWSignature, xfer_wrapper_sig);
	USETDW(cbw.dCBWTag, xfer_current_id);
	xfer_current_id++;
	USETDW(cbw.dCBWDataTransferLength, datalen);
	cbw.bCBWFlags = (isread ? CBWFLAGS_IN : CBWFLAGS_OUT);
	cbw.bCBWLUN = lun;
	cbw.bCDBLength = cmdlen;
	bcopy(pcmd, cbw.CBWCDB, cmdlen);

	actlen = 0;

	timeout = ((datalen + 299999) / 300000) * 1000;
	timeout += 5000;

	if ((error = libusb20_tr_bulk_intr_sync(xfer_out,
	    &cbw, sizeof(cbw), &actlen, TIMEOUT_FILTER(1000)))) {
		printf("ERROR: CBW reception: %d\n", error);
		do_msc_reset(lun);
		return (1);
	}
	if (actlen != sizeof(cbw)) {
		printf("ERROR: CBW length: %d != %d\n",
		    actlen, (int)sizeof(cbw));
		do_msc_reset(lun);
		return (1);
	}
	if (flags & 1)
		datalen /= 2;

	if (datalen != 0) {
		xfer_io = isread ? xfer_in : xfer_out;

		if ((error = libusb20_tr_bulk_intr_sync(xfer_io,
		    pdata, datalen, &actlen, TIMEOUT_FILTER(timeout)))) {
			printf("ERROR: Data transfer: %d\n", error);
			do_msc_reset(lun);
			return (1);
		}
		if ((actlen != datalen) && (!isshort)) {
			printf("ERROR: Short data: %d of %d bytes\n",
			    actlen, datalen);
			do_msc_reset(lun);
			return (1);
		}
	}
	actlen = 0;
	timeout = 8;

	do {
		error = libusb20_tr_bulk_intr_sync(xfer_in, &csw,
		    sizeof(csw), &actlen, TIMEOUT_FILTER(1000));
		if (error) {
			if (error == LIBUSB20_TRANSFER_TIMED_OUT) {
				printf("TIMEOUT: Trying to get CSW again. "
				    "%d tries left.\n", timeout);
			} else {
				break;
			}
		} else {
			break;
		}
	} while (--timeout);

	if (error) {
		libusb20_tr_clear_stall_sync(xfer_in);
		error = libusb20_tr_bulk_intr_sync(xfer_in, &csw,
		    sizeof(csw), &actlen, TIMEOUT_FILTER(1000));
		if (error) {
			libusb20_tr_clear_stall_sync(xfer_in);
			printf("ERROR: Could not read CSW: Stalled or "
			    "timeout (%d).\n", error);
			do_msc_reset(lun);
			return (1);
		}
	}
	if (UGETDW(csw.dCSWSignature) != CSWSIGNATURE) {
		printf("ERROR: Wrong CSW signature\n");
		do_msc_reset(lun);
		return (1);
	}
	if (actlen != sizeof(csw)) {
		printf("ERROR: Wrong CSW length: %d != %d\n",
		    actlen, (int)sizeof(csw));
		do_msc_reset(lun);
		return (1);
	}
	if (csw.bCSWStatus != 0) {
		printf("ERROR: CSW status: %d\n", (int)csw.bCSWStatus);
		return (1);
	} else {
		stats.xfer_success++;
		return (0);
	}
}
示例#7
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__));
}
示例#8
0
void
ueagle_loadpage(void *xsc)
{
	struct ueagle_softc *sc = xsc;
	usbd_xfer_handle 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, 0,
		    UEAGLE_IDMA_TIMEOUT, NULL);
		if (usbd_sync_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, 0,
		    UEAGLE_IDMA_TIMEOUT, NULL);
		if (usbd_sync_transfer(xfer) != 0) {
			printf("%s: could not transfer block data\n",
			    sc->sc_dev.dv_xname);
			break;
		}

		p += blocksize;
	}

	usbd_free_xfer(xfer);
}