zoukankan      html  css  js  c++  java
  • Linux USB驱动数据结构

    struct usb_ctrlrequest
    {
        __u8 bRequestType;
        __u8 bRequest;
        __le16 wValue;
        __le16 wIndex;
        __le16 wLength;
    } __attribute__ ((packed));


    struct usb_wireless_ep_comp_descriptor
    {
        __u8  bLength;
        __u8  bDescriptorType;

        __u8  bMaxBurst;
        __u8  bMaxSequence;
        __le16 wMaxStreamDelay;
        __le16 wOverTheAirPacketSize;
        __u8  bOverTheAirInterval;
        __u8  bmCompAttributes;
    #define USB_ENDPOINT_SWITCH_MASK    0x03    /* in bmCompAttributes */
    #define USB_ENDPOINT_SWITCH_NO        0
    #define USB_ENDPOINT_SWITCH_SWITCH    1
    #define USB_ENDPOINT_SWITCH_SCALE    2
    } __attribute__((packed));



    struct usb_wireless_cap_descriptor
    {    /* Ultra Wide Band */
        __u8  bLength;
        __u8  bDescriptorType;
        __u8  bDevCapabilityType;

        __u8  bmAttributes;
    #define    USB_WIRELESS_P2P_DRD        (1 << 1)
    #define    USB_WIRELESS_BEACON_MASK    (3 << 2)
    #define    USB_WIRELESS_BEACON_SELF    (1 << 2)
    #define    USB_WIRELESS_BEACON_DIRECTED    (2 << 2)
    #define    USB_WIRELESS_BEACON_NONE    (3 << 2)
        __le16 wPHYRates;    /* bit rates, Mbps */
    #define    USB_WIRELESS_PHY_53        (1 << 0)    /* always set */
    #define    USB_WIRELESS_PHY_80        (1 << 1)
    #define    USB_WIRELESS_PHY_107        (1 << 2)    /* always set */
    #define    USB_WIRELESS_PHY_160        (1 << 3)
    #define    USB_WIRELESS_PHY_200        (1 << 4)    /* always set */
    #define    USB_WIRELESS_PHY_320        (1 << 5)
    #define    USB_WIRELESS_PHY_400        (1 << 6)
    #define    USB_WIRELESS_PHY_480        (1 << 7)
        __u8  bmTFITXPowerInfo;    /* TFI power levels */
        __u8  bmFFITXPowerInfo;    /* FFI power levels */
        __le16 bmBandGroup;
        __u8  bReserved;
    } __attribute__((packed));



    struct usb_string_descriptor
    {
        __u8  bLength;
        __u8  bDescriptorType;

        __le16 wData[1];        /* UTF-16LE encoded */
    } __attribute__ ((packed));


    struct usb_security_descriptor
    {
        __u8  bLength;
        __u8  bDescriptorType;

        __le16 wTotalLength;
        __u8  bNumEncryptionTypes;
    } __attribute__((packed));

    struct usb_qualifier_descriptor
    {
        __u8  bLength;
        __u8  bDescriptorType;

        __le16 bcdUSB;
        __u8  bDeviceClass;
        __u8  bDeviceSubClass;
        __u8  bDeviceProtocol;
        __u8  bMaxPacketSize0;
        __u8  bNumConfigurations;
        __u8  bRESERVED;
    } __attribute__ ((packed));


    struct usb_otg_descriptor
    {
        __u8  bLength;
        __u8  bDescriptorType;

        __u8  bmAttributes;    /* support for HNP, SRP, etc */
    } __attribute__ ((packed));


    struct usb_key_descriptor
    {
        __u8  bLength;
        __u8  bDescriptorType;

        __u8  tTKID[3];
        __u8  bReserved;
        __u8  bKeyData[0];
    } __attribute__((packed));


    struct usb_interface_descriptor
    {
        __u8  bLength;
        __u8  bDescriptorType;

        __u8  bInterfaceNumber;
        __u8  bAlternateSetting;
        __u8  bNumEndpoints;
        __u8  bInterfaceClass;
        __u8  bInterfaceSubClass;
        __u8  bInterfaceProtocol;
        __u8  iInterface;
    } __attribute__ ((packed));


    struct usb_interface_assoc_descriptor
    {
        __u8  bLength;
        __u8  bDescriptorType;

        __u8  bFirstInterface;
        __u8  bInterfaceCount;
        __u8  bFunctionClass;
        __u8  bFunctionSubClass;
        __u8  bFunctionProtocol;
        __u8  iFunction;
    } __attribute__ ((packed));


    struct usb_handshake
    {
        __u8 bMessageNumber;
        __u8 bStatus;
        __u8 tTKID[3];
        __u8 bReserved;
        __u8 CDID[16];
        __u8 nonce[16];
        __u8 MIC[8];
    } __attribute__((packed));


    struct usb_endpoint_descriptor
    {
        __u8  bLength;
        __u8  bDescriptorType;

        __u8  bEndpointAddress;
        __u8  bmAttributes;
        __le16 wMaxPacketSize;
        __u8  bInterval;

        /* NOTE:  these two are _only_ in audio endpoints. */
        /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
        __u8  bRefresh;
        __u8  bSynchAddress;
    } __attribute__ ((packed));



    struct usb_encryption_descriptor
    {
        __u8  bLength;
        __u8  bDescriptorType;

        __u8  bEncryptionType;
    #define    USB_ENC_TYPE_UNSECURE        0
    #define    USB_ENC_TYPE_WIRED        1    /* non-wireless mode */
    #define    USB_ENC_TYPE_CCM_1        2    /* aes128/cbc session */
    #define    USB_ENC_TYPE_RSA_1        3    /* rsa3072/sha1 auth */
        __u8  bEncryptionValue;        /* use in SET_ENCRYPTION */
        __u8  bAuthKeyIndex;
    } __attribute__((packed));



    struct usb_device_descriptor
    {
        __u8  bLength;
        __u8  bDescriptorType;

        __le16 bcdUSB;
        __u8  bDeviceClass;
        __u8  bDeviceSubClass;
        __u8  bDeviceProtocol;
        __u8  bMaxPacketSize0;
        __le16 idVendor;
        __le16 idProduct;
        __le16 bcdDevice;
        __u8  iManufacturer;
        __u8  iProduct;
        __u8  iSerialNumber;
        __u8  bNumConfigurations;
    } __attribute__ ((packed));


    struct usb_dev_cap_header
    {
        __u8  bLength;
        __u8  bDescriptorType;
        __u8  bDevCapabilityType;
    } __attribute__((packed));


    struct usb_descriptor_header
    {
        __u8  bLength;
        __u8  bDescriptorType;
    } __attribute__ ((packed));



    struct usb_debug_descriptor
    {
        __u8  bLength;
        __u8  bDescriptorType;

        /* bulk endpoints with 8 byte maxpacket */
        __u8  bDebugInEndpoint;
        __u8  bDebugOutEndpoint;
    } __attribute__((packed));



    struct usb_connection_context {
        __u8 CHID[16];        /* persistent host id */
        __u8 CDID[16];        /* device id (unique w/in host context) */
        __u8 CK[16];        /* connection key */
    } __attribute__((packed));


    struct usb_config_descriptor {
        __u8  bLength;
        __u8  bDescriptorType;

        __le16 wTotalLength;
        __u8  bNumInterfaces;
        __u8  bConfigurationValue;
        __u8  iConfiguration;
        __u8  bmAttributes;
        __u8  bMaxPower;
    } __attribute__ ((packed));


    struct usb_bos_descriptor {
        __u8  bLength;
        __u8  bDescriptorType;

        __le16 wTotalLength;
        __u8  bNumDeviceCaps;
    } __attribute__((packed));



    struct set_config_request {
        struct usb_device    *udev;
        int            config;
        struct work_struct    work;
    };



    struct usb_sg_request {
        int            status;
        size_t            bytes;

        /*
         * members below are private: to usbcore,
         * and are not provided for driver access!
         */
        spinlock_t        lock;

        struct usb_device    *dev;
        int            pipe;
        struct scatterlist    *sg;
        int            nents;

        int            entries;
        struct urb        **urbs;

        int            count;
        struct completion    complete;
    };

    int usb_sg_init (
        struct usb_sg_request    *io,
        struct usb_device    *dev,
        unsigned        pipe,
        unsigned        period,
        struct scatterlist    *sg,
        int            nents,
        size_t            length,
        gfp_t            mem_flags
    );



    struct usb_iso_packet_descriptor {
        unsigned int offset;
        unsigned int length;        /* expected length */
        unsigned int actual_length;
        int status;
    };





    struct usb_interface_cache {
        unsigned num_altsetting;    /* number of alternate settings */
        struct kref ref;        /* reference counter */

        /* variable-length array of alternate settings for this interface,
         * stored in no particular order */
        struct usb_host_interface altsetting[0];
    };



    struct usb_interface {
        /* array of alternate settings for this interface,
         * stored in no particular order */
        struct usb_host_interface *altsetting;

        struct usb_host_interface *cur_altsetting;    /* the currently
                         * active alternate setting */
        unsigned num_altsetting;    /* number of alternate settings */

        int minor;            /* minor number this interface is
                         * bound to */
        enum usb_interface_condition condition;        /* state of binding */
        unsigned is_active:1;        /* the interface is not suspended */
        unsigned needs_remote_wakeup:1;    /* driver requires remote wakeup */

        struct device dev;        /* interface specific device info */
        struct device *usb_dev;        /* pointer to the usb class's device, if any */
        int pm_usage_cnt;        /* usage counter for autosuspend */
    };



    struct usb_host_interface {
        struct usb_interface_descriptor    desc;

        /* array of desc.bNumEndpoint endpoints associated with this
         * interface setting.  these will be in no particular order.
         */
        struct usb_host_endpoint *endpoint;

        char *string;        /* iInterface string, if present */
        unsigned char *extra;   /* Extra descriptors */
        int extralen;
    };



    struct usb_host_endpoint {
        struct usb_endpoint_descriptor    desc;
        struct list_head        urb_list;
        void                *hcpriv;
        struct ep_device         *ep_dev;    /* For sysfs info */

        unsigned char *extra;   /* Extra descriptors */
        int extralen;
    };


    struct usb_host_config {
        struct usb_config_descriptor    desc;

        char *string;        /* iConfiguration string, if present */
        /* the interfaces associated with this configuration,
         * stored in no particular order */
        struct usb_interface *interface[USB_MAXINTERFACES];

        /* Interface information available even when this is not the
         * active configuration */
        struct usb_interface_cache *intf_cache[USB_MAXINTERFACES];

        unsigned char *extra;   /* Extra descriptors */
        int extralen;
    };



    struct usb_dynids {
        spinlock_t lock;
        struct list_head list;
    };

    struct usb_dynid {
        struct list_head node;
        struct usb_device_id id;
    };




    struct usbdrv_wrap {
        struct device_driver driver;
        int for_devices;
    };


    struct usb_driver {
        const char *name;

        int (*probe) (struct usb_interface *intf,
                  const struct usb_device_id *id);

        void (*disconnect) (struct usb_interface *intf);

        int (*ioctl) (struct usb_interface *intf, unsigned int code,
                void *buf);

        int (*suspend) (struct usb_interface *intf, pm_message_t message);
        int (*resume) (struct usb_interface *intf);

        void (*pre_reset) (struct usb_interface *intf);
        void (*post_reset) (struct usb_interface *intf);

        const struct usb_device_id *id_table;

        struct usb_dynids dynids;
        struct usbdrv_wrap drvwrap;
        unsigned int no_dynamic_id:1;
        unsigned int supports_autosuspend:1;
    };


    struct usb_devmap {
        unsigned long devicemap[128 / (8*sizeof(unsigned long))];
    };


    struct usb_device_driver {
        const char *name;

        int (*probe) (struct usb_device *udev);
        void (*disconnect) (struct usb_device *udev);

        int (*suspend) (struct usb_device *udev, pm_message_t message);
        int (*resume) (struct usb_device *udev);
        struct usbdrv_wrap drvwrap;
        unsigned int supports_autosuspend:1;
    };



    struct usb_device {
        int        devnum;        /* Address on USB bus */
        char        devpath [16];    /* Use in messages: /port/port/... */
        enum usb_device_state    state;    /* configured, not attached, etc */
        enum usb_device_speed    speed;    /* high/full/low (or error) */

        struct usb_tt    *tt;         /* low/full speed dev, highspeed hub */
        int        ttport;        /* device port on that tt hub */

        unsigned int toggle[2];        /* one bit for each endpoint
                         * ([0] = IN, [1] = OUT) */

        struct usb_device *parent;    /* our hub, unless we're the root */
        struct usb_bus *bus;        /* Bus we're part of */
        struct usb_host_endpoint ep0;

        struct device dev;        /* Generic device interface */

        struct usb_device_descriptor descriptor;/* Descriptor */
        struct usb_host_config *config;    /* All of the configs */

        struct usb_host_config *actconfig;/* the active configuration */
        struct usb_host_endpoint *ep_in[16];
        struct usb_host_endpoint *ep_out[16];

        char **rawdescriptors;        /* Raw descriptors for each config */

        unsigned short bus_mA;        /* Current available from the bus */
        u8 portnum;            /* Parent port number (origin 1) */
        u8 level;            /* Number of USB hub ancestors */

        unsigned discon_suspended:1;    /* Disconnected while suspended */
        unsigned have_langid:1;        /* whether string_langid is valid */
        int string_langid;        /* language ID for strings */

        /* static strings from the device */
        char *product;            /* iProduct string, if present */
        char *manufacturer;        /* iManufacturer string, if present */
        char *serial;            /* iSerialNumber string, if present */

        struct list_head filelist;
    #ifdef CONFIG_USB_DEVICE_CLASS
        struct device *usb_classdev;
    #endif
    #ifdef CONFIG_USB_DEVICEFS
        struct dentry *usbfs_dentry;    /* usbfs dentry entry for the device */
    #endif
        /*
         * Child devices - these can be either new devices
         * (if this is a hub device), or different instances
         * of this same device.
         *
         * Each instance needs its own set of data structures.
         */

        int maxchild;            /* Number of ports if hub */
        struct usb_device *children[USB_MAXCHILDREN];

        int pm_usage_cnt;        /* usage counter for autosuspend */
        u32 quirks;            /* quirks of the whole device */

    #ifdef CONFIG_PM
        struct delayed_work autosuspend; /* for delayed autosuspends */
        struct mutex pm_mutex;        /* protects PM operations */

        unsigned long last_busy;    /* time of last use */
        int autosuspend_delay;        /* in jiffies */

        unsigned auto_pm:1;        /* autosuspend/resume in progress */
        unsigned do_remote_wakeup:1;    /* remote wakeup should be enabled */
        unsigned autosuspend_disabled:1; /* autosuspend and autoresume */
        unsigned autoresume_disabled:1;  /*  disabled by the user */
    #endif
    };


    struct usb_class_driver {
        char *name;
        const struct file_operations *fops;
        int minor_base;
    };



    struct usb_bus {
        struct device *controller;    /* host/master side hardware */
        int busnum;            /* Bus number (in order of reg) */
        char *bus_name;            /* stable id (PCI slot_name etc) */
        u8 uses_dma;            /* Does the host controller use DMA? */
        u8 otg_port;            /* 0, or number of OTG/HNP port */
        unsigned is_b_host:1;        /* true during some HNP roleswitches */
        unsigned b_hnp_enable:1;    /* OTG: did A-Host enable HNP? */

        int devnum_next;        /* Next open device number in
                         * round-robin allocation */

        struct usb_devmap devmap;    /* device address allocation map */
        struct usb_device *root_hub;    /* Root hub */
        struct list_head bus_list;    /* list of busses */

        int bandwidth_allocated;    /* on this bus: how much of the time
                         * reserved for periodic (intr/iso)
                         * requests is used, on average?
                         * Units: microseconds/frame.
                         * Limits: Full/low speed reserve 90%,
                         * while high speed reserves 80%.
                         */
        int bandwidth_int_reqs;        /* number of Interrupt requests */
        int bandwidth_isoc_reqs;    /* number of Isoc. requests */

    #ifdef CONFIG_USB_DEVICEFS
        struct dentry *usbfs_dentry;    /* usbfs dentry entry for the bus */
    #endif
        struct class_device *class_dev;    /* class device for this bus */

    #if defined(CONFIG_USB_MON)
        struct mon_bus *mon_bus;    /* non-null when associated */
        int monitored;            /* non-zero when monitored */
    #endif
    };



    struct urb
    {
        /* private: usb core and host controller only fields in the urb */
        struct kref kref;        /* reference count of the URB */
        spinlock_t lock;        /* lock for the URB */
        void *hcpriv;            /* private data for host controller */
        atomic_t use_count;        d/* concurrent submissions counter */
        u8 reject;            /* submissions will fail */

        /* public: documented fields in the urb that can be used by drivers */
        struct list_head urb_list;    /* list head for use by the urb's
                         * current owner */
        struct usb_device *dev;     /* (in) pointer to associated device */
        unsigned int pipe;        /* (in) pipe information */
        int status;            /* (return) non-ISO status */
        unsigned int transfer_flags;    /* (in) URB_SHORT_NOT_OK | ...*/
        void *transfer_buffer;        /* (in) associated data buffer */
        dma_addr_t transfer_dma;    /* (in) dma addr for transfer_buffer */
        int transfer_buffer_length;    /* (in) data buffer length */
        int actual_length;        /* (return) actual transfer length */
        unsigned char *setup_packet;    /* (in) setup packet (control only) */
        dma_addr_t setup_dma;        /* (in) dma addr for setup_packet */
        int start_frame;        /* (modify) start frame (ISO) */
        int number_of_packets;        /* (in) number of ISO packets */
        int interval;            /* (modify) transfer interval
                         * (INT/ISO) */
        int error_count;        /* (return) number of ISO errors */
        void *context;            /* (in) context for completion */
        usb_complete_t complete;    /* (in) completion routine */
        struct usb_iso_packet_descriptor iso_frame_desc[0];
                        /* (in) ISO ONLY */
    };


    struct dev_state {
        struct list_head list;      /* state list */
        struct usb_device *dev;
        struct file *file;
        spinlock_t lock;            /* protects the async urb lists */
        struct list_head async_pending;
        struct list_head async_completed;
        wait_queue_head_t wait;     /* wake up if a request completed */
        unsigned int discsignr;
        struct pid *disc_pid;
        uid_t disc_uid, disc_euid;
        void __user *disccontext;
        unsigned long ifclaimed;
        u32 secid;
    };



    struct bus_attribute {
        struct attribute    attr;
        ssize_t (*show)(struct bus_type *, char * buf);
        ssize_t (*store)(struct bus_type *, const char * buf, size_t count);
    };


    struct bus_type {
        const char        * name;
        struct module        * owner;

        struct kset        subsys;
        struct kset        drivers;
        struct kset        devices;
        struct klist        klist_devices;
        struct klist        klist_drivers;

        struct blocking_notifier_head bus_notifier;

        struct bus_attribute    * bus_attrs;
        struct device_attribute    * dev_attrs;
        struct driver_attribute    * drv_attrs;
        struct bus_attribute drivers_autoprobe_attr;
        struct bus_attribute drivers_probe_attr;

        int        (*match)(struct device * dev, struct device_driver * drv);
        int        (*uevent)(struct device *dev, char **envp,
                      int num_envp, char *buffer, int buffer_size);
        int        (*probe)(struct device * dev);
        int        (*remove)(struct device * dev);
        void        (*shutdown)(struct device * dev);

        int (*suspend)(struct device * dev, pm_message_t state);
        int (*suspend_late)(struct device * dev, pm_message_t state);
        int (*resume_early)(struct device * dev);
        int (*resume)(struct device * dev);

        unsigned int drivers_autoprobe:1;
    };


    struct class_attribute {
        struct attribute    attr;
        ssize_t (*show)(struct class *, char * buf);
        ssize_t (*store)(struct class *, const char * buf, size_t count);
    };


    struct class_device {
        struct list_head    node;

        struct kobject        kobj;
        struct class        * class;    /* required */
        dev_t            devt;        /* dev_t, creates the sysfs "dev" */
        struct class_device_attribute *devt_attr;
        struct class_device_attribute uevent_attr;
        struct device        * dev;        /* not necessary, but nice to have */
        void            * class_data;    /* class-specific data */
        struct class_device    *parent;    /* parent of this child device, if there is one */
        struct attribute_group  ** groups;    /* optional groups */

        void    (*release)(struct class_device *dev);
        int    (*uevent)(struct class_device *dev, char **envp,
                   int num_envp, char *buffer, int buffer_size);
        char    class_id[BUS_ID_SIZE];    /* unique to this class */
    };


    struct class_device_attribute {
        struct attribute    attr;
        ssize_t (*show)(struct class_device *, char * buf);
        ssize_t (*store)(struct class_device *, const char * buf, size_t count);
    };


    struct class_interface {
        struct list_head    node;
        struct class        *class;

        int (*add)    (struct class_device *, struct class_interface *);
        void (*remove)    (struct class_device *, struct class_interface *);
        int (*add_dev)        (struct device *, struct class_interface *);
        void (*remove_dev)    (struct device *, struct class_interface *);
    };


    struct device {
        struct klist        klist_children;
        struct klist_node    knode_parent;        /* node in sibling list */
        struct klist_node    knode_driver;
        struct klist_node    knode_bus;
        struct device        *parent;

        struct kobject kobj;
        char    bus_id[BUS_ID_SIZE];    /* position on parent bus */
        struct device_type    *type;
        unsigned        is_registered:1;
        unsigned        uevent_suppress:1;
        struct device_attribute uevent_attr;
        struct device_attribute *devt_attr;

        struct semaphore    sem;    /* semaphore to synchronize calls to
                         * its driver.
                         */

        struct bus_type    * bus;        /* type of bus device is on */
        struct device_driver *driver;    /* which driver has allocated this
                           device */
        void        *driver_data;    /* data private to the driver */
        void        *platform_data;    /* Platform specific data, device
                           core doesn't touch it */
        struct dev_pm_info    power;

    #ifdef CONFIG_NUMA
        int        numa_node;    /* NUMA node this device is close to */
    #endif
        u64        *dma_mask;    /* dma mask (if dma'able device) */
        u64        coherent_dma_mask;/* Like dma_mask, but for
                             alloc_coherent mappings as
                             not all hardware supports
                             64 bit addresses for consistent
                             allocations such descriptors. */

        struct list_head    dma_pools;    /* dma pools (if dma'ble) */

        struct dma_coherent_mem    *dma_mem; /* internal for coherent mem
                             override */
        /* arch specific additions */
        struct dev_archdata    archdata;

        spinlock_t        devres_lock;
        struct list_head    devres_head;

        /* class_device migration path */
        struct list_head    node;
        struct class        *class;
        dev_t            devt;        /* dev_t, creates the sysfs "dev" */
        struct attribute_group    **groups;    /* optional groups */

        void    (*release)(struct device * dev);
    };



    struct device_attribute {
        struct attribute    attr;
        ssize_t (*show)(struct device *dev, struct device_attribute *attr,
                char *buf);
        ssize_t (*store)(struct device *dev, struct device_attribute *attr,
                 const char *buf, size_t count);
    };



    struct device_driver {
        const char        * name;
        struct bus_type        * bus;

        struct kobject        kobj;
        struct klist        klist_devices;
        struct klist_node    knode_bus;

        struct module        * owner;
        const char         * mod_name;    /* used for built-in modules */
        struct module_kobject    * mkobj;

        int    (*probe)    (struct device * dev);
        int    (*remove)    (struct device * dev);
        void    (*shutdown)    (struct device * dev);
        int    (*suspend)    (struct device * dev, pm_message_t state);
        int    (*resume)    (struct device * dev);
    };




    struct device_type {
        const char *name;
        struct attribute_group **groups;
        int (*uevent)(struct device *dev, char **envp, int num_envp,
                  char *buffer, int buffer_size);
        void (*release)(struct device *dev);
        int (*suspend)(struct device * dev, pm_message_t state);
        int (*resume)(struct device * dev);
    };



    struct driver_attribute {
        struct attribute    attr;
        ssize_t (*show)(struct device_driver *, char * buf);
        ssize_t (*store)(struct device_driver *, const char * buf, size_t count);
    };


    struct find_interface_arg {
        int minor;
        struct usb_interface *interface;
    };


    struct usb_device_id {
        /* which fields to match against? */
        __u16        match_flags;

        /* Used for product specific matches; range is inclusive */
        __u16        idVendor;
        __u16        idProduct;
        __u16        bcdDevice_lo;
        __u16        bcdDevice_hi;

        /* Used for device class matches */
        __u8        bDeviceClass;
        __u8        bDeviceSubClass;
        __u8        bDeviceProtocol;

        /* Used for interface class matches */
        __u8        bInterfaceClass;
        __u8        bInterfaceSubClass;
        __u8        bInterfaceProtocol;

        /* not matched against */
        kernel_ulong_t    driver_info;
    };


    struct hc_driver {
        const char    *description;    /* "ehci-hcd" etc */
        const char    *product_desc;    /* product/vendor string */
        size_t        hcd_priv_size;    /* size of private data */

        /* irq handler */
        irqreturn_t    (*irq) (struct usb_hcd *hcd);

        int    flags;
    #define    HCD_MEMORY    0x0001        /* HC regs use memory (else I/O) */
    #define    HCD_LOCAL_MEM    0x0002        /* HC needs local memory */
    #define    HCD_USB11    0x0010        /* USB 1.1 */
    #define    HCD_USB2    0x0020        /* USB 2.0 */

        /* called to init HCD and root hub */
        int    (*reset) (struct usb_hcd *hcd);
        int    (*start) (struct usb_hcd *hcd);

        /* NOTE:  these suspend/resume calls relate to the HC as
         * a whole, not just the root hub; they're for PCI bus glue.
         */
        /* called after suspending the hub, before entering D3 etc */
        int    (*pci_suspend) (struct usb_hcd *hcd, pm_message_t message);

        /* called after entering D0 (etc), before resuming the hub */
        int    (*pci_resume) (struct usb_hcd *hcd);

        /* cleanly make HCD stop writing memory and doing I/O */
        void    (*stop) (struct usb_hcd *hcd);

        /* shutdown HCD */
        void    (*shutdown) (struct usb_hcd *hcd);

        /* return current frame number */
        int    (*get_frame_number) (struct usb_hcd *hcd);

        /* manage i/o requests, device state */
        int    (*urb_enqueue)(struct usb_hcd *hcd,
                    struct urb *urb, gfp_t mem_flags);
        int    (*urb_dequeue)(struct usb_hcd *hcd,
                    struct urb *urb, int status);

        /* hw synch, freeing endpoint resources that urb_dequeue can't */
        void     (*endpoint_disable)(struct usb_hcd *hcd,
                struct usb_host_endpoint *ep);

        /* root hub support */
        int    (*hub_status_data) (struct usb_hcd *hcd, char *buf);
        int    (*hub_control) (struct usb_hcd *hcd,
                    u16 typeReq, u16 wValue, u16 wIndex,
                    char *buf, u16 wLength);
        int    (*bus_suspend)(struct usb_hcd *);
        int    (*bus_resume)(struct usb_hcd *);
        int    (*start_port_reset)(struct usb_hcd *, unsigned port_num);

            /* force handover of high-speed port to full-speed companion */
        void    (*relinquish_port)(struct usb_hcd *, int);
            /* has a port been handed over to a companion? */
        int    (*port_handed_over)(struct usb_hcd *, int);
    };


    struct hcd_timeout {    /* timeouts we allocate */
        struct list_head    timeout_list;
        struct timer_list    timer;
    };



    struct usb_hcd {

        /*
         * housekeeping
         */
        struct usb_bus        self;        /* hcd is-a bus */
        struct kref        kref;        /* reference counter */

        const char        *product_desc;    /* product/vendor string */
        char            irq_descr[24];    /* driver + bus # */

        struct timer_list    rh_timer;    /* drives root-hub polling */
        struct urb        *status_urb;    /* the current status urb */
    #ifdef CONFIG_PM
        struct work_struct    wakeup_work;    /* for remote wakeup */
    #endif

        /*
         * hardware info/state
         */
        const struct hc_driver    *driver;    /* hw-specific hooks */

        /* Flags that need to be manipulated atomically */
        unsigned long        flags;
    #define HCD_FLAG_HW_ACCESSIBLE    0x00000001
    #define HCD_FLAG_SAW_IRQ    0x00000002

        unsigned        rh_registered:1;/* is root hub registered? */

        /* The next flag is a stopgap, to be removed when all the HCDs
         * support the new root-hub polling mechanism. */
        unsigned        uses_new_polling:1;
        unsigned        poll_rh:1;    /* poll for rh status? */
        unsigned        poll_pending:1;    /* status has changed? */
        unsigned        wireless:1;    /* Wireless USB HCD */
        unsigned        authorized_default:1;
        unsigned        has_tt:1;    /* Integrated TT in root hub */

        int            irq;        /* irq allocated */
        void __iomem        *regs;        /* device memory/io */
        u64            rsrc_start;    /* memory/io resource start */
        u64            rsrc_len;    /* memory/io resource length */
        unsigned        power_budget;    /* in mA, 0 = no limit */

    #define HCD_BUFFER_POOLS    4
        struct dma_pool        *pool [HCD_BUFFER_POOLS];

        int            state;
    #    define    __ACTIVE        0x01
    #    define    __SUSPEND        0x04
    #    define    __TRANSIENT        0x80

    #    define    HC_STATE_HALT        0
    #    define    HC_STATE_RUNNING    (__ACTIVE)
    #    define    HC_STATE_QUIESCING    (__SUSPEND|__TRANSIENT|__ACTIVE)
    #    define    HC_STATE_RESUMING    (__SUSPEND|__TRANSIENT)
    #    define    HC_STATE_SUSPENDED    (__SUSPEND)

    #define    HC_IS_RUNNING(state) ((state) & __ACTIVE)
    #define    HC_IS_SUSPENDED(state) ((state) & __SUSPEND)

        /* more shared queuing code would be good; it should support
         * smarter scheduling, handle transaction translators, etc;
         * input size of periodic table to an interrupt scheduler.
         * (ohci 32, uhci 1024, ehci 256/512/1024).
         */

        /* The HC driver's private data is stored at the end of
         * this structure.
         */
        unsigned long hcd_priv[0]
                __attribute__ ((aligned(sizeof(unsigned long))));
    };


    struct usb_mon_operations {
        void (*urb_submit)(struct usb_bus *bus, struct urb *urb);
        void (*urb_submit_error)(struct usb_bus *bus, struct urb *urb, int err);
        void (*urb_complete)(struct usb_bus *bus, struct urb *urb, int status);
        /* void (*urb_unlink)(struct usb_bus *bus, struct urb *urb); */
    };




    struct usb_busmap {
        unsigned long busmap [USB_MAXBUS / (8*sizeof (unsigned long))];
    };


    struct usb_device_status {
        unsigned int lastev;
    };

    struct class_info {
        int class;
        char *class_name;
    };


    struct dev_state {
        struct list_head list;      /* state list */
        struct usb_device *dev;
        struct file *file;
        spinlock_t lock;            /* protects the async urb lists */
        struct list_head async_pending;
        struct list_head async_completed;
        wait_queue_head_t wait;     /* wake up if a request completed */
        unsigned int discsignr;
        struct pid *disc_pid;
        uid_t disc_uid, disc_euid;
        void __user *disccontext;
        unsigned long ifclaimed;
        u32 secid;
    };

    struct async {
        struct list_head asynclist;
        struct dev_state *ps;
        struct pid *pid;
        uid_t uid, euid;
        unsigned int signr;
        unsigned int ifnum;
        void __user *userbuffer;
        void __user *userurb;
        struct urb *urb;
        int status;
        u32 secid;
    };


    struct ep_device {
        struct usb_endpoint_descriptor *desc;
        struct usb_device *udev;
        struct device dev;
        int minor;
    };
    #define to_ep_device(_dev)
        container_of(_dev, struct ep_device, dev)

    struct ep_attribute {
        struct attribute attr;
        ssize_t (*show)(struct usb_device *,
                struct usb_endpoint_descriptor *, char *);
    };

    static struct endpoint_class {
        struct kref kref;
        struct class *class;
    } *ep_class;


    static struct usb_class {
        struct kref kref;
        struct class *class;
    } *usb_class;


    struct usb_hub {
        struct device        *intfdev;    /* the "interface" device */
        struct usb_device    *hdev;
        struct kref        kref;
        struct urb        *urb;        /* for interrupt polling pipe */

        /* buffer for urb ... with extra space in case of babble */
        char            (*buffer)[8];
        dma_addr_t        buffer_dma;    /* DMA address for buffer */
        union {
            struct usb_hub_status    hub;
            struct usb_port_status    port;
        }            *status;    /* buffer for status reports */
        struct mutex        status_mutex;    /* for the status buffer */

        int            error;        /* last reported error */
        int            nerrors;    /* track consecutive errors */

        struct list_head    event_list;    /* hubs w/data or errs ready */
        unsigned long        event_bits[1];    /* status change bitmask */
        unsigned long        change_bits[1];    /* ports with logical connect
                                status change */
        unsigned long        busy_bits[1];    /* ports being reset or
                                resumed */
    #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
    #error event_bits[] is too short!
    #endif

        struct usb_hub_descriptor *descriptor;    /* class descriptor */
        struct usb_tt        tt;        /* Transaction Translator */

        unsigned        mA_per_port;    /* current for each child */

        unsigned        limited_power:1;
        unsigned        quiescing:1;
        unsigned        disconnected:1;

        unsigned        has_indicators:1;
        u8            indicator[USB_MAXCHILDREN];
        struct delayed_work    leds;
        struct delayed_work    init_work;
    };


    enum hub_activation_type {
        HUB_INIT, HUB_INIT2, HUB_INIT3,
        HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME,
    };


    enum hub_quiescing_type {
        HUB_DISCONNECT, HUB_PRE_RESET, HUB_SUSPEND
    };


    enum hub_activation_type {
        HUB_INIT, HUB_INIT2, HUB_INIT3,
        HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME,
    };


    struct usb_tt {
        struct usb_device    *hub;    /* upstream highspeed hub */
        int            multi;    /* true means one TT per port */
        unsigned        think_time;    /* think time in ns */

        /* for control/bulk error recovery (CLEAR_TT_BUFFER) */
        spinlock_t        lock;
        struct list_head    clear_list;    /* of usb_tt_clear */
        struct work_struct            kevent;
    };

    struct usb_tt_clear {
        struct list_head    clear_list;
        unsigned        tt;
        u16            devinfo;
    };


    struct usb_port_status {
        __le16 wPortStatus;
        __le16 wPortChange;
    } __attribute__ ((packed));


    struct usb_hub_status {
        __le16 wHubStatus;
        __le16 wHubChange;
    } __attribute__ ((packed));


    struct usb_hub_descriptor {
        __u8  bDescLength;
        __u8  bDescriptorType;
        __u8  bNbrPorts;
        __le16 wHubCharacteristics;
        __u8  bPwrOn2PwrGood;
        __u8  bHubContrCurrent;
            /* add 1 bit for hub status change; round to bytes */
        __u8  DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
        __u8  PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
    } __attribute__ ((packed));


    enum {
        Opt_devuid, Opt_devgid, Opt_devmode,
        Opt_busuid, Opt_busgid, Opt_busmode,
        Opt_listuid, Opt_listgid, Opt_listmode,
        Opt_err,
    };


    struct set_config_request {
        struct usb_device    *udev;
        int            config;
        struct work_struct    work;
        struct list_head    node;
    };



    struct api_context {
        struct completion    done;
        int            status;
    };


    struct find_interface_arg {
        int minor;
        struct usb_interface *interface;
    };


    enum
    {
        PM_SYS_UNKNOWN = 0x00000000, /* generic */
        PM_SYS_KBC =     0x41d00303, /* keyboard controller */
        PM_SYS_COM =     0x41d00500, /* serial port */
        PM_SYS_IRDA =     0x41d00510, /* IRDA controller */
        PM_SYS_FDC =     0x41d00700, /* floppy controller */
        PM_SYS_VGA =     0x41d00900, /* VGA controller */
        PM_SYS_PCMCIA =     0x41d00e00, /* PCMCIA controller */
    };



    struct pm_dev
    {
        pm_dev_t     type;
        unsigned long     id;
        pm_callback     callback;
        void        *data;

        unsigned long     flags;
        unsigned long     state;
        unsigned long     prev_state;

        struct list_head entry;
    };

    struct pm_ops {
        int (*valid)(suspend_state_t state);
        int (*set_target)(suspend_state_t state);
        int (*prepare)(suspend_state_t state);
        int (*enter)(suspend_state_t state);
        int (*finish)(suspend_state_t state);
    };


    typedef struct pm_message {
        int event;
    } pm_message_t;


    struct dev_pm_info {
        pm_message_t        power_state;
        unsigned        can_wakeup:1;
    #ifdef    CONFIG_PM
        unsigned        should_wakeup:1;
        pm_message_t        prev_state;
        void            * saved_state;
        struct device        * pm_parent;
        struct list_head    entry;
    #endif
    };


    struct usb_hcd {

        /*
         * housekeeping
         */
        struct usb_bus        self;        /* hcd is-a bus */
        struct kref        kref;        /* reference counter */

        const char        *product_desc;    /* product/vendor string */
        char            irq_descr[24];    /* driver + bus # */

        struct timer_list    rh_timer;    /* drives root-hub polling */
        struct urb        *status_urb;    /* the current status urb */
    #ifdef CONFIG_PM
        struct work_struct    wakeup_work;    /* for remote wakeup */
    #endif

        /*
         * hardware info/state
         */
        const struct hc_driver    *driver;    /* hw-specific hooks */

        /* Flags that need to be manipulated atomically */
        unsigned long        flags;
    #define HCD_FLAG_HW_ACCESSIBLE    0x00000001
    #define HCD_FLAG_SAW_IRQ    0x00000002

        unsigned        rh_registered:1;/* is root hub registered? */

        /* The next flag is a stopgap, to be removed when all the HCDs
         * support the new root-hub polling mechanism. */
        unsigned        uses_new_polling:1;
        unsigned        poll_rh:1;    /* poll for rh status? */
        unsigned        poll_pending:1;    /* status has changed? */
        unsigned        wireless:1;    /* Wireless USB HCD */

        int            irq;        /* irq allocated */
        void __iomem        *regs;        /* device memory/io */
        u64            rsrc_start;    /* memory/io resource start */
        u64            rsrc_len;    /* memory/io resource length */
        unsigned        power_budget;    /* in mA, 0 = no limit */

    #define HCD_BUFFER_POOLS    4
        struct dma_pool        *pool [HCD_BUFFER_POOLS];

        int            state;
    #    define    __ACTIVE        0x01
    #    define    __SUSPEND        0x04
    #    define    __TRANSIENT        0x80

    #    define    HC_STATE_HALT        0
    #    define    HC_STATE_RUNNING    (__ACTIVE)
    #    define    HC_STATE_QUIESCING    (__SUSPEND|__TRANSIENT|__ACTIVE)
    #    define    HC_STATE_RESUMING    (__SUSPEND|__TRANSIENT)
    #    define    HC_STATE_SUSPENDED    (__SUSPEND)

    #define    HC_IS_RUNNING(state) ((state) & __ACTIVE)
    #define    HC_IS_SUSPENDED(state) ((state) & __SUSPEND)

        /* more shared queuing code would be good; it should support
         * smarter scheduling, handle transaction translators, etc;
         * input size of periodic table to an interrupt scheduler.
         * (ohci 32, uhci 1024, ehci 256/512/1024).
         */

        /* The HC driver's private data is stored at the end of
         * this structure.
         */
        unsigned long hcd_priv[0]
                __attribute__ ((aligned (sizeof(unsigned long))));
    };



    struct uhci_hcd {

        /* debugfs */
        struct dentry *dentry;

        /* Grabbed from PCI */
        unsigned long io_addr;

        struct dma_pool *qh_pool;
        struct dma_pool *td_pool;

        struct uhci_td *term_td;    /* Terminating TD, see UHCI bug */
        struct uhci_qh *skelqh[UHCI_NUM_SKELQH];    /* Skeleton QHs */
        struct uhci_qh *next_qh;    /* Next QH to scan */

        spinlock_t lock;

        dma_addr_t frame_dma_handle;    /* Hardware frame list */
        __le32 *frame;
        void **frame_cpu;        /* CPU's frame list */

        enum uhci_rh_state rh_state;
        unsigned long auto_stop_time;        /* When to AUTO_STOP */

        unsigned int frame_number;        /* As of last check */
        unsigned int is_stopped;
    #define UHCI_IS_STOPPED        9999        /* Larger than a frame # */
        unsigned int last_iso_frame;        /* Frame of last scan */
        unsigned int cur_iso_frame;        /* Frame for current scan */

        unsigned int scan_in_progress:1;    /* Schedule scan is running */
        unsigned int need_rescan:1;        /* Redo the schedule scan */
        unsigned int dead:1;            /* Controller has died */
        unsigned int working_RD:1;        /* Suspended root hub doesn't
                               need to be polled */
        unsigned int is_initialized:1;        /* Data structure is usable */
        unsigned int fsbr_is_on:1;        /* FSBR is turned on */
        unsigned int fsbr_is_wanted:1;        /* Does any URB want FSBR? */
        unsigned int fsbr_expiring:1;        /* FSBR is timing out */

        struct timer_list fsbr_timer;        /* For turning off FBSR */

        /* Support for port suspend/resume/reset */
        unsigned long port_c_suspend;        /* Bit-arrays of ports */
        unsigned long resuming_ports;
        unsigned long ports_timeout;        /* Time to stop signalling */

        struct list_head idle_qh_list;        /* Where the idle QHs live */

        int rh_numports;            /* Number of root-hub ports */

        wait_queue_head_t waitqh;        /* endpoint_disable waiters */
        int num_waiting;            /* Number of waiters */

        int total_load;                /* Sum of array values */
        short load[MAX_PHASE];            /* Periodic allocations */
    };


    struct uhci_td {
        /* Hardware fields */
        __le32 link;
        __le32 status;
        __le32 token;
        __le32 buffer;

        /* Software fields */
        dma_addr_t dma_handle;

        struct list_head list;

        int frame;            /* for iso: what frame? */
        struct list_head fl_list;
    } __attribute__((aligned(16)));


    enum uhci_rh_state {
        /* In the following states the HC must be halted.
         * These two must come first. */
        UHCI_RH_RESET,
        UHCI_RH_SUSPENDED,

        UHCI_RH_AUTO_STOPPED,
        UHCI_RH_RESUMING,

        /* In this state the HC changes from running to halted,
         * so it can legally appear either way. */
        UHCI_RH_SUSPENDING,

        /* In the following states it's an error if the HC is halted.
         * These two must come last. */
        UHCI_RH_RUNNING,        /* The normal state */
        UHCI_RH_RUNNING_NODEVS,        /* Running with no devices attached */
    };


    struct uhci_qh {
        /* Hardware fields */
        __le32 link;            /* Next QH in the schedule */
        __le32 element;            /* Queue element (TD) pointer */

        /* Software fields */
        dma_addr_t dma_handle;

        struct list_head node;        /* Node in the list of QHs */
        struct usb_host_endpoint *hep;    /* Endpoint information */
        struct usb_device *udev;
        struct list_head queue;        /* Queue of urbps for this QH */
        struct uhci_td *dummy_td;    /* Dummy TD to end the queue */
        struct uhci_td *post_td;    /* Last TD completed */

        struct usb_iso_packet_descriptor *iso_packet_desc;
                        /* Next urb->iso_frame_desc entry */
        unsigned long advance_jiffies;    /* Time of last queue advance */
        unsigned int unlink_frame;    /* When the QH was unlinked */
        unsigned int period;        /* For Interrupt and Isochronous QHs */
        short phase;            /* Between 0 and period-1 */
        short load;            /* Periodic time requirement, in us */
        unsigned int iso_frame;        /* Frame # for iso_packet_desc */
        int iso_status;            /* Status for Isochronous URBs */

        int state;            /* QH_STATE_xxx; see above */
        int type;            /* Queue type (control, bulk, etc) */
        int skel;            /* Skeleton queue number */

        unsigned int initial_toggle:1;    /* Endpoint's current toggle value */
        unsigned int needs_fixup:1;    /* Must fix the TD toggle values */
        unsigned int is_stopped:1;    /* Queue was stopped by error/unlink */
        unsigned int wait_expired:1;    /* QH_WAIT_TIMEOUT has expired */
        unsigned int bandwidth_reserved:1;    /* Periodic bandwidth has
                             * been allocated */
    } __attribute__((aligned(16)));



    struct urb_priv {
        struct list_head node;        /* Node in the QH's urbp list */

        struct urb *urb;

        struct uhci_qh *qh;        /* QH for this URB */
        struct list_head td_list;

        unsigned fsbr:1;        /* URB wants FSBR */
    };


    /* embedded in scsi_cmnd */
    struct scsi_pointer {
        char *ptr;        /* data pointer */
        int this_residual;    /* left in this buffer */
        struct scatterlist *buffer;    /* which buffer */
        int buffers_residual;    /* how many buffers left */

            dma_addr_t dma_handle;

        volatile int Status;
        volatile int Message;
        volatile int have_data_in;
        volatile int sent_command;
        volatile int phase;
    };

    struct scsi_cmnd {
        struct scsi_device *device;
        struct list_head list;  /* scsi_cmnd participates in queue lists */
        struct list_head eh_entry; /* entry for the host eh_cmd_q */
        int eh_eflags;        /* Used by error handlr */
        void (*done) (struct scsi_cmnd *);    /* Mid-level done function */

        /*
         * A SCSI Command is assigned a nonzero serial_number before passed
         * to the driver's queue command function.  The serial_number is
         * cleared when scsi_done is entered indicating that the command
         * has been completed.  It currently doesn't have much use other
         * than printk's.  Some lldd's use this number for other purposes.
         * It's almost certain that such usages are either incorrect or
         * meaningless.  Please kill all usages other than printk's.  Also,
         * as this number is always identical to ->pid, please convert
         * printk's to use ->pid, so that we can kill this field.
         */
        unsigned long serial_number;
        /*
         * This is set to jiffies as it was when the command was first
         * allocated.  It is used to time how long the command has
         * been outstanding
         */
        unsigned long jiffies_at_alloc;

        int retries;
        int allowed;
        int timeout_per_command;

        unsigned char cmd_len;
        enum dma_data_direction sc_data_direction;

        /* These elements define the operation we are about to perform */
    #define MAX_COMMAND_SIZE    16
        unsigned char cmnd[MAX_COMMAND_SIZE];
        unsigned request_bufflen;    /* Actual request size */

        struct timer_list eh_timeout;    /* Used to time out the command. */
        void *request_buffer;        /* Actual requested buffer */

        /* These elements define the operation we ultimately want to perform */
        unsigned short use_sg;    /* Number of pieces of scatter-gather */
        unsigned short sglist_len;    /* size of malloc'd scatter-gather list */

        unsigned underflow;    /* Return error if less than
                       this amount is transferred */

        unsigned transfersize;    /* How much we are guaranteed to
                       transfer with each SCSI transfer
                       (ie, between disconnect /
                       reconnects.   Probably == sector
                       size */

        int resid;        /* Number of bytes requested to be
                       transferred less actual number
                       transferred (0 if not supported) */

        struct request *request;    /* The command we are
                              working on */

    #define SCSI_SENSE_BUFFERSIZE     96
        unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
                    /* obtained by REQUEST SENSE when
                     * CHECK CONDITION is received on original
                     * command (auto-sense) */

        /* Low-level done function - can be used by low-level driver to point
         *        to completion function.  Not used by mid/upper level code. */
        void (*scsi_done) (struct scsi_cmnd *);

        /*
         * The following fields can be written to by the host specific code.
         * Everything else should be left alone.
         */
        struct scsi_pointer SCp;    /* Scratchpad used by some host adapters */

        unsigned char *host_scribble;    /* The host adapter is allowed to
                         * call scsi_malloc and get some memory
                         * and hang it here.  The host adapter
                         * is also expected to call scsi_free
                         * to release this memory.  (The memory
                         * obtained by scsi_malloc is guaranteed
                         * to be at an address < 16Mb). */

        int result;        /* Status code from lower level driver */

        unsigned char tag;    /* SCSI-II queued command tag */
        unsigned long pid;    /* Process ID, starts at 0. Unique per host. */
    };



    struct scsi_mode_data {
        __u32    length;
        __u16    block_descriptor_length;
        __u8    medium_type;
        __u8    device_specific;
        __u8    header_length;
        __u8    longlba:1;
    };

    /*
     * sdev state: If you alter this, you also need to alter scsi_sysfs.c
     * (for the ascii descriptions) and the state model enforcer:
     * scsi_lib:scsi_device_set_state().
     */
    enum scsi_device_state {
        SDEV_CREATED = 1,    /* device created but not added to sysfs
                     * Only internal commands allowed (for inq) */
        SDEV_RUNNING,        /* device properly configured
                     * All commands allowed */
        SDEV_CANCEL,        /* beginning to delete device
                     * Only error handler commands allowed */
        SDEV_DEL,        /* device deleted
                     * no commands allowed */
        SDEV_QUIESCE,        /* Device quiescent.  No block commands
                     * will be accepted, only specials (which
                     * originate in the mid-layer) */
        SDEV_OFFLINE,        /* Device offlined (by error handling or
                     * user request */
        SDEV_BLOCK,        /* Device blocked by scsi lld.  No scsi
                     * commands from user or midlayer should be issued
                     * to the scsi lld. */
    };

    struct scsi_device {
        struct Scsi_Host *host;
        struct request_queue *request_queue;

        /* the next two are protected by the host->host_lock */
        struct list_head    siblings;   /* list of all devices on this host */
        struct list_head    same_target_siblings; /* just the devices sharing same target id */

        /* this is now protected by the request_queue->queue_lock */
        unsigned int device_busy;    /* commands actually active on
                         * low-level. protected by queue_lock. */
        spinlock_t list_lock;
        struct list_head cmd_list;    /* queue of in use SCSI Command structures */
        struct list_head starved_entry;
        struct scsi_cmnd *current_cmnd;    /* currently active command */
        unsigned short queue_depth;    /* How deep of a queue we want */
        unsigned short last_queue_full_depth; /* These two are used by */
        unsigned short last_queue_full_count; /* scsi_track_queue_full() */
        unsigned long last_queue_full_time;/* don't let QUEUE_FULLs on the same
                           jiffie count on our counter, they
                           could all be from the same event. */

        unsigned int id, lun, channel;

        unsigned int manufacturer;    /* Manufacturer of device, for using
                         * vendor-specific cmd's */
        unsigned sector_size;    /* size in bytes */

        void *hostdata;        /* available to low-level driver */
        char type;
        char scsi_level;
        char inq_periph_qual;    /* PQ from INQUIRY data */    
        unsigned char inquiry_len;    /* valid bytes in 'inquiry' */
        unsigned char * inquiry;    /* INQUIRY response data */
        const char * vendor;        /* [back_compat] point into 'inquiry' ... */
        const char * model;        /* ... after scan; point to static string */
        const char * rev;        /* ... "nullnullnullnull" before scan */
        unsigned char current_tag;    /* current tag */
        struct scsi_target      *sdev_target;   /* used only for single_lun */

        unsigned int    sdev_bflags; /* black/white flags as also found in
                     * scsi_devinfo.[hc]. For now used only to
                     * pass settings from slave_alloc to scsi
                     * core. */
        unsigned writeable:1;
        unsigned removable:1;
        unsigned changed:1;    /* Data invalid due to media change */
        unsigned busy:1;    /* Used to prevent races */
        unsigned lockable:1;    /* Able to prevent media removal */
        unsigned locked:1;      /* Media removal disabled */
        unsigned borken:1;    /* Tell the Seagate driver to be
                     * painfully slow on this device */
        unsigned disconnect:1;    /* can disconnect */
        unsigned soft_reset:1;    /* Uses soft reset option */
        unsigned sdtr:1;    /* Device supports SDTR messages */
        unsigned wdtr:1;    /* Device supports WDTR messages */
        unsigned ppr:1;        /* Device supports PPR messages */
        unsigned tagged_supported:1;    /* Supports SCSI-II tagged queuing */
        unsigned simple_tags:1;    /* simple queue tag messages are enabled */
        unsigned ordered_tags:1;/* ordered queue tag messages are enabled */
        unsigned single_lun:1;    /* Indicates we should only allow I/O to
                     * one of the luns for the device at a
                     * time. */
        unsigned was_reset:1;    /* There was a bus reset on the bus for
                     * this device */
        unsigned expecting_cc_ua:1; /* Expecting a CHECK_CONDITION/UNIT_ATTN
                         * because we did a bus reset. */
        unsigned use_10_for_rw:1; /* first try 10-byte read / write */
        unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */
        unsigned skip_ms_page_8:1;    /* do not use MODE SENSE page 0x08 */
        unsigned skip_ms_page_3f:1;    /* do not use MODE SENSE page 0x3f */
        unsigned use_192_bytes_for_3f:1; /* ask for 192 bytes from page 0x3f */
        unsigned no_start_on_add:1;    /* do not issue start on add */
        unsigned allow_restart:1; /* issue START_UNIT in error handler */
        unsigned manage_start_stop:1;    /* Let HLD (sd) manage start/stop */
        unsigned no_uld_attach:1; /* disable connecting to upper level drivers */
        unsigned select_no_atn:1;
        unsigned fix_capacity:1;    /* READ_CAPACITY is too high by 1 */
        unsigned guess_capacity:1;    /* READ_CAPACITY might be too high by 1 */
        unsigned retry_hwerror:1;    /* Retry HARDWARE_ERROR */

        unsigned int device_blocked;    /* Device returned QUEUE_FULL. */

        unsigned int max_device_blocked; /* what device_blocked counts down from  */
    #define SCSI_DEFAULT_DEVICE_BLOCKED    3

        atomic_t iorequest_cnt;
        atomic_t iodone_cnt;
        atomic_t ioerr_cnt;

        int timeout;

        struct device        sdev_gendev;
        struct class_device    sdev_classdev;

        struct execute_work    ew; /* used to get process context on put */

        enum scsi_device_state sdev_state;
        unsigned long        sdev_data[0];
    } __attribute__((aligned(sizeof(unsigned long))));
    #define    to_scsi_device(d)    
        container_of(d, struct scsi_device, sdev_gendev)
    #define    class_to_sdev(d)    
        container_of(d, struct scsi_device, sdev_classdev)
    #define transport_class_to_sdev(class_dev)
        to_scsi_device(class_dev->dev)

    #define sdev_printk(prefix, sdev, fmt, a...)    
        dev_printk(prefix, &(sdev)->sdev_gendev, fmt, ##a)

    #define scmd_printk(prefix, scmd, fmt, a...)                
            (scmd)->request->rq_disk ?                    
        sdev_printk(prefix, (scmd)->device, "[%s] " fmt,        
                (scmd)->request->rq_disk->disk_name, ##a) :        
        sdev_printk(prefix, (scmd)->device, fmt, ##a)

    enum scsi_target_state {
        STARGET_RUNNING = 1,
        STARGET_DEL,
    };

    /*
     * scsi_target: representation of a scsi target, for now, this is only
     * used for single_lun devices. If no one has active IO to the target,
     * starget_sdev_user is NULL, else it points to the active sdev.
     */
    struct scsi_target {
        struct scsi_device    *starget_sdev_user;
        struct list_head    siblings;
        struct list_head    devices;
        struct device        dev;
        unsigned int        reap_ref; /* protected by the host lock */
        unsigned int        channel;
        unsigned int        id; /* target id ... replace
                         * scsi_device.id eventually */
        unsigned int        create:1; /* signal that it needs to be added */
        unsigned int        pdt_1f_for_no_lun;    /* PDT = 0x1f */
                            /* means no lun present */

        char            scsi_level;
        struct execute_work    ew;
        enum scsi_target_state    state;
        void             *hostdata; /* available to low-level driver */
        unsigned long        starget_data[0]; /* for the transport */
        /* starget_data must be the last element!!!! */
    } __attribute__((aligned(sizeof(unsigned long))));



    struct scatterlist {
        struct page        *page;
        unsigned int    offset;
        dma_addr_t        dma_address;
        unsigned int    length;
    };



    /* command block wrapper */
    struct bulk_cb_wrap {
        __le32    Signature;        /* contains 'USBC' */
        __u32    Tag;            /* unique per command id */
        __le32    DataTransferLength;    /* size of data */
        __u8    Flags;            /* direction in bit 0 */
        __u8    Lun;            /* LUN normally 0 */
        __u8    Length;            /* of of the CDB */
        __u8    CDB[16];        /* max command */
    };

    #define US_BULK_CB_WRAP_LEN    31
    #define US_BULK_CB_SIGN        0x43425355    /*spells out USBC */
    #define US_BULK_FLAG_IN        1
    #define US_BULK_FLAG_OUT    0

    /* command status wrapper */
    struct bulk_cs_wrap {
        __le32    Signature;        /* should = 'USBS' */
        __u32    Tag;            /* same as original command */
        __le32    Residue;        /* amount not transferred */
        __u8    Status;            /* see below */
        __u8    Filler[18];
    };



    struct us_unusual_dev {
        const char* vendorName;
        const char* productName;
        __u8  useProtocol;
        __u8  useTransport;
        int (*initFunction)(struct us_data *);
    };


    /* Dynamic flag definitions: used in set_bit() etc. */
    #define US_FLIDX_URB_ACTIVE    18  /* 0x00040000  current_urb is in use  */
    #define US_FLIDX_SG_ACTIVE    19  /* 0x00080000  current_sg is in use   */
    #define US_FLIDX_ABORTING    20  /* 0x00100000  abort is in progress   */
    #define US_FLIDX_DISCONNECTING    21  /* 0x00200000  disconnect in progress */
    #define ABORTING_OR_DISCONNECTING    ((1UL << US_FLIDX_ABORTING) |
                         (1UL << US_FLIDX_DISCONNECTING))
    #define US_FLIDX_RESETTING    22  /* 0x00400000  device reset in progress */
    #define US_FLIDX_TIMED_OUT    23  /* 0x00800000  SCSI midlayer timed out  */


    #define USB_STOR_STRING_LEN 32

    /*
     * We provide a DMA-mapped I/O buffer for use with small USB transfers.
     * It turns out that CB[I] needs a 12-byte buffer and Bulk-only needs a
     * 31-byte buffer.  But Freecom needs a 64-byte buffer, so that's the
     * size we'll allocate.
     */

    #define US_IOBUF_SIZE        64    /* Size of the DMA-mapped I/O buffer */
    #define US_SENSE_SIZE        18    /* Size of the autosense data buffer */

    typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*);
    typedef int (*trans_reset)(struct us_data*);
    typedef void (*proto_cmnd)(struct scsi_cmnd*, struct us_data*);
    typedef void (*extra_data_destructor)(void *);    /* extra data destructor */
    typedef void (*pm_hook)(struct us_data *, int);    /* power management hook */

    #define US_SUSPEND    0
    #define US_RESUME    1

    /* we allocate one of these for every device that we remember */
    struct us_data {
        /* The device we're working with
         * It's important to note:
         *    (o) you must hold dev_mutex to change pusb_dev
         */
        struct mutex        dev_mutex;     /* protect pusb_dev */
        struct usb_device    *pusb_dev;     /* this usb_device */
        struct usb_interface    *pusb_intf;     /* this interface */
        struct us_unusual_dev   *unusual_dev;     /* device-filter entry     */
        unsigned long        flags;         /* from filter initially */
        unsigned int        send_bulk_pipe;     /* cached pipe values */
        unsigned int        recv_bulk_pipe;
        unsigned int        send_ctrl_pipe;
        unsigned int        recv_ctrl_pipe;
        unsigned int        recv_intr_pipe;

        /* information about the device */
        char            *transport_name;
        char            *protocol_name;
        __le32            bcs_signature;
        u8            subclass;
        u8            protocol;
        u8            max_lun;

        u8            ifnum;         /* interface number   */
        u8            ep_bInterval;     /* interrupt interval */

        /* function pointers for this device */
        trans_cmnd        transport;     /* transport function       */
        trans_reset        transport_reset; /* transport device reset */
        proto_cmnd        proto_handler;     /* protocol handler       */

        /* SCSI interfaces */
        struct scsi_cmnd    *srb;         /* current srb        */
        unsigned int        tag;         /* current dCBWTag    */

        /* control and bulk communications data */
        struct urb        *current_urb;     /* USB requests     */
        struct usb_ctrlrequest    *cr;         /* control requests     */
        struct usb_sg_request    current_sg;     /* scatter-gather req.  */
        unsigned char        *iobuf;         /* I/O buffer         */
        unsigned char        *sensebuf;     /* sense data buffer     */
        dma_addr_t        cr_dma;         /* buffer DMA addresses */
        dma_addr_t        iobuf_dma;

        /* mutual exclusion and synchronization structures */
        struct semaphore    sema;         /* to sleep thread on        */
        struct completion    notify;         /* thread begin/end        */
        wait_queue_head_t    delay_wait;     /* wait during scan, reset */

        /* subdriver information */
        void            *extra;         /* Any extra data          */
        extra_data_destructor    extra_destructor;/* extra data destructor   */
    #ifdef CONFIG_PM
        pm_hook            suspend_resume_hook;
    #endif
    };




    struct scsi_host_template usb_stor_host_template = {
        /* basic userland interface stuff */
        .name =                "usb-storage",
        .proc_name =            "usb-storage",
        .proc_info =            proc_info,
        .info =                host_info,

        /* command interface -- queued only */
        .queuecommand =            queuecommand,

        /* error and abort handlers */
        .eh_abort_handler =        command_abort,
        .eh_device_reset_handler =    device_reset,
        .eh_bus_reset_handler =        bus_reset,

        /* queue commands only, only one command per LUN */
        .can_queue =            1,
        .cmd_per_lun =            1,

        /* unknown initiator id */
        .this_id =            -1,

        .slave_alloc =            slave_alloc,
        .slave_configure =        slave_configure,

        /* lots of sg segments can be handled */
        .sg_tablesize =            SG_ALL,

        /* limit the total size of a transfer to 120 KB */
        .max_sectors =                  240,

        /* merge commands... this seems to help performance, but
         * periodically someone should test to see which setting is more
         * optimal.
         */
        .use_clustering =        1,

        /* emulated HBA */
        .emulated =            1,

        /* we do our own delay after a device or bus reset */
        .skip_settle_delay =        1,

        /* sysfs device attributes */
        .sdev_attrs =            sysfs_device_attr_list,

        /* module management */
        .module =            THIS_MODULE
    };

    /* To Report "Illegal Request: Invalid Field in CDB */
    unsigned char usb_stor_sense_invalidCDB[18] = {
        [0]    = 0x70,                /* current error */
        [2]    = ILLEGAL_REQUEST,        /* Illegal Request = 0x05 */
        [7]    = 0x0a,                /* additional length */
        [12]    = 0x24                /* Invalid Field in CDB */
    };

  • 相关阅读:
    微服务架构技术栈选型手册(万字长文)
    Visual Studio 2013 always switches source control plugin to Git and disconnect TFS
    Visual Studio 2013 always switches source control plugin to Git and disconnect TFS
    MFC对话框中使用CHtmlEditCtrl
    ATL开发 ActiveX控件的 inf文件模板
    ActiveX: 如何用.inf和.ocx文件生成cab文件
    Xslt 1.0中使用Array
    如何分隔两个base64字符串?
    An attempt was made to load a program with an incorrect format
    JQuery 公网 CDN
  • 原文地址:https://www.cnblogs.com/wanghuaijun/p/7189688.html
Copyright © 2011-2022 走看看