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

📄 transport.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Driver for USB Mass Storage compliant devices * * $Id: transport.c,v 1.47 2002/04/22 03:39:43 mdharm Exp $ * * Current development and maintenance by: *   (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net) * * Developed with the assistance of: *   (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org) *   (c) 2000 Stephen J. Gowdy (SGowdy@lbl.gov) *   (c) 2002 Alan Stern <stern@rowland.org> * * Initial work by: *   (c) 1999 Michael Gee (michael@linuxspecific.com) * * This driver is based on the 'USB Mass Storage Class' document. This * describes in detail the protocol used to communicate with such * devices.  Clearly, the designers had SCSI and ATAPI commands in * mind when they created this document.  The commands are all very * similar to commands in the SCSI-II and ATAPI specifications. * * It is important to note that in a number of cases this class * exhibits class-specific exemptions from the USB specification. * Notably the usage of NAK, STALL and ACK differs from the norm, in * that they are used to communicate wait, failed and OK on commands. * * Also, for certain devices, the interrupt endpoint is used to convey * status of a command. * * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more * information about this driver. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */#include <linux/config.h>#include "transport.h"#include "protocol.h"#include "scsiglue.h"#include "usb.h"#include "debug.h"#include <linux/sched.h>#include <linux/errno.h>#include <linux/slab.h>/*********************************************************************** * Data transfer routines ***********************************************************************//* * This is subtle, so pay attention: * --------------------------------- * We're very concerned about races with a command abort.  Hanging this code * is a sure fire way to hang the kernel.  (Note that this discussion applies * only to transactions resulting from a scsi queued-command, since only * these transactions are subject to a scsi abort.  Other transactions, such * as those occurring during device-specific initialization, must be handled * by a separate code path.) * * The abort function (usb_storage_command_abort() in scsiglue.c) first * sets the machine state and the ABORTING bit in us->flags to prevent * new URBs from being submitted.  It then calls usb_stor_stop_transport() * below, which atomically tests-and-clears the URB_ACTIVE bit in us->flags * to see if the current_urb needs to be stopped.  Likewise, the SG_ACTIVE * bit is tested to see if the current_sg scatter-gather request needs to be * stopped.  The timeout callback routine does much the same thing. * * When a disconnect occurs, the DISCONNECTING bit in us->flags is set to * prevent new URBs from being submitted, and usb_stor_stop_transport() is * called to stop any ongoing requests. * * The submit function first verifies that the submitting is allowed * (neither ABORTING nor DISCONNECTING bits are set) and that the submit * completes without errors, and only then sets the URB_ACTIVE bit.  This * prevents the stop_transport() function from trying to cancel the URB * while the submit call is underway.  Next, the submit function must test * the flags to see if an abort or disconnect occurred during the submission * or before the URB_ACTIVE bit was set.  If so, it's essential to cancel * the URB if it hasn't been cancelled already (i.e., if the URB_ACTIVE bit * is still set).  Either way, the function must then wait for the URB to * finish.  Note that because the URB_ASYNC_UNLINK flag is set, the URB can * still be in progress even after a call to usb_unlink_urb() returns. * * The idea is that (1) once the ABORTING or DISCONNECTING bit is set, * either the stop_transport() function or the submitting function * is guaranteed to call usb_unlink_urb() for an active URB, * and (2) test_and_clear_bit() prevents usb_unlink_urb() from being * called more than once or from being called during usb_submit_urb(). *//* This is the completion handler which will wake us up when an URB * completes. */static void usb_stor_blocking_completion(struct urb *urb, struct pt_regs *regs){	struct completion *urb_done_ptr = (struct completion *)urb->context;	complete(urb_done_ptr);} /* This is the timeout handler which will cancel an URB when its timeout * expires. */static void timeout_handler(unsigned long us_){	struct us_data *us = (struct us_data *) us_;	if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) {		US_DEBUGP("Timeout -- cancelling URB\n");		usb_unlink_urb(us->current_urb);	}}/* This is the common part of the URB message submission code * * All URBs from the usb-storage driver involved in handling a queued scsi * command _must_ pass through this function (or something like it) for the * abort mechanisms to work properly. */static int usb_stor_msg_common(struct us_data *us, int timeout){	struct completion urb_done;	struct timer_list to_timer;	int status;	/* don't submit URBs during abort/disconnect processing */	if (us->flags & ABORTING_OR_DISCONNECTING)		return -EIO;	/* set up data structures for the wakeup system */	init_completion(&urb_done);	/* fill the common fields in the URB */	us->current_urb->context = &urb_done;	us->current_urb->actual_length = 0;	us->current_urb->error_count = 0;	us->current_urb->status = 0;	/* we assume that if transfer_buffer isn't us->iobuf then it	 * hasn't been mapped for DMA.  Yes, this is clunky, but it's	 * easier than always having the caller tell us whether the	 * transfer buffer has already been mapped. */	us->current_urb->transfer_flags =			URB_ASYNC_UNLINK | URB_NO_SETUP_DMA_MAP;	if (us->current_urb->transfer_buffer == us->iobuf)		us->current_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;	us->current_urb->transfer_dma = us->iobuf_dma;	us->current_urb->setup_dma = us->cr_dma;	/* submit the URB */	status = usb_submit_urb(us->current_urb, GFP_NOIO);	if (status) {		/* something went wrong */		return status;	}	/* since the URB has been submitted successfully, it's now okay	 * to cancel it */	set_bit(US_FLIDX_URB_ACTIVE, &us->flags);	/* did an abort/disconnect occur during the submission? */	if (us->flags & ABORTING_OR_DISCONNECTING) {		/* cancel the URB, if it hasn't been cancelled already */		if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) {			US_DEBUGP("-- cancelling URB\n");			usb_unlink_urb(us->current_urb);		}	} 	/* submit the timeout timer, if a timeout was requested */	if (timeout > 0) {		init_timer(&to_timer);		to_timer.expires = jiffies + timeout;		to_timer.function = timeout_handler;		to_timer.data = (unsigned long) us;		add_timer(&to_timer);	}	/* wait for the completion of the URB */	wait_for_completion(&urb_done);	clear_bit(US_FLIDX_URB_ACTIVE, &us->flags); 	/* clean up the timeout timer */	if (timeout > 0)		del_timer_sync(&to_timer);	/* return the URB status */	return us->current_urb->status;}/* * Transfer one control message, with timeouts, and allowing early * termination.  Return codes are usual -Exxx, *not* USB_STOR_XFER_xxx. */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;	US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",			__FUNCTION__, request, requesttype,			value, index, size);	/* 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);	/* fill and submit the URB */	usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe, 			 (unsigned char*) us->cr, data, size, 			 usb_stor_blocking_completion, NULL);	status = usb_stor_msg_common(us, timeout);	/* return the actual length of the data transferred if no error */	if (status == 0)		status = us->current_urb->actual_length;	return status;}/* This is a version of usb_clear_halt() that allows early termination and * doesn't read the status from the device -- this is because some devices * crash their internal firmware when the status is requested after a halt. * * A definitive list of these 'bad' devices is too difficult to maintain or * make complete enough to be useful.  This problem was first observed on the * Hagiwara FlashGate DUAL unit.  However, bus traces reveal that neither * MacOS nor Windows checks the status after clearing a halt. * * Since many vendors in this space limit their testing to interoperability * with these two OSes, specification violations like this one are common. */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 toggles and endpoint flags */	usb_endpoint_running(us->pusb_dev, usb_pipeendpoint(pipe),		usb_pipeout(pipe));	usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe),		usb_pipeout(pipe), 0);	US_DEBUGP("%s: result = %d\n", __FUNCTION__, result);	return result;}/* * Interpret the results of a URB transfer * * This function prints appropriate debugging messages, clears halts on * non-control endpoints, and translates the status to the corresponding * USB_STOR_XFER_xxx return code. */static int interpret_urb_result(struct us_data *us, unsigned int pipe,		unsigned int length, int result, unsigned int partial){	US_DEBUGP("Status code %d; transferred %u/%u\n",			result, partial, length);	switch (result) {	/* no error code; did we send all the data? */	case 0:		if (partial != length) {			US_DEBUGP("-- short transfer\n");			return USB_STOR_XFER_SHORT;		}		US_DEBUGP("-- transfer complete\n");		return USB_STOR_XFER_GOOD;	/* stalled */	case -EPIPE:		/* for control endpoints, (used by CB[I]) a stall indicates		 * a failed command */		if (usb_pipecontrol(pipe)) {			US_DEBUGP("-- stall on control pipe\n");			return USB_STOR_XFER_STALLED;		}		/* for other sorts of endpoint, clear the stall */		US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);		if (usb_stor_clear_halt(us, pipe) < 0)			return USB_STOR_XFER_ERROR;		return USB_STOR_XFER_STALLED;	/* timeout or excessively long NAK */	case -ETIMEDOUT:		US_DEBUGP("-- timeout or NAK\n");		return USB_STOR_XFER_ERROR;	/* babble - the device tried to send more than we wanted to read */	case -EOVERFLOW:		US_DEBUGP("-- babble\n");		return USB_STOR_XFER_LONG;	/* the transfer was cancelled by abort, disconnect, or timeout */	case -ECONNRESET:		US_DEBUGP("-- transfer cancelled\n");		return USB_STOR_XFER_ERROR;	/* short scatter-gather read transfer */	case -EREMOTEIO:		US_DEBUGP("-- short read transfer\n");		return USB_STOR_XFER_SHORT;	/* abort or disconnect in progress */	case -EIO:		US_DEBUGP("-- abort or disconnect in progress\n");		return USB_STOR_XFER_ERROR;	/* the catch-all error case */	default:		US_DEBUGP("-- unknown error\n");		return USB_STOR_XFER_ERROR;	}}/* * Transfer one control message, without timeouts, but allowing early * termination.  Return codes are USB_STOR_XFER_xxx. */int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,		u8 request, u8 requesttype, u16 value, u16 index,		void *data, u16 size){	int result;	US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",			__FUNCTION__, request, requesttype,			value, index, size);	/* 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);	/* fill and submit the URB */	usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe, 			 (unsigned char*) us->cr, data, size, 			 usb_stor_blocking_completion, NULL);	result = usb_stor_msg_common(us, 0);	return interpret_urb_result(us, pipe, size, result,			us->current_urb->actual_length);}/* * Receive one interrupt buffer, without timeouts, but allowing early * termination.  Return codes are USB_STOR_XFER_xxx. * * This routine always uses us->recv_intr_pipe as the pipe and * us->ep_bInterval as the interrupt interval. */int usb_stor_intr_transfer(struct us_data *us, void *buf, unsigned int length){	int result;	unsigned int pipe = us->recv_intr_pipe;	unsigned int maxp;	US_DEBUGP("%s: xfer %u bytes\n", __FUNCTION__, length);	/* calculate the max packet size */	maxp = usb_maxpacket(us->pusb_dev, pipe, usb_pipeout(pipe));	if (maxp > length)

⌨️ 快捷键说明

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