iPXE
usbhub.h
Go to the documentation of this file.
00001 #ifndef _USBHUB_H
00002 #define _USBHUB_H
00003 
00004 /** @file
00005  *
00006  * USB hubs
00007  *
00008  */
00009 
00010 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00011 
00012 #include <ipxe/usb.h>
00013 #include <ipxe/list.h>
00014 #include <ipxe/process.h>
00015 
00016 /** Request recipient is a port */
00017 #define USB_HUB_RECIP_PORT ( 3 << 0 )
00018 
00019 /** A basic USB hub descriptor */
00020 struct usb_hub_descriptor_basic {
00021         /** Descriptor header */
00022         struct usb_descriptor_header header;
00023         /** Number of ports */
00024         uint8_t ports;
00025         /** Characteristics */
00026         uint16_t characteristics;
00027         /** Power-on delay (in 2ms intervals */
00028         uint8_t delay;
00029         /** Controller current (in mA) */
00030         uint8_t current;
00031 } __attribute__ (( packed ));
00032 
00033 /** A basic USB hub descriptor */
00034 #define USB_HUB_DESCRIPTOR 41
00035 
00036 /** An enhanced USB hub descriptor */
00037 struct usb_hub_descriptor_enhanced {
00038         /** Basic USB hub descriptor */
00039         struct usb_hub_descriptor_basic basic;
00040         /** Header decode latency */
00041         uint8_t latency;
00042         /** Maximum delay */
00043         uint16_t delay;
00044         /** Removable device bitmask */
00045         uint16_t removable;
00046 } __attribute__ (( packed ));
00047 
00048 /** An enhanced USB hub descriptor */
00049 #define USB_HUB_DESCRIPTOR_ENHANCED 42
00050 
00051 /** A USB hub descriptor */
00052 union usb_hub_descriptor {
00053         /** Descriptor header */
00054         struct usb_descriptor_header header;
00055         /** Basic hub descriptor */
00056         struct usb_hub_descriptor_basic basic;
00057         /** Enhanced hub descriptor */
00058         struct usb_hub_descriptor_enhanced enhanced;
00059 } __attribute__ (( packed ));
00060 
00061 /** Port status */
00062 struct usb_hub_port_status {
00063         /** Current status */
00064         uint16_t current;
00065         /** Changed status */
00066         uint16_t changed;
00067 } __attribute__ (( packed ));
00068 
00069 /** Current connect status feature */
00070 #define USB_HUB_PORT_CONNECTION 0
00071 
00072 /** Port enabled/disabled feature */
00073 #define USB_HUB_PORT_ENABLE 1
00074 
00075 /** Port reset feature */
00076 #define USB_HUB_PORT_RESET 4
00077 
00078 /** Port power feature */
00079 #define USB_HUB_PORT_POWER 8
00080 
00081 /** Low-speed device attached */
00082 #define USB_HUB_PORT_LOW_SPEED 9
00083 
00084 /** High-speed device attached */
00085 #define USB_HUB_PORT_HIGH_SPEED 10
00086 
00087 /** Connect status changed */
00088 #define USB_HUB_C_PORT_CONNECTION 16
00089 
00090 /** Port enable/disable changed */
00091 #define USB_HUB_C_PORT_ENABLE 17
00092 
00093 /** Suspend changed */
00094 #define USB_HUB_C_PORT_SUSPEND 18
00095 
00096 /** Over-current indicator changed */
00097 #define USB_HUB_C_PORT_OVER_CURRENT 19
00098 
00099 /** Reset changed */
00100 #define USB_HUB_C_PORT_RESET 20
00101 
00102 /** Link state changed */
00103 #define USB_HUB_C_PORT_LINK_STATE 25
00104 
00105 /** Configuration error */
00106 #define USB_HUB_C_PORT_CONFIG_ERROR 26
00107 
00108 /** Calculate feature from change bit number */
00109 #define USB_HUB_C_FEATURE( bit ) ( 16 + (bit) )
00110 
00111 /** USB features */
00112 #define USB_HUB_FEATURES                                                \
00113         ( ( 1 << USB_HUB_C_PORT_CONNECTION ) |                          \
00114           ( 1 << USB_HUB_C_PORT_ENABLE ) |                              \
00115           ( 1 << USB_HUB_C_PORT_SUSPEND ) |                             \
00116           ( 1 << USB_HUB_C_PORT_OVER_CURRENT ) |                        \
00117           ( 1 << USB_HUB_C_PORT_RESET ) )
00118 
00119 /** USB features for enhanced hubs */
00120 #define USB_HUB_FEATURES_ENHANCED                                       \
00121         ( ( 1 << USB_HUB_C_PORT_CONNECTION ) |                          \
00122           ( 1 << USB_HUB_C_PORT_OVER_CURRENT ) |                        \
00123           ( 1 << USB_HUB_C_PORT_RESET ) |                               \
00124           ( 1 << USB_HUB_C_PORT_LINK_STATE ) |                          \
00125           ( 1 << USB_HUB_C_PORT_CONFIG_ERROR ) )
00126 
00127 /** Set hub depth */
00128 #define USB_HUB_SET_HUB_DEPTH                                           \
00129         ( USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_DEVICE |             \
00130           USB_REQUEST_TYPE ( 12 ) )
00131 
00132 /** Clear transaction translator buffer */
00133 #define USB_HUB_CLEAR_TT_BUFFER                                         \
00134         ( USB_DIR_OUT | USB_TYPE_CLASS | USB_HUB_RECIP_PORT |           \
00135           USB_REQUEST_TYPE ( 8 ) )
00136 
00137 /**
00138  * Get hub descriptor
00139  *
00140  * @v usb               USB device
00141  * @v enhanced          Hub is an enhanced hub
00142  * @v data              Hub descriptor to fill in
00143  * @ret rc              Return status code
00144  */
00145 static inline __attribute__ (( always_inline )) int
00146 usb_hub_get_descriptor ( struct usb_device *usb, int enhanced,
00147                          union usb_hub_descriptor *data ) {
00148         unsigned int desc;
00149         size_t len;
00150 
00151         /* Determine descriptor type and length */
00152         desc = ( enhanced ? USB_HUB_DESCRIPTOR_ENHANCED : USB_HUB_DESCRIPTOR );
00153         len = ( enhanced ? sizeof ( data->enhanced ) : sizeof ( data->basic ) );
00154 
00155         return usb_get_descriptor ( usb, USB_TYPE_CLASS, desc, 0, 0,
00156                                     &data->header, len );
00157 }
00158 
00159 /**
00160  * Get port status
00161  *
00162  * @v usb               USB device
00163  * @v port              Port address
00164  * @v status            Port status descriptor to fill in
00165  * @ret rc              Return status code
00166  */
00167 static inline __attribute__ (( always_inline )) int
00168 usb_hub_get_port_status ( struct usb_device *usb, unsigned int port,
00169                           struct usb_hub_port_status *status ) {
00170 
00171         return usb_get_status ( usb, ( USB_TYPE_CLASS | USB_HUB_RECIP_PORT ),
00172                                 port, status, sizeof ( *status ) );
00173 }
00174 
00175 /**
00176  * Clear port feature
00177  *
00178  * @v usb               USB device
00179  * @v port              Port address
00180  * @v feature           Feature to clear
00181  * @v index             Index (when clearing a port indicator)
00182  * @ret rc              Return status code
00183  */
00184 static inline __attribute__ (( always_inline )) int
00185 usb_hub_clear_port_feature ( struct usb_device *usb, unsigned int port,
00186                              unsigned int feature, unsigned int index ) {
00187 
00188         return usb_clear_feature ( usb, ( USB_TYPE_CLASS | USB_HUB_RECIP_PORT ),
00189                                    feature, ( ( index << 8 ) | port ) );
00190 }
00191 
00192 /**
00193  * Set port feature
00194  *
00195  * @v usb               USB device
00196  * @v port              Port address
00197  * @v feature           Feature to clear
00198  * @v index             Index (when clearing a port indicator)
00199  * @ret rc              Return status code
00200  */
00201 static inline __attribute__ (( always_inline )) int
00202 usb_hub_set_port_feature ( struct usb_device *usb, unsigned int port,
00203                            unsigned int feature, unsigned int index ) {
00204 
00205         return usb_set_feature ( usb, ( USB_TYPE_CLASS | USB_HUB_RECIP_PORT ),
00206                                  feature, ( ( index << 8 ) | port ) );
00207 }
00208 
00209 /**
00210  * Set hub depth
00211  *
00212  * @v usb               USB device
00213  * @v depth             Hub depth
00214  * @ret rc              Return status code
00215  */
00216 static inline __attribute__ (( always_inline )) int
00217 usb_hub_set_hub_depth ( struct usb_device *usb, unsigned int depth ) {
00218 
00219         return usb_control ( usb, USB_HUB_SET_HUB_DEPTH, depth, 0, NULL, 0 );
00220 }
00221 
00222 /**
00223  * Clear transaction translator buffer
00224  *
00225  * @v usb               USB device
00226  * @v device            Device address
00227  * @v endpoint          Endpoint address
00228  * @v attributes        Endpoint attributes
00229  * @v tt_port           Transaction translator port (or 1 for single-TT hubs)
00230  * @ret rc              Return status code
00231  */
00232 static inline __attribute__ (( always_inline )) int
00233 usb_hub_clear_tt_buffer ( struct usb_device *usb, unsigned int device,
00234                           unsigned int endpoint, unsigned int attributes,
00235                           unsigned int tt_port ) {
00236         unsigned int value;
00237 
00238         /* Calculate value */
00239         value = ( ( ( endpoint & USB_ENDPOINT_MAX ) << 0 ) | ( device << 4 ) |
00240                   ( ( attributes & USB_ENDPOINT_ATTR_TYPE_MASK ) << 11 ) |
00241                   ( ( endpoint & USB_ENDPOINT_IN ) << 8 ) );
00242 
00243         return usb_control ( usb, USB_HUB_CLEAR_TT_BUFFER, value,
00244                              tt_port, NULL, 0 );
00245 }
00246 
00247 /** Transaction translator port value for single-TT hubs */
00248 #define USB_HUB_TT_SINGLE 1
00249 
00250 /** A USB hub device */
00251 struct usb_hub_device {
00252         /** Name */
00253         const char *name;
00254         /** USB device */
00255         struct usb_device *usb;
00256         /** USB hub */
00257         struct usb_hub *hub;
00258         /** Features */
00259         unsigned int features;
00260         /** Flags */
00261         unsigned int flags;
00262 
00263         /** Interrupt endpoint */
00264         struct usb_endpoint intr;
00265         /** Interrupt endpoint refill process */
00266         struct process refill;
00267 };
00268 
00269 /** Hub requires additional settling delay */
00270 #define USB_HUB_SLOW_START 0x0001
00271 
00272 /** Additional setting delay for out-of-spec hubs */
00273 #define USB_HUB_SLOW_START_DELAY_MS 500
00274 
00275 /** Interrupt ring fill level
00276  *
00277  * This is a policy decision.
00278  */
00279 #define USB_HUB_INTR_FILL 4
00280 
00281 /** Maximum time to wait for port to become enabled
00282  *
00283  * This is a policy decision.
00284  */
00285 #define USB_HUB_ENABLE_MAX_WAIT_MS 100
00286 
00287 #endif /* _USBHUB_H */