direct-io.hg

changeset 3570:9bef38a51377

bitkeeper revision 1.1159.212.47 (41f97f66xOoJsNNqdPQ2dvZmBkFoHw)

Import hcd.c from vanilla Linux. Required a couple of ifdefs to
make 2.4 xenU domains compile with USB support.

Signed-off-by: mark.williamson@cl.cam.ac.uk
author mwilli2@equilibrium.research
date Thu Jan 27 23:55:18 2005 +0000 (2005-01-27)
parents 30ee9c427a5b
children d9cdcc864e90
files .rootkeys linux-2.4.29-xen-sparse/drivers/usb/hcd.c
line diff
     1.1 --- a/.rootkeys	Thu Jan 27 20:45:16 2005 +0000
     1.2 +++ b/.rootkeys	Thu Jan 27 23:55:18 2005 +0000
     1.3 @@ -90,6 +90,7 @@ 40d70c24-Dy2HUMrwSZagfXvAPnI4w linux-2.4
     1.4  3f108aeaLcGDgQdFAANLTUEid0a05w linux-2.4.29-xen-sparse/drivers/char/mem.c
     1.5  3e5a4e66rw65CxyolW9PKz4GG42RcA linux-2.4.29-xen-sparse/drivers/char/tty_io.c
     1.6  40c9c0c1pPwYE3-4i-oI3ubUu7UgvQ linux-2.4.29-xen-sparse/drivers/scsi/aic7xxx/Makefile
     1.7 +41f97f64nW0wmgLxhwzPTzkF4E5ERA linux-2.4.29-xen-sparse/drivers/usb/hcd.c
     1.8  3e5a4e669uzIE54VwucPYtGwXLAbzA linux-2.4.29-xen-sparse/fs/exec.c
     1.9  3e5a4e66wbeCpsJgVf_U8Jde-CNcsA linux-2.4.29-xen-sparse/include/asm-xen/bugs.h
    1.10  3e5a4e66HdSkvIV6SJ1evG_xmTmXHA linux-2.4.29-xen-sparse/include/asm-xen/desc.h
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/linux-2.4.29-xen-sparse/drivers/usb/hcd.c	Thu Jan 27 23:55:18 2005 +0000
     2.3 @@ -0,0 +1,1511 @@
     2.4 +/*
     2.5 + * Copyright (c) 2001-2002 by David Brownell
     2.6 + * 
     2.7 + * This program is free software; you can redistribute it and/or modify it
     2.8 + * under the terms of the GNU General Public License as published by the
     2.9 + * Free Software Foundation; either version 2 of the License, or (at your
    2.10 + * option) any later version.
    2.11 + *
    2.12 + * This program is distributed in the hope that it will be useful, but
    2.13 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    2.14 + * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    2.15 + * for more details.
    2.16 + *
    2.17 + * You should have received a copy of the GNU General Public License
    2.18 + * along with this program; if not, write to the Free Software Foundation,
    2.19 + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    2.20 + */
    2.21 +
    2.22 +#include <linux/config.h>
    2.23 +#include <linux/module.h>
    2.24 +#include <linux/pci.h>
    2.25 +#include <linux/kernel.h>
    2.26 +#include <linux/delay.h>
    2.27 +#include <linux/ioport.h>
    2.28 +#include <linux/sched.h>
    2.29 +#include <linux/slab.h>
    2.30 +#include <linux/smp_lock.h>
    2.31 +#include <linux/errno.h>
    2.32 +#include <linux/kmod.h>
    2.33 +#include <linux/init.h>
    2.34 +#include <linux/timer.h>
    2.35 +#include <linux/list.h>
    2.36 +#include <linux/interrupt.h>
    2.37 +#include <linux/completion.h>
    2.38 +#include <linux/uts.h>			/* for UTS_SYSNAME */
    2.39 +
    2.40 +
    2.41 +#ifdef CONFIG_USB_DEBUG
    2.42 +	#define DEBUG
    2.43 +#else
    2.44 +	#undef DEBUG
    2.45 +#endif
    2.46 +
    2.47 +#include <linux/usb.h>
    2.48 +#include "hcd.h"
    2.49 +
    2.50 +#include <asm/io.h>
    2.51 +#include <asm/irq.h>
    2.52 +#include <asm/system.h>
    2.53 +#include <asm/unaligned.h>
    2.54 +
    2.55 +
    2.56 +/*-------------------------------------------------------------------------*/
    2.57 +
    2.58 +/*
    2.59 + * USB Host Controller Driver framework
    2.60 + *
    2.61 + * Plugs into usbcore (usb_bus) and lets HCDs share code, minimizing
    2.62 + * HCD-specific behaviors/bugs.  Think of it as the "upper level" of
    2.63 + * some drivers, where the "lower level" is hardware-specific.
    2.64 + *
    2.65 + * This does error checks, tracks devices and urbs, and delegates to a
    2.66 + * "hc_driver" only for code (and data) that really needs to know about
    2.67 + * hardware differences.  That includes root hub registers, i/o queues,
    2.68 + * and so on ... but as little else as possible.
    2.69 + *
    2.70 + * Shared code includes most of the "root hub" code (these are emulated,
    2.71 + * though each HC's hardware works differently) and PCI glue, plus request
    2.72 + * tracking overhead.  The HCD code should only block on spinlocks or on
    2.73 + * hardware handshaking; blocking on software events (such as other kernel
    2.74 + * threads releasing resources, or completing actions) is all generic.
    2.75 + *
    2.76 + * Happens the USB 2.0 spec says this would be invisible inside the "USBD",
    2.77 + * and includes mostly a "HCDI" (HCD Interface) along with some APIs used
    2.78 + * only by the hub driver ... and that neither should be seen or used by
    2.79 + * usb client device drivers.
    2.80 + *
    2.81 + * Contributors of ideas or unattributed patches include: David Brownell,
    2.82 + * Roman Weissgaerber, Rory Bolt, ...
    2.83 + *
    2.84 + * HISTORY:
    2.85 + * 2002-sept	Merge some 2.5 updates so we can share hardware level HCD
    2.86 + * 	code between the 2.4.20+ and 2.5 trees.
    2.87 + * 2002-feb	merge to 2.4.19
    2.88 + * 2001-12-12	Initial patch version for Linux 2.5.1 kernel.
    2.89 + */
    2.90 +
    2.91 +/*-------------------------------------------------------------------------*/
    2.92 +
    2.93 +/* host controllers we manage */
    2.94 +static LIST_HEAD (hcd_list);
    2.95 +
    2.96 +/* used when updating list of hcds */
    2.97 +static DECLARE_MUTEX (hcd_list_lock);
    2.98 +
    2.99 +/* used when updating hcd data */
   2.100 +static spinlock_t hcd_data_lock = SPIN_LOCK_UNLOCKED;
   2.101 +
   2.102 +static struct usb_operations hcd_operations;
   2.103 +
   2.104 +/*-------------------------------------------------------------------------*/
   2.105 +
   2.106 +/*
   2.107 + * Sharable chunks of root hub code.
   2.108 + */
   2.109 +
   2.110 +/*-------------------------------------------------------------------------*/
   2.111 +
   2.112 +#define KERNEL_REL	((LINUX_VERSION_CODE >> 16) & 0x0ff)
   2.113 +#define KERNEL_VER	((LINUX_VERSION_CODE >> 8) & 0x0ff)
   2.114 +
   2.115 +/* usb 2.0 root hub device descriptor */
   2.116 +static const u8 usb2_rh_dev_descriptor [18] = {
   2.117 +	0x12,       /*  __u8  bLength; */
   2.118 +	0x01,       /*  __u8  bDescriptorType; Device */
   2.119 +	0x00, 0x02, /*  __u16 bcdUSB; v2.0 */
   2.120 +
   2.121 +	0x09,	    /*  __u8  bDeviceClass; HUB_CLASSCODE */
   2.122 +	0x00,	    /*  __u8  bDeviceSubClass; */
   2.123 +	0x01,       /*  __u8  bDeviceProtocol; [ usb 2.0 single TT ]*/
   2.124 +	0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
   2.125 +
   2.126 +	0x00, 0x00, /*  __u16 idVendor; */
   2.127 + 	0x00, 0x00, /*  __u16 idProduct; */
   2.128 +	KERNEL_VER, KERNEL_REL, /*  __u16 bcdDevice */
   2.129 +
   2.130 +	0x03,       /*  __u8  iManufacturer; */
   2.131 +	0x02,       /*  __u8  iProduct; */
   2.132 +	0x01,       /*  __u8  iSerialNumber; */
   2.133 +	0x01        /*  __u8  bNumConfigurations; */
   2.134 +};
   2.135 +
   2.136 +/* no usb 2.0 root hub "device qualifier" descriptor: one speed only */
   2.137 +
   2.138 +/* usb 1.1 root hub device descriptor */
   2.139 +static const u8 usb11_rh_dev_descriptor [18] = {
   2.140 +	0x12,       /*  __u8  bLength; */
   2.141 +	0x01,       /*  __u8  bDescriptorType; Device */
   2.142 +	0x10, 0x01, /*  __u16 bcdUSB; v1.1 */
   2.143 +
   2.144 +	0x09,	    /*  __u8  bDeviceClass; HUB_CLASSCODE */
   2.145 +	0x00,	    /*  __u8  bDeviceSubClass; */
   2.146 +	0x00,       /*  __u8  bDeviceProtocol; [ low/full speeds only ] */
   2.147 +	0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
   2.148 +
   2.149 +	0x00, 0x00, /*  __u16 idVendor; */
   2.150 + 	0x00, 0x00, /*  __u16 idProduct; */
   2.151 +	KERNEL_VER, KERNEL_REL, /*  __u16 bcdDevice */
   2.152 +
   2.153 +	0x03,       /*  __u8  iManufacturer; */
   2.154 +	0x02,       /*  __u8  iProduct; */
   2.155 +	0x01,       /*  __u8  iSerialNumber; */
   2.156 +	0x01        /*  __u8  bNumConfigurations; */
   2.157 +};
   2.158 +
   2.159 +
   2.160 +/*-------------------------------------------------------------------------*/
   2.161 +
   2.162 +/* Configuration descriptors for our root hubs */
   2.163 +
   2.164 +static const u8 fs_rh_config_descriptor [] = {
   2.165 +
   2.166 +	/* one configuration */
   2.167 +	0x09,       /*  __u8  bLength; */
   2.168 +	0x02,       /*  __u8  bDescriptorType; Configuration */
   2.169 +	0x19, 0x00, /*  __u16 wTotalLength; */
   2.170 +	0x01,       /*  __u8  bNumInterfaces; (1) */
   2.171 +	0x01,       /*  __u8  bConfigurationValue; */
   2.172 +	0x00,       /*  __u8  iConfiguration; */
   2.173 +	0x40,       /*  __u8  bmAttributes; 
   2.174 +				 Bit 7: Bus-powered,
   2.175 +				     6: Self-powered,
   2.176 +				     5 Remote-wakwup,
   2.177 +				     4..0: resvd */
   2.178 +	0x00,       /*  __u8  MaxPower; */
   2.179 +      
   2.180 +	/* USB 1.1:
   2.181 +	 * USB 2.0, single TT organization (mandatory):
   2.182 +	 *	one interface, protocol 0
   2.183 +	 *
   2.184 +	 * USB 2.0, multiple TT organization (optional):
   2.185 +	 *	two interfaces, protocols 1 (like single TT)
   2.186 +	 *	and 2 (multiple TT mode) ... config is
   2.187 +	 *	sometimes settable
   2.188 +	 *	NOT IMPLEMENTED
   2.189 +	 */
   2.190 +
   2.191 +	/* one interface */
   2.192 +	0x09,       /*  __u8  if_bLength; */
   2.193 +	0x04,       /*  __u8  if_bDescriptorType; Interface */
   2.194 +	0x00,       /*  __u8  if_bInterfaceNumber; */
   2.195 +	0x00,       /*  __u8  if_bAlternateSetting; */
   2.196 +	0x01,       /*  __u8  if_bNumEndpoints; */
   2.197 +	0x09,       /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
   2.198 +	0x00,       /*  __u8  if_bInterfaceSubClass; */
   2.199 +	0x00,       /*  __u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
   2.200 +	0x00,       /*  __u8  if_iInterface; */
   2.201 +     
   2.202 +	/* one endpoint (status change endpoint) */
   2.203 +	0x07,       /*  __u8  ep_bLength; */
   2.204 +	0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
   2.205 +	0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
   2.206 + 	0x03,       /*  __u8  ep_bmAttributes; Interrupt */
   2.207 + 	0x02, 0x00, /*  __u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
   2.208 +	0xff        /*  __u8  ep_bInterval; (255ms -- usb 2.0 spec) */
   2.209 +};
   2.210 +
   2.211 +static const u8 hs_rh_config_descriptor [] = {
   2.212 +
   2.213 +	/* one configuration */
   2.214 +	0x09,       /*  __u8  bLength; */
   2.215 +	0x02,       /*  __u8  bDescriptorType; Configuration */
   2.216 +	0x19, 0x00, /*  __u16 wTotalLength; */
   2.217 +	0x01,       /*  __u8  bNumInterfaces; (1) */
   2.218 +	0x01,       /*  __u8  bConfigurationValue; */
   2.219 +	0x00,       /*  __u8  iConfiguration; */
   2.220 +	0x40,       /*  __u8  bmAttributes; 
   2.221 +				 Bit 7: Bus-powered,
   2.222 +				     6: Self-powered,
   2.223 +				     5 Remote-wakwup,
   2.224 +				     4..0: resvd */
   2.225 +	0x00,       /*  __u8  MaxPower; */
   2.226 +      
   2.227 +	/* USB 1.1:
   2.228 +	 * USB 2.0, single TT organization (mandatory):
   2.229 +	 *	one interface, protocol 0
   2.230 +	 *
   2.231 +	 * USB 2.0, multiple TT organization (optional):
   2.232 +	 *	two interfaces, protocols 1 (like single TT)
   2.233 +	 *	and 2 (multiple TT mode) ... config is
   2.234 +	 *	sometimes settable
   2.235 +	 *	NOT IMPLEMENTED
   2.236 +	 */
   2.237 +
   2.238 +	/* one interface */
   2.239 +	0x09,       /*  __u8  if_bLength; */
   2.240 +	0x04,       /*  __u8  if_bDescriptorType; Interface */
   2.241 +	0x00,       /*  __u8  if_bInterfaceNumber; */
   2.242 +	0x00,       /*  __u8  if_bAlternateSetting; */
   2.243 +	0x01,       /*  __u8  if_bNumEndpoints; */
   2.244 +	0x09,       /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
   2.245 +	0x00,       /*  __u8  if_bInterfaceSubClass; */
   2.246 +	0x00,       /*  __u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
   2.247 +	0x00,       /*  __u8  if_iInterface; */
   2.248 +     
   2.249 +	/* one endpoint (status change endpoint) */
   2.250 +	0x07,       /*  __u8  ep_bLength; */
   2.251 +	0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
   2.252 +	0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
   2.253 + 	0x03,       /*  __u8  ep_bmAttributes; Interrupt */
   2.254 + 	0x02, 0x00, /*  __u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
   2.255 +	0x0c        /*  __u8  ep_bInterval; (256ms -- usb 2.0 spec) */
   2.256 +};
   2.257 +
   2.258 +/*-------------------------------------------------------------------------*/
   2.259 +
   2.260 +/*
   2.261 + * helper routine for returning string descriptors in UTF-16LE
   2.262 + * input can actually be ISO-8859-1; ASCII is its 7-bit subset
   2.263 + */
   2.264 +static int ascii2utf (char *s, u8 *utf, int utfmax)
   2.265 +{
   2.266 +	int retval;
   2.267 +
   2.268 +	for (retval = 0; *s && utfmax > 1; utfmax -= 2, retval += 2) {
   2.269 +		*utf++ = *s++;
   2.270 +		*utf++ = 0;
   2.271 +	}
   2.272 +	return retval;
   2.273 +}
   2.274 +
   2.275 +/*
   2.276 + * rh_string - provides manufacturer, product and serial strings for root hub
   2.277 + * @id: the string ID number (1: serial number, 2: product, 3: vendor)
   2.278 + * @pci_desc: PCI device descriptor for the relevant HC
   2.279 + * @type: string describing our driver 
   2.280 + * @data: return packet in UTF-16 LE
   2.281 + * @len: length of the return packet
   2.282 + *
   2.283 + * Produces either a manufacturer, product or serial number string for the
   2.284 + * virtual root hub device.
   2.285 + */
   2.286 +static int rh_string (
   2.287 +	int		id,
   2.288 +	struct usb_hcd	*hcd,
   2.289 +	u8		*data,
   2.290 +	int		len
   2.291 +) {
   2.292 +	char buf [100];
   2.293 +
   2.294 +	// language ids
   2.295 +	if (id == 0) {
   2.296 +		*data++ = 4; *data++ = 3;	/* 4 bytes string data */
   2.297 +		*data++ = 0; *data++ = 0;	/* some language id */
   2.298 +		return 4;
   2.299 +
   2.300 +	// serial number
   2.301 +	} else if (id == 1) {
   2.302 +		strcpy (buf, hcd->bus->bus_name);
   2.303 +
   2.304 +	// product description
   2.305 +	} else if (id == 2) {
   2.306 +                strcpy (buf, hcd->product_desc);
   2.307 +
   2.308 + 	// id 3 == vendor description
   2.309 +	} else if (id == 3) {
   2.310 +                sprintf (buf, "%s %s %s", UTS_SYSNAME, UTS_RELEASE,
   2.311 +			hcd->description);
   2.312 +
   2.313 +	// unsupported IDs --> "protocol stall"
   2.314 +	} else
   2.315 +	    return 0;
   2.316 +
   2.317 +	data [0] = 2 * (strlen (buf) + 1);
   2.318 +	data [1] = 3;	/* type == string */
   2.319 +	return 2 + ascii2utf (buf, data + 2, len - 2);
   2.320 +}
   2.321 +
   2.322 +
   2.323 +/* Root hub control transfers execute synchronously */
   2.324 +static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
   2.325 +{
   2.326 +	struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) urb->setup_packet;
   2.327 + 	u16		typeReq, wValue, wIndex, wLength;
   2.328 +	const u8	*bufp = 0;
   2.329 +	u8		*ubuf = urb->transfer_buffer;
   2.330 +	int		len = 0;
   2.331 +
   2.332 +	typeReq  = (cmd->bRequestType << 8) | cmd->bRequest;
   2.333 +	wValue   = le16_to_cpu (cmd->wValue);
   2.334 +	wIndex   = le16_to_cpu (cmd->wIndex);
   2.335 +	wLength  = le16_to_cpu (cmd->wLength);
   2.336 +
   2.337 +	if (wLength > urb->transfer_buffer_length)
   2.338 +		goto error;
   2.339 +
   2.340 +	/* set up for success */
   2.341 +	urb->status = 0;
   2.342 +	urb->actual_length = wLength;
   2.343 +	switch (typeReq) {
   2.344 +
   2.345 +	/* DEVICE REQUESTS */
   2.346 +
   2.347 +	case DeviceRequest | USB_REQ_GET_STATUS:
   2.348 +		// DEVICE_REMOTE_WAKEUP
   2.349 +		ubuf [0] = 1; // selfpowered
   2.350 +		ubuf [1] = 0;
   2.351 +			/* FALLTHROUGH */
   2.352 +	case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
   2.353 +	case DeviceOutRequest | USB_REQ_SET_FEATURE:
   2.354 +		dbg ("no device features yet yet");
   2.355 +		break;
   2.356 +	case DeviceRequest | USB_REQ_GET_CONFIGURATION:
   2.357 +		ubuf [0] = 1;
   2.358 +			/* FALLTHROUGH */
   2.359 +	case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
   2.360 +		break;
   2.361 +	case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
   2.362 +		switch (wValue & 0xff00) {
   2.363 +		case USB_DT_DEVICE << 8:
   2.364 +			if (hcd->driver->flags & HCD_USB2)
   2.365 +				bufp = usb2_rh_dev_descriptor;
   2.366 +			else if (hcd->driver->flags & HCD_USB11)
   2.367 +				bufp = usb11_rh_dev_descriptor;
   2.368 +			else
   2.369 +				goto error;
   2.370 +			len = 18;
   2.371 +			break;
   2.372 +		case USB_DT_CONFIG << 8:
   2.373 +			if (hcd->driver->flags & HCD_USB2) {
   2.374 +				bufp = hs_rh_config_descriptor;
   2.375 +				len = sizeof hs_rh_config_descriptor;
   2.376 +			} else {
   2.377 +				bufp = fs_rh_config_descriptor;
   2.378 +				len = sizeof fs_rh_config_descriptor;
   2.379 +			}
   2.380 +			break;
   2.381 +		case USB_DT_STRING << 8:
   2.382 +			urb->actual_length = rh_string (
   2.383 +				wValue & 0xff, hcd,
   2.384 +				ubuf, wLength);
   2.385 +			break;
   2.386 +		default:
   2.387 +			goto error;
   2.388 +		}
   2.389 +		break;
   2.390 +	case DeviceRequest | USB_REQ_GET_INTERFACE:
   2.391 +		ubuf [0] = 0;
   2.392 +			/* FALLTHROUGH */
   2.393 +	case DeviceOutRequest | USB_REQ_SET_INTERFACE:
   2.394 +		break;
   2.395 +	case DeviceOutRequest | USB_REQ_SET_ADDRESS:
   2.396 +		// wValue == urb->dev->devaddr
   2.397 +		dbg ("%s root hub device address %d",
   2.398 +			hcd->bus->bus_name, wValue);
   2.399 +		break;
   2.400 +
   2.401 +	/* INTERFACE REQUESTS (no defined feature/status flags) */
   2.402 +
   2.403 +	/* ENDPOINT REQUESTS */
   2.404 +
   2.405 +	case EndpointRequest | USB_REQ_GET_STATUS:
   2.406 +		// ENDPOINT_HALT flag
   2.407 +		ubuf [0] = 0;
   2.408 +		ubuf [1] = 0;
   2.409 +			/* FALLTHROUGH */
   2.410 +	case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
   2.411 +	case EndpointOutRequest | USB_REQ_SET_FEATURE:
   2.412 +		dbg ("no endpoint features yet");
   2.413 +		break;
   2.414 +
   2.415 +	/* CLASS REQUESTS (and errors) */
   2.416 +
   2.417 +	default:
   2.418 +		/* non-generic request */
   2.419 +		urb->status = hcd->driver->hub_control (hcd,
   2.420 +			typeReq, wValue, wIndex,
   2.421 +			ubuf, wLength);
   2.422 +		break;
   2.423 +error:
   2.424 +		/* "protocol stall" on error */
   2.425 +		urb->status = -EPIPE;
   2.426 +		dbg ("unsupported hub control message (maxchild %d)",
   2.427 +				urb->dev->maxchild);
   2.428 +	}
   2.429 +	if (urb->status) {
   2.430 +		urb->actual_length = 0;
   2.431 +		dbg ("CTRL: TypeReq=0x%x val=0x%x idx=0x%x len=%d ==> %d",
   2.432 +			typeReq, wValue, wIndex, wLength, urb->status);
   2.433 +	}
   2.434 +	if (bufp) {
   2.435 +		if (urb->transfer_buffer_length < len)
   2.436 +			len = urb->transfer_buffer_length;
   2.437 +		urb->actual_length = len;
   2.438 +		// always USB_DIR_IN, toward host
   2.439 +		memcpy (ubuf, bufp, len);
   2.440 +	}
   2.441 +
   2.442 +	/* any errors get returned through the urb completion */
   2.443 +	usb_hcd_giveback_urb (hcd, urb, 0);
   2.444 +	return 0;
   2.445 +}
   2.446 +
   2.447 +/*-------------------------------------------------------------------------*/
   2.448 +
   2.449 +/*
   2.450 + * Root Hub interrupt transfers are synthesized with a timer.
   2.451 + * Completions are called in_interrupt() but not in_irq().
   2.452 + */
   2.453 +
   2.454 +static void rh_report_status (unsigned long ptr);
   2.455 +
   2.456 +static int rh_status_urb (struct usb_hcd *hcd, struct urb *urb) 
   2.457 +{
   2.458 +	int	len = 1 + (urb->dev->maxchild / 8);
   2.459 +
   2.460 +	/* rh_timer protected by hcd_data_lock */
   2.461 +	if (timer_pending (&hcd->rh_timer)
   2.462 +			|| urb->status != -EINPROGRESS
   2.463 +			|| !HCD_IS_RUNNING (hcd->state)
   2.464 +			|| urb->transfer_buffer_length < len) {
   2.465 +		dbg ("not queuing status urb, stat %d", urb->status);
   2.466 +		return -EINVAL;
   2.467 +	}
   2.468 +
   2.469 +	urb->hcpriv = hcd;	/* nonzero to indicate it's queued */
   2.470 +	init_timer (&hcd->rh_timer);
   2.471 +	hcd->rh_timer.function = rh_report_status;
   2.472 +	hcd->rh_timer.data = (unsigned long) urb;
   2.473 +	/* USB 2.0 spec says 256msec; this is close enough */
   2.474 +	hcd->rh_timer.expires = jiffies + HZ/4;
   2.475 +	add_timer (&hcd->rh_timer);
   2.476 +	return 0;
   2.477 +}
   2.478 +
   2.479 +/* timer callback */
   2.480 +
   2.481 +static void rh_report_status (unsigned long ptr)
   2.482 +{
   2.483 +	struct urb	*urb;
   2.484 +	struct usb_hcd	*hcd;
   2.485 +	int		length;
   2.486 +	unsigned long	flags;
   2.487 +
   2.488 +	urb = (struct urb *) ptr;
   2.489 +	spin_lock_irqsave (&urb->lock, flags);
   2.490 +	if (!urb->dev) {
   2.491 +		spin_unlock_irqrestore (&urb->lock, flags);
   2.492 +		return;
   2.493 +	}
   2.494 +
   2.495 +	hcd = urb->dev->bus->hcpriv;
   2.496 +	if (urb->status == -EINPROGRESS) {
   2.497 +		if (HCD_IS_RUNNING (hcd->state)) {
   2.498 +			length = hcd->driver->hub_status_data (hcd,
   2.499 +					urb->transfer_buffer);
   2.500 +			spin_unlock_irqrestore (&urb->lock, flags);
   2.501 +			if (length > 0) {
   2.502 +				urb->actual_length = length;
   2.503 +				urb->status = 0;
   2.504 +				urb->complete (urb);
   2.505 +			}
   2.506 +			spin_lock_irqsave (&hcd_data_lock, flags);
   2.507 +			urb->status = -EINPROGRESS;
   2.508 +			if (HCD_IS_RUNNING (hcd->state)
   2.509 +					&& rh_status_urb (hcd, urb) != 0) {
   2.510 +				/* another driver snuck in? */
   2.511 +				dbg ("%s, can't resubmit roothub status urb?",
   2.512 +					hcd->bus->bus_name);
   2.513 +				spin_unlock_irqrestore (&hcd_data_lock, flags);
   2.514 +				BUG ();
   2.515 +			}
   2.516 +			spin_unlock_irqrestore (&hcd_data_lock, flags);
   2.517 +		} else
   2.518 +			spin_unlock_irqrestore (&urb->lock, flags);
   2.519 +	} else {
   2.520 +		/* this urb's been unlinked */
   2.521 +		urb->hcpriv = 0;
   2.522 +		spin_unlock_irqrestore (&urb->lock, flags);
   2.523 +
   2.524 +		usb_hcd_giveback_urb (hcd, urb, 0);
   2.525 +	}
   2.526 +}
   2.527 +
   2.528 +/*-------------------------------------------------------------------------*/
   2.529 +
   2.530 +static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb)
   2.531 +{
   2.532 +	if (usb_pipeint (urb->pipe)) {
   2.533 +		int		retval;
   2.534 +		unsigned long	flags;
   2.535 +
   2.536 +		spin_lock_irqsave (&hcd_data_lock, flags);
   2.537 +		retval = rh_status_urb (hcd, urb);
   2.538 +		spin_unlock_irqrestore (&hcd_data_lock, flags);
   2.539 +		return retval;
   2.540 +	}
   2.541 +	if (usb_pipecontrol (urb->pipe))
   2.542 +		return rh_call_control (hcd, urb);
   2.543 +	else
   2.544 +		return -EINVAL;
   2.545 +}
   2.546 +
   2.547 +/*-------------------------------------------------------------------------*/
   2.548 +
   2.549 +static void rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb)
   2.550 +{
   2.551 +	unsigned long	flags;
   2.552 +
   2.553 +	spin_lock_irqsave (&hcd_data_lock, flags);
   2.554 +	del_timer_sync (&hcd->rh_timer);
   2.555 +	hcd->rh_timer.data = 0;
   2.556 +	spin_unlock_irqrestore (&hcd_data_lock, flags);
   2.557 +
   2.558 +	/* we rely on RH callback code not unlinking its URB! */
   2.559 +	usb_hcd_giveback_urb (hcd, urb, 0);
   2.560 +}
   2.561 +
   2.562 +/*-------------------------------------------------------------------------*/
   2.563 +
   2.564 +#ifdef CONFIG_PCI
   2.565 +
   2.566 +/* PCI-based HCs are normal, but custom bus glue should be ok */
   2.567 +
   2.568 +static void hcd_irq (int irq, void *__hcd, struct pt_regs *r);
   2.569 +static void hc_died (struct usb_hcd *hcd);
   2.570 +
   2.571 +/*-------------------------------------------------------------------------*/
   2.572 +
   2.573 +/* configure so an HC device and id are always provided */
   2.574 +/* always called with process context; sleeping is OK */
   2.575 +
   2.576 +/**
   2.577 + * usb_hcd_pci_probe - initialize PCI-based HCDs
   2.578 + * @dev: USB Host Controller being probed
   2.579 + * @id: pci hotplug id connecting controller to HCD framework
   2.580 + * Context: !in_interrupt()
   2.581 + *
   2.582 + * Allocates basic PCI resources for this USB host controller, and
   2.583 + * then invokes the start() method for the HCD associated with it
   2.584 + * through the hotplug entry's driver_data.
   2.585 + *
   2.586 + * Store this function in the HCD's struct pci_driver as probe().
   2.587 + */
   2.588 +int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
   2.589 +{
   2.590 +	struct hc_driver	*driver;
   2.591 +	unsigned long		resource, len;
   2.592 +	void			*base;
   2.593 +	struct usb_bus		*bus;
   2.594 +	struct usb_hcd		*hcd;
   2.595 +	int			retval, region;
   2.596 +	char			buf [8], *bufp = buf;
   2.597 +
   2.598 +	if (!id || !(driver = (struct hc_driver *) id->driver_data))
   2.599 +		return -EINVAL;
   2.600 +
   2.601 +	if (pci_enable_device (dev) < 0)
   2.602 +		return -ENODEV;
   2.603 +	
   2.604 +        if (!dev->irq) {
   2.605 +        	err ("Found HC with no IRQ.  Check BIOS/PCI %s setup!",
   2.606 +			dev->slot_name);
   2.607 +   	        return -ENODEV;
   2.608 +        }
   2.609 +	
   2.610 +	if (driver->flags & HCD_MEMORY) {	// EHCI, OHCI
   2.611 +		region = 0;
   2.612 +		resource = pci_resource_start (dev, 0);
   2.613 +		len = pci_resource_len (dev, 0);
   2.614 +		if (!request_mem_region (resource, len, driver->description)) {
   2.615 +			dbg ("controller already in use");
   2.616 +			return -EBUSY;
   2.617 +		}
   2.618 +		base = ioremap_nocache (resource, len);
   2.619 +		if (base == NULL) {
   2.620 +			dbg ("error mapping memory");
   2.621 +			retval = -EFAULT;
   2.622 +clean_1:
   2.623 +			release_mem_region (resource, len);
   2.624 +			err ("init %s fail, %d", dev->slot_name, retval);
   2.625 +			return retval;
   2.626 +		}
   2.627 +
   2.628 +	} else { 				// UHCI
   2.629 +		resource = len = 0;
   2.630 +		for (region = 0; region < PCI_ROM_RESOURCE; region++) {
   2.631 +			if (!(pci_resource_flags (dev, region) & IORESOURCE_IO))
   2.632 +				continue;
   2.633 +
   2.634 +			resource = pci_resource_start (dev, region);
   2.635 +			len = pci_resource_len (dev, region);
   2.636 +			if (request_region (resource, len,
   2.637 +					driver->description))
   2.638 +				break;
   2.639 +		}
   2.640 +		if (region == PCI_ROM_RESOURCE) {
   2.641 +			dbg ("no i/o regions available");
   2.642 +			return -EBUSY;
   2.643 +		}
   2.644 +		base = (void *) resource;
   2.645 +	}
   2.646 +
   2.647 +	// driver->start(), later on, will transfer device from
   2.648 +	// control by SMM/BIOS to control by Linux (if needed)
   2.649 +
   2.650 +	pci_set_master (dev);
   2.651 +	hcd = driver->hcd_alloc ();
   2.652 +	if (hcd == NULL){
   2.653 +		dbg ("hcd alloc fail");
   2.654 +		retval = -ENOMEM;
   2.655 +clean_2:
   2.656 +		if (driver->flags & HCD_MEMORY) {
   2.657 +			iounmap (base);
   2.658 +			goto clean_1;
   2.659 +		} else {
   2.660 +			release_region (resource, len);
   2.661 +			err ("init %s fail, %d", dev->slot_name, retval);
   2.662 +			return retval;
   2.663 +		}
   2.664 +	}
   2.665 +	pci_set_drvdata(dev, hcd);
   2.666 +	hcd->driver = driver;
   2.667 +	hcd->description = driver->description;
   2.668 +	hcd->pdev = dev;
   2.669 +	printk (KERN_INFO "%s %s: %s\n",
   2.670 +			hcd->description,  dev->slot_name, dev->name);
   2.671 +
   2.672 +#ifndef __sparc__
   2.673 +	sprintf (buf, "%d", dev->irq);
   2.674 +#else
   2.675 +	bufp = __irq_itoa(dev->irq);
   2.676 +#endif
   2.677 +	if (request_irq (dev->irq, hcd_irq, SA_SHIRQ, hcd->description, hcd)
   2.678 +			!= 0) {
   2.679 +		err ("request interrupt %s failed", bufp);
   2.680 +		retval = -EBUSY;
   2.681 +clean_3:
   2.682 +		driver->hcd_free (hcd);
   2.683 +		goto clean_2;
   2.684 +	}
   2.685 +	hcd->irq = dev->irq;
   2.686 +
   2.687 +	hcd->regs = base;
   2.688 +	hcd->region = region;
   2.689 +	printk (KERN_INFO "%s %s: irq %s, %s %p\n",
   2.690 +		hcd->description,  dev->slot_name, bufp,
   2.691 +		(driver->flags & HCD_MEMORY) ? "pci mem" : "io base",
   2.692 +		base);
   2.693 +
   2.694 +// FIXME simpler: make "bus" be that data, not pointer to it.
   2.695 +// (fixed in 2.5)
   2.696 +	bus = usb_alloc_bus (&hcd_operations);
   2.697 +	if (bus == NULL) {
   2.698 +		dbg ("usb_alloc_bus fail");
   2.699 +		retval = -ENOMEM;
   2.700 +		free_irq (dev->irq, hcd);
   2.701 +		goto clean_3;
   2.702 +	}
   2.703 +	hcd->bus = bus;
   2.704 +	bus->bus_name = dev->slot_name;
   2.705 +	hcd->product_desc = dev->name;
   2.706 +	bus->hcpriv = (void *) hcd;
   2.707 +
   2.708 +	INIT_LIST_HEAD (&hcd->dev_list);
   2.709 +	INIT_LIST_HEAD (&hcd->hcd_list);
   2.710 +
   2.711 +	down (&hcd_list_lock);
   2.712 +	list_add (&hcd->hcd_list, &hcd_list);
   2.713 +	up (&hcd_list_lock);
   2.714 +
   2.715 +	usb_register_bus (bus);
   2.716 +
   2.717 +	if ((retval = driver->start (hcd)) < 0)
   2.718 +		usb_hcd_pci_remove (dev);
   2.719 +
   2.720 +	return retval;
   2.721 +} 
   2.722 +EXPORT_SYMBOL (usb_hcd_pci_probe);
   2.723 +
   2.724 +
   2.725 +/* may be called without controller electrically present */
   2.726 +/* may be called with controller, bus, and devices active */
   2.727 +
   2.728 +/**
   2.729 + * usb_hcd_pci_remove - shutdown processing for PCI-based HCDs
   2.730 + * @dev: USB Host Controller being removed
   2.731 + * Context: !in_interrupt()
   2.732 + *
   2.733 + * Reverses the effect of usb_hcd_pci_probe(), first invoking
   2.734 + * the HCD's stop() method.  It is always called from a thread
   2.735 + * context, normally "rmmod", "apmd", or something similar.
   2.736 + *
   2.737 + * Store this function in the HCD's struct pci_driver as remove().
   2.738 + */
   2.739 +void usb_hcd_pci_remove (struct pci_dev *dev)
   2.740 +{
   2.741 +	struct usb_hcd		*hcd;
   2.742 +	struct usb_device	*hub;
   2.743 +
   2.744 +	hcd = pci_get_drvdata(dev);
   2.745 +	if (!hcd)
   2.746 +		return;
   2.747 +	printk (KERN_INFO "%s %s: remove state %x\n",
   2.748 +		hcd->description,  dev->slot_name, hcd->state);
   2.749 +
   2.750 +	if (in_interrupt ()) BUG ();
   2.751 +
   2.752 +	hub = hcd->bus->root_hub;
   2.753 +	hcd->state = USB_STATE_QUIESCING;
   2.754 +
   2.755 +	dbg ("%s: roothub graceful disconnect", hcd->bus->bus_name);
   2.756 +	usb_disconnect (&hub);
   2.757 +	// usb_disconnect (&hcd->bus->root_hub);
   2.758 +
   2.759 +	hcd->driver->stop (hcd);
   2.760 +	hcd->state = USB_STATE_HALT;
   2.761 +
   2.762 +	free_irq (hcd->irq, hcd);
   2.763 +	if (hcd->driver->flags & HCD_MEMORY) {
   2.764 +		iounmap (hcd->regs);
   2.765 +		release_mem_region (pci_resource_start (dev, 0),
   2.766 +			pci_resource_len (dev, 0));
   2.767 +	} else {
   2.768 +		release_region (pci_resource_start (dev, hcd->region),
   2.769 +			pci_resource_len (dev, hcd->region));
   2.770 +	}
   2.771 +
   2.772 +	down (&hcd_list_lock);
   2.773 +	list_del (&hcd->hcd_list);
   2.774 +	up (&hcd_list_lock);
   2.775 +
   2.776 +	usb_deregister_bus (hcd->bus);
   2.777 +	usb_free_bus (hcd->bus);
   2.778 +	hcd->bus = NULL;
   2.779 +
   2.780 +	hcd->driver->hcd_free (hcd);
   2.781 +}
   2.782 +EXPORT_SYMBOL (usb_hcd_pci_remove);
   2.783 +
   2.784 +
   2.785 +#ifdef	CONFIG_PM
   2.786 +
   2.787 +/*
   2.788 + * Some "sleep" power levels imply updating struct usb_driver
   2.789 + * to include a callback asking hcds to do their bit by checking
   2.790 + * if all the drivers can suspend.  Gets involved with remote wakeup.
   2.791 + *
   2.792 + * If there are pending urbs, then HCs will need to access memory,
   2.793 + * causing extra power drain.  New sleep()/wakeup() PM calls might
   2.794 + * be needed, beyond PCI suspend()/resume().  The root hub timer
   2.795 + * still be accessing memory though ...
   2.796 + *
   2.797 + * FIXME:  USB should have some power budgeting support working with
   2.798 + * all kinds of hubs.
   2.799 + *
   2.800 + * FIXME:  This assumes only D0->D3 suspend and D3->D0 resume.
   2.801 + * D1 and D2 states should do something, yes?
   2.802 + *
   2.803 + * FIXME:  Should provide generic enable_wake(), calling pci_enable_wake()
   2.804 + * for all supported states, so that USB remote wakeup can work for any
   2.805 + * devices that support it (and are connected via powered hubs).
   2.806 + *
   2.807 + * FIXME:  resume doesn't seem to work right any more...
   2.808 + */
   2.809 +
   2.810 +
   2.811 +// 2.4 kernels have issued concurrent resumes (w/APM)
   2.812 +// we defend against that error; PCI doesn't yet.
   2.813 +
   2.814 +/**
   2.815 + * usb_hcd_pci_suspend - power management suspend of a PCI-based HCD
   2.816 + * @dev: USB Host Controller being suspended
   2.817 + *
   2.818 + * Store this function in the HCD's struct pci_driver as suspend().
   2.819 + */
   2.820 +int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
   2.821 +{
   2.822 +	struct usb_hcd		*hcd;
   2.823 +	int			retval;
   2.824 +
   2.825 +	hcd = pci_get_drvdata(dev);
   2.826 +	printk (KERN_INFO "%s %s: suspend to state %d\n",
   2.827 +		hcd->description,  dev->slot_name, state);
   2.828 +
   2.829 +	pci_save_state (dev, hcd->pci_state);
   2.830 +
   2.831 +	// FIXME for all connected devices, leaf-to-root:
   2.832 +	// driver->suspend()
   2.833 +	// proposed "new 2.5 driver model" will automate that
   2.834 +
   2.835 +	/* driver may want to disable DMA etc */
   2.836 +	retval = hcd->driver->suspend (hcd, state);
   2.837 +	hcd->state = USB_STATE_SUSPENDED;
   2.838 +
   2.839 + 	pci_set_power_state (dev, state);
   2.840 +	return retval;
   2.841 +}
   2.842 +EXPORT_SYMBOL (usb_hcd_pci_suspend);
   2.843 +
   2.844 +/**
   2.845 + * usb_hcd_pci_resume - power management resume of a PCI-based HCD
   2.846 + * @dev: USB Host Controller being resumed
   2.847 + *
   2.848 + * Store this function in the HCD's struct pci_driver as resume().
   2.849 + */
   2.850 +int usb_hcd_pci_resume (struct pci_dev *dev)
   2.851 +{
   2.852 +	struct usb_hcd		*hcd;
   2.853 +	int			retval;
   2.854 +
   2.855 +	hcd = pci_get_drvdata(dev);
   2.856 +	printk (KERN_INFO "%s %s: resume\n",
   2.857 +		hcd->description,  dev->slot_name);
   2.858 +
   2.859 +	/* guard against multiple resumes (APM bug?) */
   2.860 +	atomic_inc (&hcd->resume_count);
   2.861 +	if (atomic_read (&hcd->resume_count) != 1) {
   2.862 +		err ("concurrent PCI resumes for %s", hcd->bus->bus_name);
   2.863 +		retval = 0;
   2.864 +		goto done;
   2.865 +	}
   2.866 +
   2.867 +	retval = -EBUSY;
   2.868 +	if (hcd->state != USB_STATE_SUSPENDED) {
   2.869 +		dbg ("can't resume, not suspended!");
   2.870 +		goto done;
   2.871 +	}
   2.872 +	hcd->state = USB_STATE_RESUMING;
   2.873 +
   2.874 +	pci_set_power_state (dev, 0);
   2.875 +	pci_restore_state (dev, hcd->pci_state);
   2.876 +
   2.877 +	retval = hcd->driver->resume (hcd);
   2.878 +	if (!HCD_IS_RUNNING (hcd->state)) {
   2.879 +		dbg ("resume %s failure, retval %d",
   2.880 +			hcd->bus->bus_name, retval);
   2.881 +		hc_died (hcd);
   2.882 +// FIXME:  recover, reset etc.
   2.883 +	} else {
   2.884 +		// FIXME for all connected devices, root-to-leaf:
   2.885 +		// driver->resume ();
   2.886 +		// proposed "new 2.5 driver model" will automate that
   2.887 +	}
   2.888 +
   2.889 +done:
   2.890 +	atomic_dec (&hcd->resume_count);
   2.891 +	return retval;
   2.892 +}
   2.893 +EXPORT_SYMBOL (usb_hcd_pci_resume);
   2.894 +
   2.895 +#endif	/* CONFIG_PM */
   2.896 +
   2.897 +#endif
   2.898 +
   2.899 +/*-------------------------------------------------------------------------*/
   2.900 +
   2.901 +/*
   2.902 + * Generic HC operations.
   2.903 + */
   2.904 +
   2.905 +/*-------------------------------------------------------------------------*/
   2.906 +
   2.907 +/* called from khubd, or root hub init threads for hcd-private init */
   2.908 +static int hcd_alloc_dev (struct usb_device *udev)
   2.909 +{
   2.910 +	struct hcd_dev		*dev;
   2.911 +	struct usb_hcd		*hcd;
   2.912 +	unsigned long		flags;
   2.913 +
   2.914 +	if (!udev || udev->hcpriv)
   2.915 +		return -EINVAL;
   2.916 +	if (!udev->bus || !udev->bus->hcpriv)
   2.917 +		return -ENODEV;
   2.918 +	hcd = udev->bus->hcpriv;
   2.919 +	if (hcd->state == USB_STATE_QUIESCING)
   2.920 +		return -ENOLINK;
   2.921 +
   2.922 +	dev = (struct hcd_dev *) kmalloc (sizeof *dev, GFP_KERNEL);
   2.923 +	if (dev == NULL)
   2.924 +		return -ENOMEM;
   2.925 +	memset (dev, 0, sizeof *dev);
   2.926 +
   2.927 +	INIT_LIST_HEAD (&dev->dev_list);
   2.928 +	INIT_LIST_HEAD (&dev->urb_list);
   2.929 +
   2.930 +	spin_lock_irqsave (&hcd_data_lock, flags);
   2.931 +	list_add (&dev->dev_list, &hcd->dev_list);
   2.932 +	// refcount is implicit
   2.933 +	udev->hcpriv = dev;
   2.934 +	spin_unlock_irqrestore (&hcd_data_lock, flags);
   2.935 +
   2.936 +	return 0;
   2.937 +}
   2.938 +
   2.939 +/*-------------------------------------------------------------------------*/
   2.940 +
   2.941 +static void hcd_panic (void *_hcd)
   2.942 +{
   2.943 +	struct usb_hcd *hcd = _hcd;
   2.944 +	hcd->driver->stop (hcd);
   2.945 +}
   2.946 +
   2.947 +static void hc_died (struct usb_hcd *hcd)
   2.948 +{
   2.949 +	struct list_head	*devlist, *urblist;
   2.950 +	struct hcd_dev		*dev;
   2.951 +	struct urb		*urb;
   2.952 +	unsigned long		flags;
   2.953 +	
   2.954 +	/* flag every pending urb as done */
   2.955 +	spin_lock_irqsave (&hcd_data_lock, flags);
   2.956 +	list_for_each (devlist, &hcd->dev_list) {
   2.957 +		dev = list_entry (devlist, struct hcd_dev, dev_list);
   2.958 +		list_for_each (urblist, &dev->urb_list) {
   2.959 +			urb = list_entry (urblist, struct urb, urb_list);
   2.960 +			dbg ("shutdown %s urb %p pipe %x, current status %d",
   2.961 +				hcd->bus->bus_name,
   2.962 +				urb, urb->pipe, urb->status);
   2.963 +			if (urb->status == -EINPROGRESS)
   2.964 +				urb->status = -ESHUTDOWN;
   2.965 +		}
   2.966 +	}
   2.967 +	urb = (struct urb *) hcd->rh_timer.data;
   2.968 +	if (urb)
   2.969 +		urb->status = -ESHUTDOWN;
   2.970 +	spin_unlock_irqrestore (&hcd_data_lock, flags);
   2.971 +
   2.972 +	if (urb)
   2.973 +		rh_status_dequeue (hcd, urb);
   2.974 +
   2.975 +	/* hcd->stop() needs a task context */
   2.976 +	INIT_TQUEUE (&hcd->work, hcd_panic, hcd);
   2.977 +	(void) schedule_task (&hcd->work);
   2.978 +}
   2.979 +
   2.980 +/*-------------------------------------------------------------------------*/
   2.981 +
   2.982 +static void urb_unlink (struct urb *urb)
   2.983 +{
   2.984 +	unsigned long		flags;
   2.985 +	struct usb_device	*dev;
   2.986 +
   2.987 +	/* Release any periodic transfer bandwidth */
   2.988 +	if (urb->bandwidth)
   2.989 +		usb_release_bandwidth (urb->dev, urb,
   2.990 +			usb_pipeisoc (urb->pipe));
   2.991 +
   2.992 +	/* clear all state linking urb to this dev (and hcd) */
   2.993 +
   2.994 +	spin_lock_irqsave (&hcd_data_lock, flags);
   2.995 +	list_del_init (&urb->urb_list);
   2.996 +	dev = urb->dev;
   2.997 +	urb->dev = NULL;
   2.998 +	usb_dec_dev_use (dev);
   2.999 +	spin_unlock_irqrestore (&hcd_data_lock, flags);
  2.1000 +}
  2.1001 +
  2.1002 +
  2.1003 +/* may be called in any context with a valid urb->dev usecount */
  2.1004 +/* caller surrenders "ownership" of urb */
  2.1005 +
  2.1006 +static int hcd_submit_urb (struct urb *urb)
  2.1007 +{
  2.1008 +	int			status;
  2.1009 +	struct usb_hcd		*hcd;
  2.1010 +	struct hcd_dev		*dev;
  2.1011 +	unsigned long		flags;
  2.1012 +	int			pipe, temp, max;
  2.1013 +	int			mem_flags;
  2.1014 +
  2.1015 +	if (!urb || urb->hcpriv || !urb->complete)
  2.1016 +		return -EINVAL;
  2.1017 +
  2.1018 +	urb->status = -EINPROGRESS;
  2.1019 +	urb->actual_length = 0;
  2.1020 +	urb->bandwidth = 0;
  2.1021 +	INIT_LIST_HEAD (&urb->urb_list);
  2.1022 +
  2.1023 +	if (!urb->dev || !urb->dev->bus || urb->dev->devnum <= 0)
  2.1024 +		return -ENODEV;
  2.1025 +	hcd = urb->dev->bus->hcpriv;
  2.1026 +	dev = urb->dev->hcpriv;
  2.1027 +	if (!hcd || !dev)
  2.1028 +		return -ENODEV;
  2.1029 +
  2.1030 +	/* can't submit new urbs when quiescing, halted, ... */
  2.1031 +	if (hcd->state == USB_STATE_QUIESCING || !HCD_IS_RUNNING (hcd->state))
  2.1032 +		return -ESHUTDOWN;
  2.1033 +	pipe = urb->pipe;
  2.1034 +	temp = usb_pipetype (urb->pipe);
  2.1035 +	if (usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe),
  2.1036 +			usb_pipeout (pipe)))
  2.1037 +		return -EPIPE;
  2.1038 +
  2.1039 +	/* NOTE: 2.5 passes this value explicitly in submit() */
  2.1040 +	mem_flags = GFP_ATOMIC;
  2.1041 +
  2.1042 +	/* FIXME there should be a sharable lock protecting us against
  2.1043 +	 * config/altsetting changes and disconnects, kicking in here.
  2.1044 +	 */
  2.1045 +
  2.1046 +	/* Sanity check, so HCDs can rely on clean data */
  2.1047 +	max = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe));
  2.1048 +	if (max <= 0) {
  2.1049 +		err ("bogus endpoint (bad maxpacket)");
  2.1050 +		return -EINVAL;
  2.1051 +	}
  2.1052 +
  2.1053 +	/* "high bandwidth" mode, 1-3 packets/uframe? */
  2.1054 +	if (urb->dev->speed == USB_SPEED_HIGH) {
  2.1055 +		int	mult;
  2.1056 +		switch (temp) {
  2.1057 +		case PIPE_ISOCHRONOUS:
  2.1058 +		case PIPE_INTERRUPT:
  2.1059 +			mult = 1 + ((max >> 11) & 0x03);
  2.1060 +			max &= 0x03ff;
  2.1061 +			max *= mult;
  2.1062 +		}
  2.1063 +	}
  2.1064 +
  2.1065 +	/* periodic transfers limit size per frame/uframe */
  2.1066 +	switch (temp) {
  2.1067 +	case PIPE_ISOCHRONOUS: {
  2.1068 +		int	n, len;
  2.1069 +
  2.1070 +		if (urb->number_of_packets <= 0)		    
  2.1071 +			return -EINVAL;
  2.1072 +		for (n = 0; n < urb->number_of_packets; n++) {
  2.1073 +			len = urb->iso_frame_desc [n].length;
  2.1074 +			if (len < 0 || len > max) 
  2.1075 +				return -EINVAL;
  2.1076 +		}
  2.1077 +
  2.1078 +		}
  2.1079 +		break;
  2.1080 +	case PIPE_INTERRUPT:
  2.1081 +		if (urb->transfer_buffer_length > max)
  2.1082 +			return -EINVAL;
  2.1083 +	}
  2.1084 +
  2.1085 +	/* the I/O buffer must usually be mapped/unmapped */
  2.1086 +	if (urb->transfer_buffer_length < 0)
  2.1087 +		return -EINVAL;
  2.1088 +
  2.1089 +	if (urb->next) {
  2.1090 +		warn ("use explicit queuing not urb->next");
  2.1091 +		return -EINVAL;
  2.1092 +	}
  2.1093 +
  2.1094 +#ifdef DEBUG
  2.1095 +	/* stuff that drivers shouldn't do, but which shouldn't
  2.1096 +	 * cause problems in HCDs if they get it wrong.
  2.1097 +	 */
  2.1098 +	{
  2.1099 +	unsigned int	orig_flags = urb->transfer_flags;
  2.1100 +	unsigned int	allowed;
  2.1101 +
  2.1102 +	/* enforce simple/standard policy */
  2.1103 +	allowed = USB_ASYNC_UNLINK;	// affects later unlinks
  2.1104 +	allowed |= USB_NO_FSBR;		// only affects UHCI
  2.1105 +	switch (temp) {
  2.1106 +	case PIPE_CONTROL:
  2.1107 +		allowed |= USB_DISABLE_SPD;
  2.1108 +		break;
  2.1109 +	case PIPE_BULK:
  2.1110 +		allowed |= USB_DISABLE_SPD | USB_QUEUE_BULK
  2.1111 +				| USB_ZERO_PACKET | URB_NO_INTERRUPT;
  2.1112 +		break;
  2.1113 +	case PIPE_INTERRUPT:
  2.1114 +		allowed |= USB_DISABLE_SPD;
  2.1115 +		break;
  2.1116 +	case PIPE_ISOCHRONOUS:
  2.1117 +		allowed |= USB_ISO_ASAP;
  2.1118 +		break;
  2.1119 +	}
  2.1120 +	urb->transfer_flags &= allowed;
  2.1121 +
  2.1122 +	/* fail if submitter gave bogus flags */
  2.1123 +	if (urb->transfer_flags != orig_flags) {
  2.1124 +		err ("BOGUS urb flags, %x --> %x",
  2.1125 +			orig_flags, urb->transfer_flags);
  2.1126 +		return -EINVAL;
  2.1127 +	}
  2.1128 +	}
  2.1129 +#endif
  2.1130 +	/*
  2.1131 +	 * Force periodic transfer intervals to be legal values that are
  2.1132 +	 * a power of two (so HCDs don't need to).
  2.1133 +	 *
  2.1134 +	 * FIXME want bus->{intr,iso}_sched_horizon values here.  Each HC
  2.1135 +	 * supports different values... this uses EHCI/UHCI defaults (and
  2.1136 +	 * EHCI can use smaller non-default values).
  2.1137 +	 */
  2.1138 +	switch (temp) {
  2.1139 +	case PIPE_ISOCHRONOUS:
  2.1140 +	case PIPE_INTERRUPT:
  2.1141 +		/* too small? */
  2.1142 +		if (urb->interval <= 0)
  2.1143 +			return -EINVAL;
  2.1144 +		/* too big? */
  2.1145 +		switch (urb->dev->speed) {
  2.1146 +		case USB_SPEED_HIGH:	/* units are microframes */
  2.1147 +			// NOTE usb handles 2^15
  2.1148 +			if (urb->interval > (1024 * 8))
  2.1149 +				urb->interval = 1024 * 8;
  2.1150 +			temp = 1024 * 8;
  2.1151 +			break;
  2.1152 +		case USB_SPEED_FULL:	/* units are frames/msec */
  2.1153 +		case USB_SPEED_LOW:
  2.1154 +			if (temp == PIPE_INTERRUPT) {
  2.1155 +				if (urb->interval > 255)
  2.1156 +					return -EINVAL;
  2.1157 +				// NOTE ohci only handles up to 32
  2.1158 +				temp = 128;
  2.1159 +			} else {
  2.1160 +				if (urb->interval > 1024)
  2.1161 +					urb->interval = 1024;
  2.1162 +				// NOTE usb and ohci handle up to 2^15
  2.1163 +				temp = 1024;
  2.1164 +			}
  2.1165 +			break;
  2.1166 +		default:
  2.1167 +			return -EINVAL;
  2.1168 +		}
  2.1169 +		/* power of two? */
  2.1170 +		while (temp > urb->interval)
  2.1171 +			temp >>= 1;
  2.1172 +		urb->interval = temp;
  2.1173 +	}
  2.1174 +
  2.1175 +
  2.1176 +	/*
  2.1177 +	 * FIXME:  make urb timeouts be generic, keeping the HCD cores
  2.1178 +	 * as simple as possible.
  2.1179 +	 */
  2.1180 +
  2.1181 +	// NOTE:  a generic device/urb monitoring hook would go here.
  2.1182 +	// hcd_monitor_hook(MONITOR_URB_SUBMIT, urb)
  2.1183 +	// It would catch submission paths for all urbs.
  2.1184 +
  2.1185 +	/*
  2.1186 +	 * Atomically queue the urb,  first to our records, then to the HCD.
  2.1187 +	 * Access to urb->status is controlled by urb->lock ... changes on
  2.1188 +	 * i/o completion (normal or fault) or unlinking.
  2.1189 +	 */
  2.1190 +
  2.1191 +	// FIXME:  verify that quiescing hc works right (RH cleans up)
  2.1192 +
  2.1193 +	spin_lock_irqsave (&hcd_data_lock, flags);
  2.1194 +	if (HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_QUIESCING) {
  2.1195 +		usb_inc_dev_use (urb->dev);
  2.1196 +		list_add (&urb->urb_list, &dev->urb_list);
  2.1197 +		status = 0;
  2.1198 +	} else {
  2.1199 +		INIT_LIST_HEAD (&urb->urb_list);
  2.1200 +		status = -ESHUTDOWN;
  2.1201 +	}
  2.1202 +	spin_unlock_irqrestore (&hcd_data_lock, flags);
  2.1203 +	if (status)
  2.1204 +		return status;
  2.1205 +
  2.1206 +	// NOTE:  2.5 does this if !URB_NO_DMA_MAP transfer flag
  2.1207 +	
  2.1208 +	/* For 2.4, don't map bounce buffer if it's a root hub operation. */
  2.1209 +	if (urb->dev == hcd->bus->root_hub) {
  2.1210 +		status = rh_urb_enqueue (hcd, urb);
  2.1211 +	} else {
  2.1212 +#ifdef CONFIG_PCI
  2.1213 +		if (usb_pipecontrol (urb->pipe))
  2.1214 +			urb->setup_dma = pci_map_single (
  2.1215 +					hcd->pdev,
  2.1216 +					urb->setup_packet,
  2.1217 +					sizeof (struct usb_ctrlrequest),
  2.1218 +					PCI_DMA_TODEVICE);
  2.1219 +		if (urb->transfer_buffer_length != 0)
  2.1220 +			urb->transfer_dma = pci_map_single (
  2.1221 +					hcd->pdev,
  2.1222 +					urb->transfer_buffer,
  2.1223 +					urb->transfer_buffer_length,
  2.1224 +					usb_pipein (urb->pipe)
  2.1225 +					    ? PCI_DMA_FROMDEVICE
  2.1226 +					    : PCI_DMA_TODEVICE);
  2.1227 +#endif
  2.1228 +		status = hcd->driver->urb_enqueue (hcd, urb, mem_flags);
  2.1229 +	}
  2.1230 +	return status;
  2.1231 +}
  2.1232 +
  2.1233 +/*-------------------------------------------------------------------------*/
  2.1234 +
  2.1235 +/* called in any context */
  2.1236 +static int hcd_get_frame_number (struct usb_device *udev)
  2.1237 +{
  2.1238 +	struct usb_hcd	*hcd = (struct usb_hcd *)udev->bus->hcpriv;
  2.1239 +	return hcd->driver->get_frame_number (hcd);
  2.1240 +}
  2.1241 +
  2.1242 +/*-------------------------------------------------------------------------*/
  2.1243 +
  2.1244 +struct completion_splice {		// modified urb context:
  2.1245 +	/* did we complete? */
  2.1246 +	struct completion	done;
  2.1247 +
  2.1248 +	/* original urb data */
  2.1249 +	void			(*complete)(struct urb *);
  2.1250 +	void			*context;
  2.1251 +};
  2.1252 +
  2.1253 +static void unlink_complete (struct urb *urb)
  2.1254 +{
  2.1255 +	struct completion_splice	*splice;
  2.1256 +
  2.1257 +	splice = (struct completion_splice *) urb->context;
  2.1258 +
  2.1259 +	/* issue original completion call */
  2.1260 +	urb->complete = splice->complete;
  2.1261 +	urb->context = splice->context;
  2.1262 +	urb->complete (urb);
  2.1263 +
  2.1264 +	/* then let the synchronous unlink call complete */
  2.1265 +	complete (&splice->done);
  2.1266 +}
  2.1267 +
  2.1268 +/*
  2.1269 + * called in any context; note ASYNC_UNLINK restrictions
  2.1270 + *
  2.1271 + * caller guarantees urb won't be recycled till both unlink()
  2.1272 + * and the urb's completion function return
  2.1273 + */
  2.1274 +static int hcd_unlink_urb (struct urb *urb)
  2.1275 +{
  2.1276 +	struct hcd_dev			*dev;
  2.1277 +	struct usb_hcd			*hcd = 0;
  2.1278 +	unsigned long			flags;
  2.1279 +	struct completion_splice	splice;
  2.1280 +	int				retval;
  2.1281 +
  2.1282 +	if (!urb)
  2.1283 +		return -EINVAL;
  2.1284 +
  2.1285 +	/*
  2.1286 +	 * we contend for urb->status with the hcd core,
  2.1287 +	 * which changes it while returning the urb.
  2.1288 +	 *
  2.1289 +	 * Caller guaranteed that the urb pointer hasn't been freed, and
  2.1290 +	 * that it was submitted.  But as a rule it can't know whether or
  2.1291 +	 * not it's already been unlinked ... so we respect the reversed
  2.1292 +	 * lock sequence needed for the usb_hcd_giveback_urb() code paths
  2.1293 +	 * (urb lock, then hcd_data_lock) in case some other CPU is now
  2.1294 +	 * unlinking it.
  2.1295 +	 */
  2.1296 +	spin_lock_irqsave (&urb->lock, flags);
  2.1297 +	spin_lock (&hcd_data_lock);
  2.1298 +	if (!urb->hcpriv || urb->transfer_flags & USB_TIMEOUT_KILLED) {
  2.1299 +		retval = -EINVAL;
  2.1300 +		goto done;
  2.1301 +	}
  2.1302 +
  2.1303 +	if (!urb->dev || !urb->dev->bus) {
  2.1304 +		retval = -ENODEV;
  2.1305 +		goto done;
  2.1306 +	}
  2.1307 +
  2.1308 +	/* giveback clears dev; non-null means it's linked at this level */
  2.1309 +	dev = urb->dev->hcpriv;
  2.1310 +	hcd = urb->dev->bus->hcpriv;
  2.1311 +	if (!dev || !hcd) {
  2.1312 +		retval = -ENODEV;
  2.1313 +		goto done;
  2.1314 +	}
  2.1315 +
  2.1316 +	/* Any status except -EINPROGRESS means the HCD has already started
  2.1317 +	 * to return this URB to the driver.  In that case, there's no
  2.1318 +	 * more work for us to do.
  2.1319 +	 *
  2.1320 +	 * There's much magic because of "automagic resubmit" of interrupt
  2.1321 +	 * transfers, stopped only by explicit unlinking.  We won't issue
  2.1322 +	 * an "it's unlinked" callback more than once, but device drivers
  2.1323 +	 * can need to retry (SMP, -EAGAIN) an unlink request as well as
  2.1324 +	 * fake out the "not yet completed" state (set -EINPROGRESS) if
  2.1325 +	 * unlinking from complete().  Automagic eventually vanishes.
  2.1326 +	 *
  2.1327 +	 * FIXME use an URB_UNLINKED flag to match URB_TIMEOUT_KILLED
  2.1328 +	 */
  2.1329 +	if (urb->status != -EINPROGRESS) {
  2.1330 +		if (usb_pipetype (urb->pipe) == PIPE_INTERRUPT)
  2.1331 +			retval = -EAGAIN;
  2.1332 +		else
  2.1333 +			retval = -EBUSY;
  2.1334 +		goto done;
  2.1335 +	}
  2.1336 +
  2.1337 +	/* maybe set up to block on completion notification */
  2.1338 +	if ((urb->transfer_flags & USB_TIMEOUT_KILLED))
  2.1339 +		urb->status = -ETIMEDOUT;
  2.1340 +	else if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) {
  2.1341 +		if (in_interrupt ()) {
  2.1342 +			dbg ("non-async unlink in_interrupt");
  2.1343 +			retval = -EWOULDBLOCK;
  2.1344 +			goto done;
  2.1345 +		}
  2.1346 +		/* synchronous unlink: block till we see the completion */
  2.1347 +		init_completion (&splice.done);
  2.1348 +		splice.complete = urb->complete;
  2.1349 +		splice.context = urb->context;
  2.1350 +		urb->complete = unlink_complete;
  2.1351 +		urb->context = &splice;
  2.1352 +		urb->status = -ENOENT;
  2.1353 +	} else {
  2.1354 +		/* asynchronous unlink */
  2.1355 +		urb->status = -ECONNRESET;
  2.1356 +	}
  2.1357 +	spin_unlock (&hcd_data_lock);
  2.1358 +	spin_unlock_irqrestore (&urb->lock, flags);
  2.1359 +
  2.1360 +	if (urb == (struct urb *) hcd->rh_timer.data) {
  2.1361 +		rh_status_dequeue (hcd, urb);
  2.1362 +		retval = 0;
  2.1363 +	} else {
  2.1364 +		retval = hcd->driver->urb_dequeue (hcd, urb);
  2.1365 +// FIXME:  if retval and we tried to splice, whoa!!
  2.1366 +if (retval && urb->status == -ENOENT) err ("whoa! retval %d", retval);
  2.1367 +	}
  2.1368 +
  2.1369 +    	/* block till giveback, if needed */
  2.1370 +	if (!(urb->transfer_flags & (USB_ASYNC_UNLINK|USB_TIMEOUT_KILLED))
  2.1371 +			&& HCD_IS_RUNNING (hcd->state)
  2.1372 +			&& !retval) {
  2.1373 +		wait_for_completion (&splice.done);
  2.1374 +	} else if ((urb->transfer_flags & USB_ASYNC_UNLINK) && retval == 0) {
  2.1375 +		return -EINPROGRESS;
  2.1376 +	}
  2.1377 +	goto bye;
  2.1378 +done:
  2.1379 +	spin_unlock (&hcd_data_lock);
  2.1380 +	spin_unlock_irqrestore (&urb->lock, flags);
  2.1381 +bye:
  2.1382 +	if (retval)
  2.1383 +		dbg ("%s: hcd_unlink_urb fail %d",
  2.1384 +		    hcd ? hcd->bus->bus_name : "(no bus?)",
  2.1385 +		    retval);
  2.1386 +	return retval;
  2.1387 +}
  2.1388 +
  2.1389 +/*-------------------------------------------------------------------------*/
  2.1390 +
  2.1391 +/* called by khubd, rmmod, apmd, or other thread for hcd-private cleanup */
  2.1392 +
  2.1393 +// FIXME:  likely best to have explicit per-setting (config+alt)
  2.1394 +// setup primitives in the usbcore-to-hcd driver API, so nothing
  2.1395 +// is implicit.  kernel 2.5 needs a bunch of config cleanup...
  2.1396 +
  2.1397 +static int hcd_free_dev (struct usb_device *udev)
  2.1398 +{
  2.1399 +	struct hcd_dev		*dev;
  2.1400 +	struct usb_hcd		*hcd;
  2.1401 +	unsigned long		flags;
  2.1402 +
  2.1403 +	if (!udev || !udev->hcpriv)
  2.1404 +		return -EINVAL;
  2.1405 +
  2.1406 +	if (!udev->bus || !udev->bus->hcpriv)
  2.1407 +		return -ENODEV;
  2.1408 +
  2.1409 +	// should udev->devnum == -1 ??
  2.1410 +
  2.1411 +	dev = udev->hcpriv;
  2.1412 +	hcd = udev->bus->hcpriv;
  2.1413 +
  2.1414 +	/* device driver problem with refcounts? */
  2.1415 +	if (!list_empty (&dev->urb_list)) {
  2.1416 +		dbg ("free busy dev, %s devnum %d (bug!)",
  2.1417 +			hcd->bus->bus_name, udev->devnum);
  2.1418 +		return -EINVAL;
  2.1419 +	}
  2.1420 +
  2.1421 +	hcd->driver->free_config (hcd, udev);
  2.1422 +
  2.1423 +	spin_lock_irqsave (&hcd_data_lock, flags);
  2.1424 +	list_del (&dev->dev_list);
  2.1425 +	udev->hcpriv = NULL;
  2.1426 +	spin_unlock_irqrestore (&hcd_data_lock, flags);
  2.1427 +
  2.1428 +	kfree (dev);
  2.1429 +	return 0;
  2.1430 +}
  2.1431 +
  2.1432 +static struct usb_operations hcd_operations = {
  2.1433 +	allocate:		hcd_alloc_dev,
  2.1434 +	get_frame_number:	hcd_get_frame_number,
  2.1435 +	submit_urb:		hcd_submit_urb,
  2.1436 +	unlink_urb:		hcd_unlink_urb,
  2.1437 +	deallocate:		hcd_free_dev,
  2.1438 +};
  2.1439 +
  2.1440 +/*-------------------------------------------------------------------------*/
  2.1441 +
  2.1442 +static void hcd_irq (int irq, void *__hcd, struct pt_regs * r)
  2.1443 +{
  2.1444 +	struct usb_hcd		*hcd = __hcd;
  2.1445 +	int			start = hcd->state;
  2.1446 +
  2.1447 +	if (unlikely (hcd->state == USB_STATE_HALT))	/* irq sharing? */
  2.1448 +		return;
  2.1449 +
  2.1450 +	hcd->driver->irq (hcd, r);
  2.1451 +	if (hcd->state != start && hcd->state == USB_STATE_HALT)
  2.1452 +		hc_died (hcd);
  2.1453 +}
  2.1454 +
  2.1455 +/*-------------------------------------------------------------------------*/
  2.1456 +
  2.1457 +/**
  2.1458 + * usb_hcd_giveback_urb - return URB from HCD to device driver
  2.1459 + * @hcd: host controller returning the URB
  2.1460 + * @urb: urb being returned to the USB device driver.
  2.1461 + * @regs: saved hardware registers (ignored on 2.4 kernels)
  2.1462 + * Context: in_interrupt()
  2.1463 + *
  2.1464 + * This hands the URB from HCD to its USB device driver, using its
  2.1465 + * completion function.  The HCD has freed all per-urb resources
  2.1466 + * (and is done using urb->hcpriv).  It also released all HCD locks;
  2.1467 + * the device driver won't cause deadlocks if it resubmits this URB,
  2.1468 + * and won't confuse things by modifying and resubmitting this one.
  2.1469 + * Bandwidth and other resources will be deallocated.
  2.1470 + *
  2.1471 + * HCDs must not use this for periodic URBs that are still scheduled
  2.1472 + * and will be reissued.  They should just call their completion handlers
  2.1473 + * until the urb is returned to the device driver by unlinking.
  2.1474 + *
  2.1475 + * NOTE that no urb->next processing is done, even for isochronous URBs.
  2.1476 + * ISO streaming functionality can be achieved by having completion handlers
  2.1477 + * re-queue URBs.  Such explicit queuing doesn't discard error reports.
  2.1478 + */
  2.1479 +void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs)
  2.1480 +{
  2.1481 +	int is_root_hub_operation;
  2.1482 +
  2.1483 +	/* Work this out here as urb_unlink clears urb->dev */
  2.1484 +	is_root_hub_operation = (urb->dev == hcd->bus->root_hub);
  2.1485 +
  2.1486 +	urb_unlink (urb);
  2.1487 +
  2.1488 +	// NOTE:  a generic device/urb monitoring hook would go here.
  2.1489 +	// hcd_monitor_hook(MONITOR_URB_FINISH, urb, dev)
  2.1490 +	// It would catch exit/unlink paths for all urbs, but non-exit
  2.1491 +	// completions for periodic urbs need hooks inside the HCD.
  2.1492 +	// hcd_monitor_hook(MONITOR_URB_UPDATE, urb, dev)
  2.1493 +
  2.1494 +	// NOTE:  2.5 does this if !URB_NO_DMA_MAP transfer flag
  2.1495 +
  2.1496 +#ifdef CONFIG_PCI	
  2.1497 +	/* For 2.4, don't unmap bounce buffer if it's a root hub operation. */
  2.1498 +	if (usb_pipecontrol (urb->pipe) && !is_root_hub_operation)
  2.1499 +		pci_unmap_single (hcd->pdev, urb->setup_dma,
  2.1500 +				sizeof (struct usb_ctrlrequest),
  2.1501 +				PCI_DMA_TODEVICE);
  2.1502 +
  2.1503 +	if ((urb->transfer_buffer_length != 0) && !is_root_hub_operation)
  2.1504 +		pci_unmap_single (hcd->pdev, urb->transfer_dma,
  2.1505 +				urb->transfer_buffer_length,
  2.1506 +				usb_pipein (urb->pipe)
  2.1507 +				    ? PCI_DMA_FROMDEVICE
  2.1508 +				    : PCI_DMA_TODEVICE);
  2.1509 +#endif
  2.1510 +
  2.1511 +	/* pass ownership to the completion handler */
  2.1512 +	urb->complete (urb);
  2.1513 +}
  2.1514 +EXPORT_SYMBOL (usb_hcd_giveback_urb);