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

📄 csk_udisk_mgr.c

📁 linux 2.6.13 USB2.0开发补丁,lyj_uptech@126.com
💻 C
📖 第 1 页 / 共 4 页
字号:
		}		scsi_unlock(host);		/* reject the command if the direction indicator 		* is UNKNOWN		*/		if (us->srb->sc_data_direction == DMA_BIDIRECTIONAL) {			us->srb->result = DID_ERROR << 16;		}		/* reject if target != 0 or if LUN is higher than		* the maximum known LUN		*/		else if (us->srb->device->id && 			!(us->flags & US_FL_SCM_MULT_TARG)) {				us->srb->result = DID_BAD_TARGET << 16;		}		else if (us->srb->device->lun > us->max_lun) {			us->srb->result = DID_BAD_TARGET << 16;		}		/* Handle those devices which need us to fake 		* their inquiry data */		else  if ((us->srb->cmnd[0] == INQUIRY) &&			(us->flags & US_FL_FIX_INQUIRY)) {		}		/* we've got a command, let's do it! */		else {	/* Pad the ATAPI command with zeros 	*	* NOTE: This only works because a scsi_cmnd struct field contains	* a unsigned char cmnd[16], so we know we have storage available	*/	/* Pad the ATAPI command with zeros */			for (; us->srb->cmd_len<12; us->srb->cmd_len++)				us->srb->cmnd[us->srb->cmd_len] = 0;			/* set command length to 12 bytes */			us->srb->cmd_len = 12;			/* send the command to the transport layer */			usb_stor_invoke_transport(us->srb, us);		}		/* lock access to the state */		scsi_lock(host);		if (!us->srb)			;		/* nothing to do */		/* indicate that the command is done */		else if (us->srb->result != DID_ABORT << 16) {			us->srb->scsi_done(us->srb);		} else {		}SkipForAbort:		/* If an abort request was received we need to signal that		* the abort has finished.  The proper test for this is		* the TIMED_OUT flag, not srb->result == DID_ABORT, because		* the timeout might have occurred after the command had		* already completed with a different result code. */		if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {			complete(&(us->notify));			/* Allow USB transfers to resume */			clear_bit(US_FLIDX_ABORTING, &us->flags);			clear_bit(US_FLIDX_TIMED_OUT, &us->flags);		}		/* finished working on this command */		us->srb = NULL;		scsi_unlock(host);		/* unlock the device pointers */		mutex_unlock(&us->dev_mutex);	} /* for (;;) */	scsi_host_put(host);	/* notify the exit routine that we're actually exiting now 	*	* complete()/wait_for_completion() is similar to up()/down(),	* except that complete() is safe in the case where the structure	* is getting deleted in a parallel mode of execution (i.e. just	* after the down() -- that's necessary for the thread-shutdown	* case.	*	*(struct bulk_cs_wrap *)bcb complete_and_exit() goes even further than this -- it is safe in	* the case that the thread of the caller is going away (not just	* the structure) -- this is necessary for the module-remove case.	* This is important in preemption kernels, which transfer the flow	* of execution immediately upon a complete().	*/	//complete_and_exit(&threads_gone, 0);}	static int usb_stor_clear_halt(struct us_data *us, unsigned int pipe){	int result;	int endp = usb_pipeendpoint(pipe);	if (usb_pipein (pipe))		endp |= USB_DIR_IN;	result = usb_stor_control_msg(us, us->send_ctrl_pipe,		USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,		USB_ENDPOINT_HALT, endp,		NULL, 0, 3*HZ);	/* reset the endpoint toggle */	if (result >= 0)		usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe),		usb_pipeout(pipe), 0);	return result;}static 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;	/* 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 */		result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,				bcb, cbwlen, NULL);	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 (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);		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 */		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) {				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 */				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 (result != USB_STOR_XFER_GOOD)		return USB_STOR_TRANSPORT_ERROR;	/* check bulk status */	residue = le32_to_cpu(bcs->Residue);		if (bcs->Tag != us->tag || bcs->Status > US_BULK_STAT_PHASE) {				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;	} else if (bcs->Signature != 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) {				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 */	return USB_STOR_TRANSPORT_ERROR;}/* Issue a USB port reset to the device.  The caller must not hold * us->dev_mutex. */static int usb_stor_port_reset(struct us_data *us){	int result, rc_lock;	result = rc_lock =		usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);	if (result < 0)		{}	else {		/* Were we disconnected while waiting for the lock? */		if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {			result = -EIO;				} else {			result = usb_reset_composite_device(					us->pusb_dev, us->pusb_intf);					}		if (rc_lock)			usb_unlock_device(us->pusb_dev);	}	return result;}static void usb_stor_report_device_reset(struct us_data *us){	int i;	struct Scsi_Host *host = us_to_host(us);	scsi_report_device_reset(host, 0, 0);	if (us->flags & US_FL_SCM_MULT_TARG) {		for (i = 1; i < host->max_id; ++i)			scsi_report_device_reset(host, 0, i);	}}/* This issues a Bulk-only Reset to the device in question, including * clearing the subsequent endpoint halts that may occur. */static int usb_stor_Bulk_reset(struct us_data *us){		int result;	int result2;	if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {				return -EIO;	}	result = usb_stor_control_msg(us, us->send_ctrl_pipe,			US_BULK_RESET_REQUEST, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,  us->ifnum, 0, 0,			5*HZ);	if (result < 0) {				return result;	} 	/* Give the device some time to recover from the reset, 	 * but don't delay disconnect processing. */ 	wait_event_interruptible_timeout(us->delay_wait, 			test_bit(US_FLIDX_DISCONNECTING, &us->flags), 			HZ*6);	if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {				return -EIO;	}		result = usb_stor_clear_halt(us, us->recv_bulk_pipe);		result2 = usb_stor_clear_halt(us, us->send_bulk_pipe);	/* return a result code based on the result of the clear-halts */	if (result >= 0)		result = result2;		return result;}/* * 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. */static int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,	void *buf, unsigned int length, unsigned int *act_len){	int result;	/* 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 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. */static 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;}/* * Transfer one control message, with timeouts, and allowing early * termination.  Return codes are usual -Exxx, *not* USB_STOR_XFER_xxx. */static int usb_stor_control_msg(struct us_data *us, unsigned int pipe,		 u8 request, u8 requesttype, u16 value, u16 index, 		 void *data, u16 size, int timeout){	int status;	/* fill in the devrequest structure */	us->cr->bRequestType = requesttype;	us->cr->bRequest = request;	us->cr->wValue = cpu_to_le16(value);	us->cr->wIndex = cpu_to_le16(index);	us->cr->wLength = cpu_to_le16(size);

⌨️ 快捷键说明

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