コード例 #1
0
ファイル: usb_storage.c プロジェクト: xmyth/pmon-osolution
/* FIXME: we also need a CBI_command which sets up the completion
 * interrupt, and waits for it
 */
int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
{
    int result = 0;
    int dir_in,retry;
    unsigned int pipe;
    unsigned long status;

    retry=5;
    dir_in=US_DIRECTION(srb->cmd[0]);

    if(dir_in)
        pipe=usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
    else
        pipe=usb_sndbulkpipe(us->pusb_dev, us->ep_out);
    while(retry--) {
        USB_STOR_PRINTF("CBI gets a command: Try %d\n",5-retry);
#ifdef USB_STOR_DEBUG
        usb_show_srb(srb);
#endif
        /* let's send the command via the control pipe */
        result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
                                 US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
                                 0, us->ifnum,
                                 srb->cmd, srb->cmdlen, USB_CNTL_TIMEOUT*5);
        USB_STOR_PRINTF("CB_transport: control msg returned %d, status %X\n",result,us->pusb_dev->status);
        /* check the return code for the command */
        if (result < 0) {
            if(us->pusb_dev->status & USB_ST_STALLED) {
                status=us->pusb_dev->status;
                USB_STOR_PRINTF(" stall during command found, clear pipe\n");
                usb_clear_halt(us->pusb_dev,  usb_sndctrlpipe(us->pusb_dev,0));
                us->pusb_dev->status=status;
            }
            USB_STOR_PRINTF(" error during command %02X Stat = %X\n",srb->cmd[0],us->pusb_dev->status);
            return result;
        }
        /* transfer the data payload for this command, if one exists*/

        USB_STOR_PRINTF("CB_transport: control msg returned %d, direction is %s to go 0x%lx\n",result,dir_in ? "IN" : "OUT",srb->datalen);
        if (srb->datalen) {
            result = us_one_transfer(us, pipe, (char *)srb->pdata,srb->datalen);
            USB_STOR_PRINTF("CBI attempted to transfer data, result is %d status %lX, len %d\n", result,us->pusb_dev->status,us->pusb_dev->act_len);
            if(!(us->pusb_dev->status & USB_ST_NAK_REC))
                break;
        } /* if (srb->datalen) */
        else
            break;
    }
    /* return result */

    return result;
}
コード例 #2
0
/*
 * Set up the command for a BBB device. Note that the actual SCSI
 * command is copied into cbw.CBWCDB.
 */
static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
{
	int result;
	int actlen;
	int dir_in;
	unsigned int pipe;
	ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_cbw_t, cbw_buf, 1);
	umass_bbb_cbw_t *cbw = (umass_bbb_cbw_t *)KSEG1ADDR(cbw_buf);

	dir_in = US_DIRECTION(srb->cmd[0]);

#ifdef BBB_COMDAT_TRACE
	printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
		dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
		srb->pdata);
	if (srb->cmdlen) {
		for (result = 0; result < srb->cmdlen; result++)
			printf("cmd[%d] %#x ", result, srb->cmd[result]);
		printf("\n");
	}
#endif
	/* sanity checks */
	if (!(srb->cmdlen <= CBWCDBLENGTH)) {
		USB_STOR_PRINTF("usb_stor_BBB_comdat:cmdlen too large\n");
		return -1;
	}

	/* always OUT to the ep */
	pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);

	cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
	cbw->dCBWTag = cpu_to_le32(CBWTag++);
	cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
	cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
	cbw->bCBWLUN = srb->lun;
	cbw->bCDBLength = srb->cmdlen;
	/* copy the command data into the CBW command data buffer */
	/* DST SRC LEN!!! */
	memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
	result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
			      &actlen, USB_CNTL_TIMEOUT * 5);
	if (result < 0)
		USB_STOR_PRINTF("usb_stor_BBB_comdat:usb_bulk_msg error\n");
	return result;
}
コード例 #3
0
ファイル: usb_storage.c プロジェクト: RAR/apc-8750
/*
 * Set up the command for a BBB device. Note that the actual SCSI
 * command is copied into cbw.CBWCDB.
 */
int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
{
    int result;
    int actlen;
    int dir_in;
    unsigned int pipe;
    umass_bbb_cbw_t cbw;

    dir_in = US_DIRECTION(srb->cmd[0]);

#ifdef BBB_COMDAT_TRACE
    printf("dir %d lun %d cmdlen %d cmd %p datalen %d pdata %p\n", dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen, srb->pdata);
    if (srb->cmdlen) {
        for(result = 0; result < srb->cmdlen; result++)
            printf("cmd[%d] %#x ", result, srb->cmd[result]);
        printf("\n");
    }
    printf(" us->ep_in %d us->ep_out %d dir_in %d \n", us->ep_in, us->ep_out,dir_in);

#endif
    /* sanity checks */
    if (!(srb->cmdlen <= CBWCDBLENGTH)) {
        USB_STOR_PRINTF("usb_stor_BBB_comdat:cmdlen too large\n");
        return -1;
    }

    /* always OUT to the ep */
    pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);

    cbw.dCBWSignature = swap_32(CBWSIGNATURE);
    cbw.dCBWTag = swap_32(CBWTag++);
    cbw.dCBWDataTransferLength = swap_32(srb->datalen);
    cbw.bCBWFlags = (dir_in? CBWFLAGS_IN : CBWFLAGS_OUT);
    cbw.bCBWLUN = srb->lun;
    cbw.bCDBLength = srb->cmdlen;
    /* copy the command data into the CBW command data buffer */
    /* DST SRC LEN!!! */
    memcpy(cbw.CBWCDB, srb->cmd, 0x10);
    result = usb_bulk_msg(us->pusb_dev, pipe, &cbw, UMASS_BBB_CBW_SIZE, &actlen, USB_CNTL_TIMEOUT);//Charles

    return 0 ;
}
コード例 #4
0
ファイル: usb_storage.c プロジェクト: xmyth/pmon-osolution
int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
{
    int result, retry;
    int dir_in;
    int actlen, data_actlen;
    unsigned int pipe, pipein, pipeout;
#ifdef BBB_XPORT_TRACE
    unsigned char *ptr;
    int index;
#endif

    dir_in = US_DIRECTION(srb->cmd[0]);

    /* COMMAND phase */
    USB_STOR_PRINTF("COMMAND phase\n");
    result = usb_stor_BBB_comdat(srb, us);
    if (result < 0) {
        USB_STOR_PRINTF("failed to send CBW status %ld\n",
                        us->pusb_dev->status);
        usb_stor_BBB_reset(us);
        return USB_STOR_TRANSPORT_FAILED;
    }
    pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
    pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
    /* DATA phase + error handling */
    data_actlen = 0;
    /* no data, go immediately to the STATUS phase */
    if (srb->datalen == 0)
        goto st;
    USB_STOR_PRINTF("DATA phase\n");
    if (dir_in)
        pipe = pipein;
    else
        pipe = pipeout;

    result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen, &data_actlen, USB_CNTL_TIMEOUT*5);
    /* special handling of STALL in DATA phase */
    if((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
        USB_STOR_PRINTF("DATA:stall\n");
        /* clear the STALL on the endpoint */
        result = usb_stor_BBB_clear_endpt_stall(us, dir_in? us->ep_in : us->ep_out);
        if (result >= 0)
            /* continue on to STATUS phase */
            goto st;
    }
    if (result < 0) {
        USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
                        us->pusb_dev->status);
        usb_stor_BBB_reset(us);
        return USB_STOR_TRANSPORT_FAILED;
    }
#ifdef BBB_XPORT_TRACE
    for (index = 0; index < data_actlen; index++)
        printf("pdata[%d] %#x ", index, srb->pdata[index]);
    printf("\n");
#endif
    /* STATUS phase + error handling */
st:
    retry = 0;
again:
    USB_STOR_PRINTF("STATUS phase\n");

    result = usb_bulk_msg(us->pusb_dev, pipein, &csw, UMASS_BBB_CSW_SIZE,
                          &actlen, USB_CNTL_TIMEOUT*5);

    /* special handling of STALL in STATUS phase */
    if((result < 0) && (retry < 1) && (us->pusb_dev->status & USB_ST_STALLED)) {
        USB_STOR_PRINTF("STATUS:stall\n");
        /* clear the STALL on the endpoint */
        result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
        if (result >= 0 && (retry++ < 1))
            /* do a retry */
            goto again;
    }
    if (result < 0) {
        USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
                        us->pusb_dev->status);
        usb_stor_BBB_reset(us);
        return USB_STOR_TRANSPORT_FAILED;
    }
#ifdef BBB_XPORT_TRACE
    ptr = (unsigned char *)&csw;
    for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
        printf("ptr[%d] %#x ", index, ptr[index]);
    printf("\n");
#endif
    /* misuse pipe to get the residue */
    pipe = swap_32(csw.dCSWDataResidue);
    if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
        pipe = srb->datalen - data_actlen;
    if (CSWSIGNATURE != swap_32(csw.dCSWSignature)) {
        USB_STOR_PRINTF("!CSWSIGNATURE\n");
        usb_stor_BBB_reset(us);
        return USB_STOR_TRANSPORT_FAILED;
    } else if ((CBWTag - 1) != swap_32(csw.dCSWTag)) {
        USB_STOR_PRINTF("!Tag\n");
        usb_stor_BBB_reset(us);
        return USB_STOR_TRANSPORT_FAILED;
    } else if (csw.bCSWStatus > CSWSTATUS_PHASE) {
        USB_STOR_PRINTF(">PHASE\n");
        usb_stor_BBB_reset(us);
        return USB_STOR_TRANSPORT_FAILED;
    } else if (csw.bCSWStatus == CSWSTATUS_PHASE) {
        USB_STOR_PRINTF("=PHASE\n");
        usb_stor_BBB_reset(us);
        return USB_STOR_TRANSPORT_FAILED;
    } else if (data_actlen > srb->datalen) {
        USB_STOR_PRINTF("transferred %dB instead of %dB\n",
                        data_actlen, srb->datalen);
        return USB_STOR_TRANSPORT_FAILED;
    } else if (csw.bCSWStatus == CSWSTATUS_FAILED) {
        USB_STOR_PRINTF("FAILED\n");
        return USB_STOR_TRANSPORT_FAILED;
    }

    return result;
}
コード例 #5
0
ファイル: transport.c プロジェクト: cpdesign/barebox
int usb_stor_Bulk_transport(ccb *srb, struct us_data *us)
{
	struct bulk_cb_wrap cbw;
	struct bulk_cs_wrap csw;
	int actlen, data_actlen;
	int result;
	unsigned int residue;
	unsigned int pipein = usb_rcvbulkpipe(us->pusb_dev, us->recv_bulk_ep);
	unsigned int pipeout = usb_sndbulkpipe(us->pusb_dev, us->send_bulk_ep);
	int dir_in = US_DIRECTION(srb->cmd[0]);

	srb->trans_bytes = 0;

	/* set up the command wrapper */
	cbw.Signature = cpu_to_le32(US_BULK_CB_SIGN);
	cbw.DataTransferLength = cpu_to_le32(srb->datalen);
	cbw.Flags = (dir_in ? US_BULK_FLAG_IN : US_BULK_FLAG_OUT);
	cbw.Tag = ++cbw_tag;
	cbw.Lun = srb->lun;
	cbw.Length = srb->cmdlen;

	/* copy the command payload */
	memcpy(cbw.CDB, srb->cmd, cbw.Length);

	/* send it to out endpoint */
	US_DEBUGP("Bulk Command S 0x%x T 0x%x L %d F %d Trg %d LUN %d CL %d\n",
	                le32_to_cpu(cbw.Signature), cbw.Tag,
	                le32_to_cpu(cbw.DataTransferLength), cbw.Flags,
	                (cbw.Lun >> 4), (cbw.Lun & 0x0F),
	                cbw.Length);
	result = usb_bulk_msg(us->pusb_dev, pipeout, &cbw, US_BULK_CB_WRAP_LEN,
			      &actlen, USB_BULK_TO);
	US_DEBUGP("Bulk command transfer result=%d\n", result);
	if (result < 0) {
		usb_stor_Bulk_reset(us);
		return USB_STOR_TRANSPORT_FAILED;
	}

	/* DATA STAGE */
	/* send/receive data payload, if there is any */

	wait_ms(1);

	data_actlen = 0;
	if (srb->datalen) {
		unsigned int pipe = dir_in ? pipein : pipeout;
		result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata,
		                      srb->datalen, &data_actlen, USB_BULK_TO);
		US_DEBUGP("Bulk data transfer result 0x%x\n", result);
		/* special handling of STALL in DATA phase */
		if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
			US_DEBUGP("DATA: stall\n");
			/* clear the STALL on the endpoint */
			result = usb_stor_Bulk_clear_endpt_stall(us, pipe);
		}
		if (result < 0) {
			US_DEBUGP("Device status: %lx\n", us->pusb_dev->status);
			usb_stor_Bulk_reset(us);
			return USB_STOR_TRANSPORT_FAILED;
		}
	}

	/* STATUS phase + error handling */
	US_DEBUGP("Attempting to get CSW...\n");
	result = usb_bulk_msg(us->pusb_dev, pipein, &csw, US_BULK_CS_WRAP_LEN,
	                      &actlen, USB_BULK_TO);

	/* did the endpoint stall? */
	if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
		US_DEBUGP("STATUS: stall\n");
		/* clear the STALL on the endpoint */
		result = usb_stor_Bulk_clear_endpt_stall(us, pipein);
		if (result >= 0) {
			US_DEBUGP("Attempting to get CSW...\n");
			result = usb_bulk_msg(us->pusb_dev, pipein,
			                      &csw, US_BULK_CS_WRAP_LEN,
			                      &actlen, USB_BULK_TO);
		}
	}

	if (result < 0) {
		US_DEBUGP("Device status: %lx\n", us->pusb_dev->status);
		usb_stor_Bulk_reset(us);
		return USB_STOR_TRANSPORT_FAILED;
	}

	/* check bulk status */
	residue = le32_to_cpu(csw.Residue);
	US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
	          le32_to_cpu(csw.Signature), csw.Tag, residue, csw.Status);
	if (csw.Signature != cpu_to_le32(US_BULK_CS_SIGN)) {
		US_DEBUGP("Bad CSW signature\n");
		usb_stor_Bulk_reset(us);
		return USB_STOR_TRANSPORT_FAILED;
	} else if (csw.Tag != cbw_tag) {
		US_DEBUGP("Mismatching tag\n");
		usb_stor_Bulk_reset(us);
		return USB_STOR_TRANSPORT_FAILED;
	} else if (csw.Status >= US_BULK_STAT_PHASE) {
		US_DEBUGP("Status >= phase\n");
		usb_stor_Bulk_reset(us);
		return USB_STOR_TRANSPORT_ERROR;
	} else if (residue > srb->datalen) {
		US_DEBUGP("residue (%uB) > req data (%luB)\n",
		          residue, srb->datalen);
		return USB_STOR_TRANSPORT_FAILED;
	} else if (csw.Status == US_BULK_STAT_FAIL) {
		US_DEBUGP("FAILED\n");
		return USB_STOR_TRANSPORT_FAILED;
	}
	srb->trans_bytes = min(srb->datalen - residue, (ulong)data_actlen);

	return 0;
}