Пример #1
0
static int
freecom_writedata (struct scsi_cmnd *srb, struct us_data *us,
                   int unsigned ipipe, unsigned int opipe, int count)
{
    struct freecom_xfer_wrap *fxfr =
        (struct freecom_xfer_wrap *) us->iobuf;
    int result;

    fxfr->Type = FCM_PACKET_OUTPUT | 0x00;
    fxfr->Timeout = 0;    /* Short timeout for debugging. */
    fxfr->Count = cpu_to_le32 (count);
    memset (fxfr->Pad, 0, sizeof (fxfr->Pad));

    US_DEBUGP("Write data Freecom! (c=%d)\n", count);

    /* Issue the transfer command. */
    result = usb_stor_bulk_transfer_buf (us, opipe, fxfr,
                                         FCM_PACKET_LENGTH, NULL);
    if (result != USB_STOR_XFER_GOOD) {
        US_DEBUGP ("Freecom writedata transport error\n");
        return USB_STOR_TRANSPORT_ERROR;
    }

    /* Now transfer all of our blocks. */
    US_DEBUGP("Start of write\n");
    result = usb_stor_bulk_transfer_sg(us, opipe, srb->request_buffer,
                                       count, srb->use_sg, &srb->resid);

    US_DEBUGP("freecom_writedata done!\n");
    if (result > USB_STOR_XFER_SHORT)
        return USB_STOR_TRANSPORT_ERROR;
    return USB_STOR_TRANSPORT_GOOD;
}
Пример #2
0
static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg)
{
	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
	struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;

	int result;
	unsigned int residue;
	unsigned int cswlen = 0, partial = 0;
	unsigned int transfer_length = bcb->DataTransferLength;

	/* US_DEBUGP("transport --- ene_send_scsi_cmd\n"); */
	/* send cmd to out endpoint */
	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
					    bcb, US_BULK_CB_WRAP_LEN, NULL);
	if (result != USB_STOR_XFER_GOOD) {
		US_DEBUGP("send cmd to out endpoint fail ---\n");
		return USB_STOR_TRANSPORT_ERROR;
	}

	if (buf) {
		unsigned int pipe = fDir;

		if (fDir  == FDIR_READ)
			pipe = us->recv_bulk_pipe;
		else
			pipe = us->send_bulk_pipe;

		/* Bulk */
		if (use_sg) {
			result = usb_stor_bulk_srb(us, pipe, us->srb);
		} else {
			result = usb_stor_bulk_transfer_sg(us, pipe, buf,
						transfer_length, 0, &partial);
		}
		if (result != USB_STOR_XFER_GOOD) {
			US_DEBUGP("data transfer fail ---\n");
			return USB_STOR_TRANSPORT_ERROR;
		}
	}

	/* Get CSW for device status */
	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs,
					    US_BULK_CS_WRAP_LEN, &cswlen);

	if (result == USB_STOR_XFER_SHORT && cswlen == 0) {
		US_DEBUGP("Received 0-length CSW; retrying...\n");
		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
					    bcs, US_BULK_CS_WRAP_LEN, &cswlen);
	}

	if (result == USB_STOR_XFER_STALLED) {
		/* get the status again */
		US_DEBUGP("Attempting 
Пример #3
0
/*
 * Control/Bulk transport
 */
int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
{
	unsigned int transfer_length = srb->request_bufflen;
	int result;

	/* COMMAND STAGE */
	/* let's send the command via the control pipe */
	result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
				      US_CBI_ADSC, 
				      USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, 
				      us->ifnum, srb->cmnd, srb->cmd_len);

	/* check the return code for the command */
	US_DEBUGP("Call to usb_stor_ctrl_transfer() returned %d\n", result);

	/* if we stalled the command, it means command failed */
	if (result == USB_STOR_XFER_STALLED) {
		return USB_STOR_TRANSPORT_FAILED;
	}

	/* Uh oh... serious problem here */
	if (result != USB_STOR_XFER_GOOD) {
		return USB_STOR_TRANSPORT_ERROR;
	}

	/* DATA STAGE */
	/* transfer the data payload for this command, if one exists*/
	if (transfer_length) {
		unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
				us->recv_bulk_pipe : us->send_bulk_pipe;
		result = usb_stor_bulk_transfer_sg(us, pipe,
					srb->request_buffer, transfer_length,
					srb->use_sg, &srb->resid);
		US_DEBUGP("CB data stage result is 0x%x\n", result);

		/* if we stalled the data transfer it means command failed */
		if (result == USB_STOR_XFER_STALLED)
			return USB_STOR_TRANSPORT_FAILED;
		if (result > USB_STOR_XFER_STALLED)
			return USB_STOR_TRANSPORT_ERROR;
	}

	/* STATUS STAGE */
	/* NOTE: CB does not have a status stage.  Silly, I know.  So
	 * we have to catch this at a higher level.
	 */
	return USB_STOR_TRANSPORT_GOOD;
}
Пример #4
0
int usb_stor_CBI_transport(struct scsi_cmnd *srb, struct us_data *us)
{
	unsigned int transfer_length = srb->request_bufflen;
	unsigned int pipe = 0;
	int result;

	/* COMMAND STAGE */
	/* let's send the command via the control pipe */
	result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
				      US_CBI_ADSC, 
				      USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, 
				      us->ifnum, srb->cmnd, srb->cmd_len);

	/* check the return code for the command */
	US_DEBUGP("Call to usb_stor_ctrl_transfer() returned %d\n", result);

	/* if we stalled the command, it means command failed */
	if (result == USB_STOR_XFER_STALLED) {
		return USB_STOR_TRANSPORT_FAILED;
	}

	/* Uh oh... serious problem here */
	if (result != USB_STOR_XFER_GOOD) {
		return USB_STOR_TRANSPORT_ERROR;
	}

	/* DATA STAGE */
	/* transfer the data payload for this command, if one exists*/
	if (transfer_length) {
		pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
				us->recv_bulk_pipe : us->send_bulk_pipe;
		result = usb_stor_bulk_transfer_sg(us, pipe,
					srb->request_buffer, transfer_length,
					srb->use_sg, &srb->resid);
		US_DEBUGP("CBI data stage result is 0x%x\n", result);

		/* if we stalled the data transfer it means command failed */
		if (result == USB_STOR_XFER_STALLED)
			return USB_STOR_TRANSPORT_FAILED;
		if (result > USB_STOR_XFER_STALLED)
			return USB_STOR_TRANSPORT_ERROR;
	}

	/* STATUS STAGE */
	result = usb_stor_intr_transfer(us, us->iobuf, 2);
	US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", 
			us->iobuf[0], us->iobuf[1]);
	if (result != USB_STOR_XFER_GOOD)
		return USB_STOR_TRANSPORT_ERROR;

	/* UFI gives us ASC and ASCQ, like a request sense
	 *
	 * REQUEST_SENSE and INQUIRY don't affect the sense data on UFI
	 * devices, so we ignore the information for those commands.  Note
	 * that this means we could be ignoring a real error on these
	 * commands, but that can't be helped.
	 */
	if (us->subclass == US_SC_UFI) {
		if (srb->cmnd[0] == REQUEST_SENSE ||
		    srb->cmnd[0] == INQUIRY)
			return USB_STOR_TRANSPORT_GOOD;
		if (us->iobuf[0])
			goto Failed;
		return USB_STOR_TRANSPORT_GOOD;
	}

	/* If not UFI, we interpret the data as a result code 
	 * The first byte should always be a 0x0.
	 *
	 * Some bogus devices don't follow that rule.  They stuff the ASC
	 * into the first byte -- so if it's non-zero, call it a failure.
	 */
	if (us->iobuf[0]) {
		_VMKLNX_USB_STOR_MSG("CBI IRQ data showed reserved bType 0x%x\n",
				us->srb, us->iobuf[0]);
		US_DEBUGP("CBI IRQ data showed reserved bType 0x%x\n",
				us->iobuf[0]);
		goto Failed;

	}

	/* The second byte & 0x0F should be 0x0 for good, otherwise error */
	switch (us->iobuf[1] & 0x0F) {
		case 0x00: 
			return USB_STOR_TRANSPORT_GOOD;
		case 0x01: 
			goto Failed;
	}
	return USB_STOR_TRANSPORT_ERROR;

	/* the CBI spec requires that the bulk pipe must be cleared
	 * following any data-in/out command failure (section 2.4.3.1.3)
	 */
  Failed:
	if (pipe)
		usb_stor_clear_halt(us, pipe);
	return USB_STOR_TRANSPORT_FAILED;
}
Пример #5
0
int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
{
	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
	struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
	unsigned int transfer_length = srb->request_bufflen;
	unsigned int residue;
	int result;
	int fake_sense = 0;
	unsigned int cswlen;
	unsigned int cbwlen = US_BULK_CB_WRAP_LEN;

	/* Take care of BULK32 devices; set extra byte to 0 */
	if ( unlikely(us->flags & US_FL_BULK32)) {
		cbwlen = 32;
		us->iobuf[31] = 0;
	}

	/* set up the command wrapper */
	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
	bcb->DataTransferLength = cpu_to_le32(transfer_length);
	bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0;
	bcb->Tag = ++us->tag;
	bcb->Lun = srb->device->lun;
	if (us->flags & US_FL_SCM_MULT_TARG)
		bcb->Lun |= srb->device->id << 4;
	bcb->Length = srb->cmd_len;

	/* copy the command payload */
	memset(bcb->CDB, 0, sizeof(bcb->CDB));
	memcpy(bcb->CDB, srb->cmnd, bcb->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(bcb->Signature), bcb->Tag,
			le32_to_cpu(bcb->DataTransferLength), bcb->Flags,
			(bcb->Lun >> 4), (bcb->Lun & 0x0F), 
			bcb->Length);
	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
				bcb, cbwlen, NULL);
	_VMKLNX_USB_STOR_MSG("Bulk command transfer result=%d\n", srb, result);
	US_DEBUGP("Bulk command transfer result=%d\n", result);
	if (result != USB_STOR_XFER_GOOD)
		return USB_STOR_TRANSPORT_ERROR;

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

	/* Some USB-IDE converter chips need a 100us delay between the
	 * command phase and the data phase.  Some devices need a little
	 * more than that, probably because of clock rate inaccuracies. */
	if (unlikely(us->flags & US_FL_GO_SLOW))
		udelay(125);

#if defined(__VMKLNX__)
	if (!in_interrupt() &&
	    VMKLNX_STRESS_COUNTER(stressUSBStorageDelaySCSIDataPhase)) {
		// XXX make sleep duration a random value?
		info("Sleeping for 5 seconds to delay USB SCSI data phase");
		ssleep(5);
		dbg("Done sleeping; proceeding with USB SCSI data phase");
	}
#endif /* __VMKLNX__ */

	if (transfer_length) {
		unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
				us->recv_bulk_pipe : us->send_bulk_pipe;
		result = usb_stor_bulk_transfer_sg(us, pipe,
					srb->request_buffer, transfer_length,
					srb->use_sg, &srb->resid);
		_VMKLNX_USB_STOR_MSG("Bulk data transfer result 0x%x\n", srb, result);
		US_DEBUGP("Bulk data transfer result 0x%x\n", result);
		if (result == USB_STOR_XFER_ERROR)
			return USB_STOR_TRANSPORT_ERROR;

		/* If the device tried to send back more data than the
		 * amount requested, the spec requires us to transfer
		 * the CSW anyway.  Since there's no point retrying the
		 * the command, we'll return fake sense data indicating
		 * Illegal Request, Invalid Field in CDB.
		 */
		if (result == USB_STOR_XFER_LONG)
			fake_sense = 1;
	}

	/* See flow chart on pg 15 of the Bulk Only Transport spec for
	 * an explanation of how this code works.
	 */

	/* get CSW for device status */
	US_DEBUGP("Attempting to get CSW...\n");
	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
				bcs, US_BULK_CS_WRAP_LEN, &cswlen);

	/* Some broken devices add unnecessary zero-length packets to the
	 * end of their data transfers.  Such packets show up as 0-length
	 * CSWs.  If we encounter such a thing, try to read the CSW again.
	 */
	if (result == USB_STOR_XFER_SHORT && cswlen == 0) {
		_VMKLNX_USB_STOR_MSG("Received 0-length CSW; retrying...\n", us->srb);
		US_DEBUGP("Received 0-length CSW; retrying...\n");
		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
				bcs, US_BULK_CS_WRAP_LEN, &cswlen);
	}

	/* did the attempt to read the CSW fail? */
	if (result == USB_STOR_XFER_STALLED) {

		/* get the status again */
		US_DEBUGP("Attempting to get CSW (2nd try)...\n");
		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
				bcs, US_BULK_CS_WRAP_LEN, NULL);
	}

	/* if we still have a failure at this point, we're in trouble */
#if defined(__VMKLNX__)
	if (result != USB_STOR_XFER_GOOD)
		_VMKLNX_USB_STOR_WARN("Bulk status result = %d\n", us->srb, result);
#endif
	US_DEBUGP("Bulk status result = %d\n", result);
	if (result != USB_STOR_XFER_GOOD)
		return USB_STOR_TRANSPORT_ERROR;

	/* check bulk status */
	residue = le32_to_cpu(bcs->Residue);
	US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
			le32_to_cpu(bcs->Signature), bcs->Tag, 
			residue, bcs->Status);
	if (!(bcs->Tag == us->tag || (us->flags & US_FL_BULK_IGNORE_TAG)) ||
		bcs->Status > US_BULK_STAT_PHASE) {
		_VMKLNX_USB_STOR_WARN("Bulk logical error\n", us->srb);
		US_DEBUGP("Bulk logical error\n");
		return USB_STOR_TRANSPORT_ERROR;
	}

	/* Some broken devices report odd signatures, so we do not check them
	 * for validity against the spec. We store the first one we see,
	 * and check subsequent transfers for validity against this signature.
	 */
	if (!us->bcs_signature) {
		us->bcs_signature = bcs->Signature;
		if (us->bcs_signature != cpu_to_le32(US_BULK_CS_SIGN))
#if defined(__VMKLNX__)
		{
			_VMKLNX_USB_STOR_WARN("Learnt BCS signature 0x%08X\n",
				us->srb, le32_to_cpu(us->bcs_signature));
#endif
			US_DEBUGP("Learnt BCS signature 0x%08X\n",
					le32_to_cpu(us->bcs_signature));
#if defined(__VMKLNX__)
		}
#endif
	} else if (bcs->Signature != us->bcs_signature) {
		_VMKLNX_USB_STOR_WARN("Signature mismatch: got %08X, expecting %08X\n",
			  us->srb,
			  le32_to_cpu(bcs->Signature),
			  le32_to_cpu(us->bcs_signature));
		US_DEBUGP("Signature mismatch: got %08X, expecting %08X\n",
			  le32_to_cpu(bcs->Signature),
			  le32_to_cpu(us->bcs_signature));
		return USB_STOR_TRANSPORT_ERROR;
	}

	/* try to compute the actual residue, based on how much data
	 * was really transferred and what the device tells us */
	if (residue) {
		if (!(us->flags & US_FL_IGNORE_RESIDUE)) {
			residue = min(residue, transfer_length);
			srb->resid = max(srb->resid, (int) residue);
		}
	}

	/* based on the status code, we report good or bad */
	switch (bcs->Status) {
		case US_BULK_STAT_OK:
			/* device babbled -- return fake sense data */
			if (fake_sense) {
				_VMKLNX_USB_STOR_MSG("Device tried to send back more data than requested, returning sense data as Illegal Request, Invalid Field.\n", us->srb);
				memcpy(srb->sense_buffer, 
				       usb_stor_sense_invalidCDB, 
				       sizeof(usb_stor_sense_invalidCDB));
				return USB_STOR_TRANSPORT_NO_SENSE;
			}

			/* command good -- note that data could be short */
			return USB_STOR_TRANSPORT_GOOD;

		case US_BULK_STAT_FAIL:
			/* command failed */
			return USB_STOR_TRANSPORT_FAILED;

		case US_BULK_STAT_PHASE:
			/* phase error -- note that a transport reset will be
			 * invoked by the invoke_transport() function
			 */
			return USB_STOR_TRANSPORT_ERROR;
	}

	/* we should never get here, but if we do, we're in trouble */
	_VMKLNX_USB_STOR_WARN("ERROR: fell thru switch in %s", us->srb, __FUNCTION__);
	return USB_STOR_TRANSPORT_ERROR;
}
Пример #6
0
/*
 * ENE_SendScsiCmd():
 */
int ENE_SendScsiCmd(struct us_data *us, BYTE fDir, void *buf, int use_sg)
{
	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
	struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;

	int result;
	unsigned int transfer_length = bcb->DataTransferLength,
		     cswlen = 0, partial = 0;
	unsigned int residue;

	/* printk(KERN_INFO "transport --- ENE_SendScsiCmd\n"); */
	/* send cmd to out endpoint */
	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
					    bcb, US_BULK_CB_WRAP_LEN, NULL);
	if (result != USB_STOR_XFER_GOOD) {
		printk(KERN_ERR "send cmd to out endpoint fail ---\n");
		return USB_STOR_TRANSPORT_ERROR;
	}

	if (buf) {
		unsigned int pipe = fDir;

		if (fDir == FDIR_READ)
			pipe = us->recv_bulk_pipe;
		else
			pipe = us->send_bulk_pipe;

		/* Bulk */
		if (use_sg)
			result = usb_stor_bulk_srb(us, pipe, us->srb);
		else
			result = usb_stor_bulk_transfer_sg(us, pipe, buf,
						transfer_length, 0, &partial);
		if (result != USB_STOR_XFER_GOOD) {
			printk(KERN_ERR "data transfer fail ---\n");
			return USB_STOR_TRANSPORT_ERROR;
		}
	}

	/* Get CSW for device status */
	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs,
						US_BULK_CS_WRAP_LEN, &cswlen);

	if (result == USB_STOR_XFER_SHORT && cswlen == 0) {
		printk(KERN_WARNING "Received 0-length CSW; retrying...\n");
		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
					bcs, US_BULK_CS_WRAP_LEN, &cswlen);
	}

	if (result == USB_STOR_XFER_STALLED) {
		/* get the status again */
		printk(KERN_WARNING "Attempting to get CSW (2nd try)...\n");
		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
						bcs, US_BULK_CS_WRAP_LEN, NULL);
	}

	if (result != USB_STOR_XFER_GOOD)
		return USB_STOR_TRANSPORT_ERROR;

	/* check bulk status */
	residue = le32_to_cpu(bcs->Residue);

	/*
	 * try to compute the actual residue, based on how much data
	 * was really transferred and what the device tells us
	 */
	if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) {
		residue = min(residue, transfer_length);
		if (us->srb)
			scsi_set_resid(us->srb, max(scsi_get_resid(us->srb),
					(int) residue));
	}

	if (bcs->Status != US_BULK_STAT_OK)
		return USB_STOR_TRANSPORT_ERROR;

	return USB_STOR_TRANSPORT_GOOD;
}
Пример #7
0
/**
* @fn		__sm331_internal_cmd
* @brief	transport SCSI Command from this driver.
* @param	srb	    : SCSI command structure
* @param	us_data	    : USB Storage device structure
* @param	cmnd	    : Command Description
* @param	cmnd_length : Length of Command Description
* @param	reply_buf   : Reply buffer
* @param	reply_len   : Length of reply buffer
* @param	direction   : DMA_BIDIRECTIONAL, DMA_TO_DEVICE, DMA_FROM_DEVICE, DMA_NONE
* @return	success : 0	failure : not zero
* @date		2008/07/10
*/
int __sm331_internal_cmd(
    struct scsi_cmnd *srb, void *us_data, __u8 *cmnd, __u8 cmnd_length,
    void *reply_buf, unsigned int reply_len, int direction)
{
    struct bulk_cb_wrap bcb;
    struct bulk_cs_wrap bcs;
    unsigned int transfer_length = reply_len;
    unsigned int residue;
    int resid;
    int result;
    int fake_sense = 0;
    unsigned int cswlen;
    unsigned int cbwlen = US_BULK_CB_WRAP_LEN;
    struct us_data *us = (struct us_data *)us_data;
#ifdef SDOP_DEBUG
    static int write_count = 0;
    static int read_count = 0;
#endif //SDOP_DUBUG

    /* set up the command wrapper */
    bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
    bcb.DataTransferLength = cpu_to_le32(transfer_length);
    bcb.Flags = direction == DMA_FROM_DEVICE ? 1 << 7 : 0;
    bcb.Tag = ++us->tag;
    bcb.Lun = srb->device->lun;
    if (us->fflags & US_FL_SCM_MULT_TARG)
        bcb.Lun |= srb->device->id << 4;
    bcb.Length = cmnd_length;

    /* copy the command payload */
    memset(bcb.CDB, 0, sizeof(bcb.CDB));
    memcpy(bcb.CDB, cmnd, cmnd_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(bcb.Signature), bcb.Tag,
              le32_to_cpu(bcb.DataTransferLength), bcb.Flags,
              (bcb.Lun >> 4), (bcb.Lun & 0x0F),
              bcb.Length);
    result = __usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
                                          &bcb, cbwlen, NULL, cmd_timeout * HZ);
    US_DEBUGP("Bulk command transfer result=%d\n", result);
    if (result == USB_STOR_XFER_TIMEOUT)
        return SM331_TRANS_TIMEOUT;
    else if (result != USB_STOR_XFER_GOOD)
        return USB_STOR_TRANSPORT_ERROR;
#ifdef SDOP_DEBUG
    if(cmnd[0] == WRITE_10 && write_timeout_num) {
        write_timeout_num--;
        wait_event_timeout(timeout_wq, 0, cmd_timeout*HZ);
        return SM331_TRANS_TIMEOUT;
    }
    else if(cmnd[0] == READ_10 && read_timeout_num) {
        read_timeout_num--;
        wait_event_timeout(timeout_wq, 0, cmd_timeout*HZ);
        return SM331_TRANS_TIMEOUT;
    }
    else if(cmnd[0] == WRITE_10 && write_timeout_interval) {
        write_count++;

        if(write_count >= write_timeout_interval) {
            printk("write : dummy timeout : %d sec\n", cmd_timeout);
            wait_event_timeout(timeout_wq, 0, cmd_timeout*HZ);
            write_count = 0;
            return SM331_TRANS_TIMEOUT;
        }
    }
    else if(cmnd[0] == READ_10 && read_timeout_interval) {
        read_count++;

        if(read_count >= read_timeout_interval) {
            printk("read : dummy timeout : %d sec\n", cmd_timeout);
            wait_event_timeout(timeout_wq, 0, cmd_timeout*HZ);
            read_count = 0;
            return SM331_TRANS_TIMEOUT;
        }
    }
#endif //SDOP_DEBUG

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

    /* Some USB-IDE converter chips need a 100us delay between the
     * command phase and the data phase.  Some devices need a little
     * more than that, probably because of clock rate inaccuracies. */
    if (unlikely(us->fflags & US_FL_GO_SLOW))
        udelay(125);

    if (transfer_length) {
        unsigned int pipe = direction == DMA_FROM_DEVICE ?
                            us->recv_bulk_pipe : us->send_bulk_pipe;

//		result = usb_stor_bulk_srb(us, pipe, srb);
        result = usb_stor_bulk_transfer_sg(us, pipe,
                                           reply_buf, transfer_length,
                                           0, &resid);
        US_DEBUGP("Bulk data transfer result 0x%x\n", result);
        if (result == USB_STOR_XFER_ERROR)
            return USB_STOR_TRANSPORT_ERROR;

        /* If the device tried to send back more data than the
         * amount requested, the spec requires us to transfer
         * the CSW anyway.  Since there's no point retrying the
         * the command, we'll return fake sense data indicating
         * Illegal Request, Invalid Field in CDB.
         */
        if (result == USB_STOR_XFER_LONG)
            fake_sense = 1;
    }

    /* See flow chart on pg 15 of the Bulk Only Transport spec for
     * an explanation of how this code works.
     */

    /* get CSW for device status */
    US_DEBUGP("Attempting to get CSW...\n");
    result = __usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
                                          &bcs, US_BULK_CS_WRAP_LEN, &cswlen, cmd_timeout * HZ);

    /* Some broken devices add unnecessary zero-length packets to the
     * end of their data transfers.  Such packets show up as 0-length
     * CSWs.  If we encounter such a thing, try to read the CSW again.
     */
    if (result == USB_STOR_XFER_SHORT && cswlen == 0) {
        US_DEBUGP("Received 0-length CSW; retrying...\n");
        result = __usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
                                              &bcs, US_BULK_CS_WRAP_LEN, &cswlen, cmd_timeout * HZ);
    }

    /* did the attempt to read the CSW fail? */
    if (result == USB_STOR_XFER_STALLED) {

        /* get the status again */
        US_DEBUGP("Attempting to get CSW (2nd try)...\n");
        result = __usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
                                              &bcs, US_BULK_CS_WRAP_LEN, NULL, cmd_timeout * HZ);
    }

    /* if we still have a failure at this point, we're in trouble */
    US_DEBUGP("Bulk status result = %d\n", result);
    if (result == USB_STOR_XFER_TIMEOUT)
        return SM331_TRANS_TIMEOUT;
    else if (result != USB_STOR_XFER_GOOD)
        return USB_STOR_TRANSPORT_ERROR;
#ifdef SDOP_DEBUG
    if(cmnd[0] == WRITE_10 && write_timeout_num) {
        write_timeout_num--;
        wait_event_timeout(timeout_wq, 0, cmd_timeout*HZ);
        return SM331_TRANS_TIMEOUT;
    }
    else if(cmnd[0] == READ_10 && read_timeout_num) {
        read_timeout_num--;
        wait_event_timeout(timeout_wq, 0, cmd_timeout*HZ);
        return SM331_TRANS_TIMEOUT;
    }
    else if(cmnd[0] == WRITE_10 && write_timeout_interval) {
        write_count++;

        if(write_count >= write_timeout_interval) {
            printk("write : dummy timeout : %d sec\n", cmd_timeout);
            wait_event_timeout(timeout_wq, 0, cmd_timeout*HZ);
            write_count = 0;
            return SM331_TRANS_TIMEOUT;
        }
    }
    else if(cmnd[0] == READ_10 && read_timeout_interval) {
        read_count++;

        if(read_count >= read_timeout_interval) {
            printk("read : dummy timeout : %d sec\n", cmd_timeout);
            wait_event_timeout(timeout_wq, 0, cmd_timeout*HZ);
            read_count = 0;
            return SM331_TRANS_TIMEOUT;
        }
    }
#endif //SDOP_DEBUG

    /* check bulk status */
    residue = le32_to_cpu(bcs.Residue);
    US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
              le32_to_cpu(bcs.Signature), bcs.Tag,
              residue, bcs.Status);
    if (!(bcs.Tag == us->tag || (us->fflags & US_FL_BULK_IGNORE_TAG)) ||
            bcs.Status > US_BULK_STAT_PHASE) {
        US_DEBUGP("Bulk logical error\n");
        return USB_STOR_TRANSPORT_ERROR;
    }

    /* Some broken devices report odd signatures, so we do not check them
     * for validity against the spec. We store the first one we see,
     * and check subsequent transfers for validity against this signature.
     */
    if (!us->bcs_signature) {
        us->bcs_signature = bcs.Signature;
        if (us->bcs_signature != cpu_to_le32(US_BULK_CS_SIGN))
            US_DEBUGP("Learnt BCS signature 0x%08X\n",
                      le32_to_cpu(us->bcs_signature));
    } else if (bcs.Signature != us->bcs_signature) {
        US_DEBUGP("Signature mismatch: got %08X, expecting %08X\n",
                  le32_to_cpu(bcs.Signature),
                  le32_to_cpu(us->bcs_signature));
        return USB_STOR_TRANSPORT_ERROR;
    }

    /* try to compute the actual residue, based on how much data
     * was really transferred and what the device tells us */
    if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) {

        /* Heuristically detect devices that generate bogus residues
         * by seeing what happens with INQUIRY and READ CAPACITY
         * commands.
         */
        if (bcs.Status == US_BULK_STAT_OK &&
                scsi_get_resid(srb) == 0 &&
                ((cmnd[0] == INQUIRY &&
                  transfer_length == 36) ||
                 (cmnd[0] == READ_CAPACITY &&
                  transfer_length == 8))) {
            us->fflags |= US_FL_IGNORE_RESIDUE;

        } else {
            residue = min(residue, transfer_length);
//			scsi_set_resid(srb, max(scsi_get_resid(srb),
//			                                       (int) residue));
        }
    }

    /* based on the status code, we report good or bad */
    switch (bcs.Status) {
    case US_BULK_STAT_OK:
        /* device babbled -- return fake sense data */
        if (fake_sense) {
            return USB_STOR_TRANSPORT_NO_SENSE;
        }

        /* command good -- note that data could be short */
        return USB_STOR_TRANSPORT_GOOD;

    case US_BULK_STAT_FAIL:
        /* command failed */
        return USB_STOR_TRANSPORT_FAILED;

    case US_BULK_STAT_PHASE:
        /* phase error -- note that a transport reset will be
         * invoked by the invoke_transport() function
         */
        return USB_STOR_TRANSPORT_ERROR;
    }

    /* we should never get here, but if we do, we're in trouble */
    return USB_STOR_TRANSPORT_ERROR;
}