⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transport.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		maxp = length;	/* fill and submit the URB */	usb_fill_int_urb(us->current_urb, us->pusb_dev, pipe, buf,			maxp, usb_stor_blocking_completion, NULL,			us->ep_bInterval);	result = usb_stor_msg_common(us, 0);	return interpret_urb_result(us, pipe, length, result,			us->current_urb->actual_length);}/* * Transfer one buffer via bulk pipe, without timeouts, but allowing early * termination.  Return codes are USB_STOR_XFER_xxx.  If the bulk pipe * stalls during the transfer, the halt is automatically cleared. */int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,	void *buf, unsigned int length, unsigned int *act_len){	int result;	US_DEBUGP("%s: xfer %u bytes\n", __FUNCTION__, length);	/* fill and submit the URB */	usb_fill_bulk_urb(us->current_urb, us->pusb_dev, pipe, buf, length,		      usb_stor_blocking_completion, NULL);	result = usb_stor_msg_common(us, 0);	/* store the actual length of the data transferred */	if (act_len)		*act_len = us->current_urb->actual_length;	return interpret_urb_result(us, pipe, length, result, 			us->current_urb->actual_length);}/* * Transfer a scatter-gather list via bulk transfer * * This function does basically the same thing as usb_stor_bulk_transfer_buf() * above, but it uses the usbcore scatter-gather library. */int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,		struct scatterlist *sg, int num_sg, unsigned int length,		unsigned int *act_len){	int result;	/* don't submit s-g requests during abort/disconnect processing */	if (us->flags & ABORTING_OR_DISCONNECTING)		return USB_STOR_XFER_ERROR;	/* initialize the scatter-gather request block */	US_DEBUGP("%s: xfer %u bytes, %d entries\n", __FUNCTION__,			length, num_sg);	result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0,			sg, num_sg, length, SLAB_NOIO);	if (result) {		US_DEBUGP("usb_sg_init returned %d\n", result);		return USB_STOR_XFER_ERROR;	}	/* since the block has been initialized successfully, it's now	 * okay to cancel it */	set_bit(US_FLIDX_SG_ACTIVE, &us->flags);	/* did an abort/disconnect occur during the submission? */	if (us->flags & ABORTING_OR_DISCONNECTING) {		/* cancel the request, if it hasn't been cancelled already */		if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->flags)) {			US_DEBUGP("-- cancelling sg request\n");			usb_sg_cancel(&us->current_sg);		}	}	/* wait for the completion of the transfer */	usb_sg_wait(&us->current_sg);	clear_bit(US_FLIDX_SG_ACTIVE, &us->flags);	result = us->current_sg.status;	if (act_len)		*act_len = us->current_sg.bytes;	return interpret_urb_result(us, pipe, length, result,			us->current_sg.bytes);}/* * Transfer an entire SCSI command's worth of data payload over the bulk * pipe. * * Note that this uses usb_stor_bulk_transfer_buf() and * usb_stor_bulk_transfer_sglist() to achieve its goals -- * this function simply determines whether we're going to use * scatter-gather or not, and acts appropriately. */int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe,		void *buf, unsigned int length_left, int use_sg, int *residual){	int result;	unsigned int partial;	/* are we scatter-gathering? */	if (use_sg) {		/* use the usb core scatter-gather primitives */		result = usb_stor_bulk_transfer_sglist(us, pipe,				(struct scatterlist *) buf, use_sg,				length_left, &partial);		length_left -= partial;	} else {		/* no scatter-gather, just make the request */		result = usb_stor_bulk_transfer_buf(us, pipe, buf, 				length_left, &partial);		length_left -= partial;	}	/* store the residual and return the error code */	if (residual)		*residual = length_left;	return result;}/*********************************************************************** * Transport routines ***********************************************************************//* Invoke the transport and basic error-handling/recovery methods * * This is used by the protocol layers to actually send the message to * the device and receive the response. */void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us){	int need_auto_sense;	int result;	/* send the command to the transport layer */	srb->resid = 0;	result = us->transport(srb, us);	/* if the command gets aborted by the higher layers, we need to	 * short-circuit all other processing	 */	if (us->sm_state == US_STATE_ABORTING) {		US_DEBUGP("-- command was aborted\n");		goto Handle_Abort;	}	/* if there is a transport error, reset and don't auto-sense */	if (result == USB_STOR_TRANSPORT_ERROR) {		US_DEBUGP("-- transport indicates error, resetting\n");		us->transport_reset(us);		srb->result = DID_ERROR << 16;		return;	}	/* if the transport provided its own sense data, don't auto-sense */	if (result == USB_STOR_TRANSPORT_NO_SENSE) {		srb->result = SAM_STAT_CHECK_CONDITION;		return;	}	srb->result = SAM_STAT_GOOD;	/* Determine if we need to auto-sense	 *	 * I normally don't use a flag like this, but it's almost impossible	 * to understand what's going on here if I don't.	 */	need_auto_sense = 0;	/*	 * If we're running the CB transport, which is incapable	 * of determining status on its own, we will auto-sense	 * unless the operation involved a data-in transfer.  Devices	 * can signal most data-in errors by stalling the bulk-in pipe.	 */	if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) &&			srb->sc_data_direction != SCSI_DATA_READ) {		US_DEBUGP("-- CB transport device requiring auto-sense\n");		need_auto_sense = 1;	}	/*	 * If we have a failure, we're going to do a REQUEST_SENSE 	 * automatically.  Note that we differentiate between a command	 * "failure" and an "error" in the transport mechanism.	 */	if (result == USB_STOR_TRANSPORT_FAILED) {		US_DEBUGP("-- transport indicates command failure\n");		need_auto_sense = 1;	}	/*	 * A short transfer on a command where we don't expect it	 * is unusual, but it doesn't mean we need to auto-sense.	 */	if ((srb->resid > 0) &&	    !((srb->cmnd[0] == REQUEST_SENSE) ||	      (srb->cmnd[0] == INQUIRY) ||	      (srb->cmnd[0] == MODE_SENSE) ||	      (srb->cmnd[0] == LOG_SENSE) ||	      (srb->cmnd[0] == MODE_SENSE_10))) {		US_DEBUGP("-- unexpectedly short transfer\n");	}	/* Now, if we need to do the auto-sense, let's do it */	if (need_auto_sense) {		int temp_result;		void* old_request_buffer;		unsigned short old_sg;		unsigned old_request_bufflen;		unsigned char old_sc_data_direction;		unsigned char old_cmd_len;		unsigned char old_cmnd[MAX_COMMAND_SIZE];		unsigned long old_serial_number;		int old_resid;		US_DEBUGP("Issuing auto-REQUEST_SENSE\n");		/* save the old command */		memcpy(old_cmnd, srb->cmnd, MAX_COMMAND_SIZE);		old_cmd_len = srb->cmd_len;		/* set the command and the LUN */		memset(srb->cmnd, 0, MAX_COMMAND_SIZE);		srb->cmnd[0] = REQUEST_SENSE;		srb->cmnd[1] = old_cmnd[1] & 0xE0;		srb->cmnd[4] = 18;		/* FIXME: we must do the protocol translation here */		if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI)			srb->cmd_len = 6;		else			srb->cmd_len = 12;		/* set the transfer direction */		old_sc_data_direction = srb->sc_data_direction;		srb->sc_data_direction = SCSI_DATA_READ;		/* use the new buffer we have */		old_request_buffer = srb->request_buffer;		srb->request_buffer = srb->sense_buffer;		/* set the buffer length for transfer */		old_request_bufflen = srb->request_bufflen;		srb->request_bufflen = 18;		/* set up for no scatter-gather use */		old_sg = srb->use_sg;		srb->use_sg = 0;		/* change the serial number -- toggle the high bit*/		old_serial_number = srb->serial_number;		srb->serial_number ^= 0x80000000;		/* issue the auto-sense command */		old_resid = srb->resid;		srb->resid = 0;		temp_result = us->transport(us->srb, us);		/* let's clean up right away */		srb->resid = old_resid;		srb->request_buffer = old_request_buffer;		srb->request_bufflen = old_request_bufflen;		srb->use_sg = old_sg;		srb->serial_number = old_serial_number;		srb->sc_data_direction = old_sc_data_direction;		srb->cmd_len = old_cmd_len;		memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE);		if (us->sm_state == US_STATE_ABORTING) {			US_DEBUGP("-- auto-sense aborted\n");			goto Handle_Abort;		}		if (temp_result != USB_STOR_TRANSPORT_GOOD) {			US_DEBUGP("-- auto-sense failure\n");			/* we skip the reset if this happens to be a			 * multi-target device, since failure of an			 * auto-sense is perfectly valid			 */			if (!(us->flags & US_FL_SCM_MULT_TARG))				us->transport_reset(us);			srb->result = DID_ERROR << 16;			return;		}		US_DEBUGP("-- Result from auto-sense is %d\n", temp_result);		US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n",			  srb->sense_buffer[0],			  srb->sense_buffer[2] & 0xf,			  srb->sense_buffer[12], 			  srb->sense_buffer[13]);#ifdef CONFIG_USB_STORAGE_DEBUG		usb_stor_show_sense(			  srb->sense_buffer[2] & 0xf,			  srb->sense_buffer[12], 			  srb->sense_buffer[13]);#endif		/* set the result so the higher layers expect this data */		srb->result = SAM_STAT_CHECK_CONDITION;		/* If things are really okay, then let's show that.  Zero		 * out the sense buffer so the higher layers won't realize		 * we did an unsolicited auto-sense. */		if (result == USB_STOR_TRANSPORT_GOOD &&			/* Filemark 0, ignore EOM, ILI 0, no sense */				(srb->sense_buffer[2] & 0xaf) == 0 &&			/* No ASC or ASCQ */				srb->sense_buffer[12] == 0 &&				srb->sense_buffer[13] == 0) {			srb->result = SAM_STAT_GOOD;			srb->sense_buffer[0] = 0x0;		}	}	/* Did we transfer less than the minimum amount required? */	if (srb->result == SAM_STAT_GOOD &&			srb->request_bufflen - srb->resid < srb->underflow)		srb->result = (DID_ERROR << 16) | (SUGGEST_RETRY << 24);	return;	/* abort processing: the bulk-only transport requires a reset	 * following an abort */  Handle_Abort:	srb->result = DID_ABORT << 16;	if (us->protocol == US_PR_BULK)		us->transport_reset(us);}/* Stop the current URB transfer */void usb_stor_stop_transport(struct us_data *us){	US_DEBUGP("%s called\n", __FUNCTION__);	/* If the state machine is blocked waiting for an URB,	 * let's wake it up.  The test_and_clear_bit() call	 * guarantees that if a URB has just been submitted,	 * it won't be cancelled more than once. */	if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) {		US_DEBUGP("-- cancelling URB\n");		usb_unlink_urb(us->current_urb);	}	/* If we are waiting for a scatter-gather operation, cancel it. */	if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->flags)) {		US_DEBUGP("-- cancelling sg request\n");		usb_sg_cancel(&us->current_sg);	}}/* * Control/Bulk/Interrupt transport */int usb_stor_CBI_transport(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 == SCSI_DATA_READ ? 				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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -