1 /* 2 * Contains commonly used types and procedures, for HCD handling/initialization 3 * If possible, everything OS specific (IPC, virtual memory...) should be here 4 */ 5 6 #ifndef _HCD_COMMON_H_ 7 #define _HCD_COMMON_H_ 8 9 #include <ddekit/thread.h> 10 #include <ddekit/semaphore.h> 11 #include <ddekit/usb.h> 12 13 /* TODO: usb.h is for DDEKit's IPC and should not be used here */ 14 #include <minix/usb.h> /* for setup structures */ 15 #include <minix/usb_ch9.h> /* for descriptor structures */ 16 17 #include <sys/cdefs.h> /* for __aligned() */ 18 19 20 /*===========================================================================* 21 * USB register handling defines * 22 *===========================================================================*/ 23 /* Helper type used for register bitwise access */ 24 #define HCD_BIT(num) (0x01u << (num)) 25 26 /* Unsigned type that can hold all possible addresses */ 27 typedef unsigned long hcd_addr; 28 29 /* Register types */ 30 typedef unsigned long hcd_reg4; 31 typedef unsigned short hcd_reg2; 32 typedef unsigned char hcd_reg1; 33 34 /* For register dereferencing */ 35 #define _HCD_REG4 volatile hcd_reg4 * 36 #define _HCD_REG2 volatile hcd_reg2 * 37 #define _HCD_REG1 volatile hcd_reg1 * 38 39 /* Scalar address to dereference */ 40 #define _HCD_ADDR(base, off) (((hcd_addr)(base))+(off)) 41 42 /* Defines for fixed size register access 43 * May cause unaligned memory access */ 44 #define HCD_WR4(base, off, val) (*((_HCD_REG4)_HCD_ADDR(base, off)) = (val)) 45 #define HCD_WR2(base, off, val) (*((_HCD_REG2)_HCD_ADDR(base, off)) = (val)) 46 #define HCD_WR1(base, off, val) (*((_HCD_REG1)_HCD_ADDR(base, off)) = (val)) 47 #define HCD_RD4(base, off) (*((_HCD_REG4)_HCD_ADDR(base, off))) 48 #define HCD_RD2(base, off) (*((_HCD_REG2)_HCD_ADDR(base, off))) 49 #define HCD_RD1(base, off) (*((_HCD_REG1)_HCD_ADDR(base, off))) 50 51 /* Other useful defines */ 52 #define HCD_SET(val, bits) ((val)|=(bits)) 53 #define HCD_CLR(val, bits) ((val)&=~(bits)) 54 55 /* Alignment safe conversion from 'bytes' array to a word */ 56 #define HCD_8TO32(bytes) (((bytes)[0]) | \ 57 (((bytes)[1])<<8) | \ 58 (((bytes)[2])<<16) | \ 59 (((bytes)[3])<<24)) 60 61 /* Convert type's 'sizeof' to 4-byte words count */ 62 #define HCD_SIZEOF_TO_4(type) ((sizeof(type)+3)/4) 63 64 65 /*===========================================================================* 66 * USB descriptor types * 67 *===========================================================================*/ 68 typedef usb_descriptor_t hcd_descriptor; 69 typedef usb_device_descriptor_t hcd_device_descriptor; 70 typedef usb_config_descriptor_t hcd_config_descriptor; 71 typedef usb_interface_descriptor_t hcd_interface_descriptor; 72 typedef usb_endpoint_descriptor_t hcd_endpoint_descriptor; 73 typedef usb_string_descriptor_t hcd_string_descriptor; 74 75 76 /*===========================================================================* 77 * HCD descriptor tree types * 78 *===========================================================================*/ 79 typedef struct hcd_endpoint { 80 81 hcd_endpoint_descriptor descriptor; 82 } 83 hcd_endpoint; 84 85 typedef struct hcd_interface { 86 87 hcd_interface_descriptor descriptor; 88 hcd_endpoint * endpoint; 89 int num_endpoints; 90 } 91 hcd_interface; 92 93 typedef struct hcd_configuration { 94 95 hcd_config_descriptor descriptor; 96 hcd_interface * interface; 97 int num_interfaces; 98 } 99 hcd_configuration; 100 101 102 /*===========================================================================* 103 * HCD enumerations * 104 *===========================================================================*/ 105 /* Possible USB transfer types */ 106 typedef enum { 107 108 HCD_TRANSFER_CONTROL = UE_CONTROL, 109 HCD_TRANSFER_ISOCHRONOUS = UE_ISOCHRONOUS, 110 HCD_TRANSFER_BULK = UE_BULK, 111 HCD_TRANSFER_INTERRUPT = UE_INTERRUPT 112 } 113 hcd_transfer; 114 115 /* Possible USB transfer directions */ 116 typedef enum { 117 118 HCD_DIRECTION_OUT = 0, 119 HCD_DIRECTION_IN = 1, 120 HCD_DIRECTION_UNUSED = 0xFF 121 } 122 hcd_direction; 123 124 /* Possible asynchronous HCD events */ 125 typedef enum { 126 127 HCD_EVENT_CONNECTED = 0, /* Device connected directly to root */ 128 HCD_EVENT_DISCONNECTED, /* Directly connected device removed */ 129 HCD_EVENT_PORT_LS_CONNECTED, /* Low speed device connected to hub */ 130 HCD_EVENT_PORT_FS_CONNECTED, /* Full speed device connected to hub */ 131 HCD_EVENT_PORT_HS_CONNECTED, /* High speed device connected to hub */ 132 HCD_EVENT_PORT_DISCONNECTED, /* Device disconnected from hub */ 133 HCD_EVENT_ENDPOINT, /* Something happened at endpoint */ 134 HCD_EVENT_URB, /* URB was submitted by device driver */ 135 HCD_EVENT_INVALID = 0xFF 136 } 137 hcd_event; 138 139 /* Possible device states */ 140 typedef enum { 141 142 HCD_STATE_DISCONNECTED = 0, /* default for initialization */ 143 HCD_STATE_CONNECTION_PENDING, 144 HCD_STATE_CONNECTED 145 } 146 hcd_state; 147 148 /* USB speeds */ 149 typedef enum { 150 151 HCD_SPEED_LOW, 152 HCD_SPEED_FULL, 153 HCD_SPEED_HIGH, 154 } 155 hcd_speed; 156 157 /* Possible data toggle values (at least for bulk transfer) */ 158 typedef enum { 159 160 HCD_DATATOG_DATA0 = 0, 161 HCD_DATATOG_DATA1 = 1 162 } 163 hcd_datatog; 164 165 166 /*===========================================================================* 167 * HCD threading/device/URB types * 168 *===========================================================================*/ 169 typedef void (*hcd_thread_function)(void *); 170 typedef ddekit_thread_t hcd_thread; 171 typedef ddekit_sem_t hcd_lock; 172 typedef struct hcd_driver_state hcd_driver_state; 173 typedef struct usb_ctrlrequest hcd_ctrlrequest; 174 175 /* Largest value that can be transfered by this driver at a time 176 * see MAXPAYLOAD in TXMAXP/RXMAXP */ 177 #define MAX_WTOTALLENGTH 1024u 178 179 /* TODO: This has corresponding redefinition in hub driver */ 180 /* Limit of child devices for each parent */ 181 #define HCD_CHILDREN 8u 182 183 /* Total number of endpoints available in USB 2.0 */ 184 #define HCD_TOTAL_EP 16u 185 186 /* Forward declarations */ 187 typedef struct hcd_datarequest hcd_datarequest; 188 typedef struct hcd_urb hcd_urb; 189 typedef struct hcd_device_state hcd_device_state; 190 191 /* Non-control transfer request structure */ 192 struct hcd_datarequest { 193 194 hcd_reg1 * data; /* RX/TX buffer */ 195 int data_left; /* Amount of data to transfer (may 196 * become negative in case of error 197 * thus 'int') */ 198 hcd_reg2 max_packet_size; /* Read from EP descriptor */ 199 hcd_reg1 endpoint; /* EP number */ 200 hcd_reg1 interval; /* Should match one in EP descriptor */ 201 hcd_direction direction; /* Should match one in EP descriptor */ 202 hcd_speed speed; /* Decided during device reset */ 203 hcd_transfer type; /* Should match one in EP descriptor */ 204 }; 205 206 /* HCD's URB structure */ 207 struct hcd_urb { 208 209 /* Basic */ 210 void * original_urb; 211 hcd_device_state * target_device; 212 void (*handled)(hcd_urb *); /* URB handled callback */ 213 214 /* Transfer (in/out signifies what may be overwritten by HCD) */ 215 hcd_ctrlrequest * in_setup; 216 hcd_reg1 * inout_data; 217 hcd_reg4 in_size; 218 hcd_reg4 out_size; 219 int inout_status; /* URB submission/validity status */ 220 221 /* Transfer control */ 222 hcd_transfer type; 223 hcd_direction direction; 224 hcd_reg1 endpoint; 225 hcd_reg1 interval; 226 }; 227 228 /* Current state of attached device */ 229 struct hcd_device_state { 230 231 hcd_device_state * parent; /* In case of hub attachment */ 232 hcd_device_state * child[HCD_CHILDREN]; /* In case of being hub */ 233 hcd_device_state * _next; /* To allow device lists */ 234 hcd_driver_state * driver; /* Specific HCD driver object */ 235 hcd_thread * thread; 236 hcd_lock * lock; 237 void * data; 238 239 hcd_urb * urb; /* URB to be used by device */ 240 hcd_event wait_event; /* Expected event */ 241 hcd_reg1 wait_ep; /* Expected event's endpoint */ 242 hcd_device_descriptor device_desc; 243 hcd_configuration config_tree; 244 hcd_reg1 max_packet_size; 245 hcd_speed speed; 246 hcd_state state; 247 hcd_reg1 reserved_address; 248 hcd_reg1 current_address; 249 hcd_datatog ep_tx_tog[HCD_TOTAL_EP]; 250 hcd_datatog ep_rx_tog[HCD_TOTAL_EP]; 251 252 /* 253 * Control transfer's local data: 254 */ 255 256 /* Number of bytes received/transmitted in last control transfer (may 257 * become negative in case of error thus 'int') */ 258 int control_len; 259 260 /* Word aligned buffer for each device to hold transfered data */ 261 hcd_reg1 control_data[MAX_WTOTALLENGTH] __aligned(sizeof(hcd_reg4)); 262 }; 263 264 265 /*===========================================================================* 266 * Other definitions * 267 *===========================================================================*/ 268 #define HCD_MILI 1000 269 #define HCD_MICRO 1000000 270 #define HCD_NANO 1000000000 271 #define HCD_NANOSLEEP_SEC(sec) ((sec) * HCD_NANO) 272 #define HCD_NANOSLEEP_MSEC(msec) ((msec) * HCD_MICRO) 273 #define HCD_NANOSLEEP_USEC(usec) ((usec) * HCD_MILI) 274 275 /* Default USB communication parameters */ 276 #define HCD_DEFAULT_EP 0x00u 277 #define HCD_DEFAULT_ADDR 0x00u 278 #define HCD_DEFAULT_CONFIG 0x00u 279 #define HCD_FIRST_ADDR 0x01u 280 #define HCD_LAST_ADDR 0x7Fu 281 #define HCD_TOTAL_ADDR 0x80u 282 #define HCD_LAST_EP 0x0Fu 283 #define HCD_UNUSED_VAL 0xFFu /* When number not needed */ 284 #define HCD_DEFAULT_NAKLIMIT 0x10u 285 286 287 /* Legal interval values */ 288 #define HCD_LOWEST_INTERVAL 0x00u 289 #define HCD_HIGHEST_INTERVAL 0xFFu 290 291 /* Translates configuration number for 'set configuration' */ 292 #define HCD_SET_CONFIG_NUM(num) ((num)+0x01u) 293 294 /* Default MaxPacketSize for control transfer */ 295 #define HCD_LS_MAXPACKETSIZE 8u /* Low-speed, Full-speed */ 296 #define HCD_HS_MAXPACKETSIZE 64u /* High-speed */ 297 #define HCD_MAX_MAXPACKETSIZE 1024u 298 299 300 /*===========================================================================* 301 * Operating system specific * 302 *===========================================================================*/ 303 /* Generic method for registering interrupts */ 304 int hcd_os_interrupt_attach(int irq, void (*init)(void *), 305 void (*isr)(void *), void *priv); 306 307 /* Generic method for unregistering interrupts */ 308 void hcd_os_interrupt_detach(int); 309 310 /* Generic method for enabling interrupts */ 311 void hcd_os_interrupt_enable(int); 312 313 /* Generic method for disabling interrupts */ 314 void hcd_os_interrupt_disable(int); 315 316 /* Returns pointer to memory mapped for given arguments */ 317 void * hcd_os_regs_init(hcd_addr, unsigned long); 318 319 /* Unregisters mapped memory */ 320 int hcd_os_regs_deinit(hcd_addr, unsigned long); 321 322 /* Configure clocking */ 323 int hcd_os_clkconf(unsigned long, unsigned long, unsigned long); 324 325 /* Release clocking */ 326 int hcd_os_clkconf_release(void); 327 328 /* OS's sleep wrapper */ 329 void hcd_os_nanosleep(int); 330 331 332 /*===========================================================================* 333 * Device handling calls * 334 *===========================================================================*/ 335 /* Initializes device threading on connection */ 336 int hcd_connect_device(hcd_device_state *, hcd_thread_function); 337 338 /* Cleans after device disconnection */ 339 void hcd_disconnect_device(hcd_device_state *); 340 341 /* Locks device thread until 'hcd_device_continue' */ 342 void hcd_device_wait(hcd_device_state *, hcd_event, hcd_reg1); 343 344 /* Unlocks device thread halted by 'hcd_device_wait' */ 345 void hcd_device_continue(hcd_device_state *, hcd_event, hcd_reg1); 346 347 /* Allocation/deallocation of device structures */ 348 hcd_device_state * hcd_new_device(void); 349 void hcd_delete_device(hcd_device_state *); 350 void hcd_dump_devices(void); 351 int hcd_check_device(hcd_device_state *); 352 353 354 /*===========================================================================* 355 * Descriptor tree calls * 356 *===========================================================================*/ 357 /* Creates descriptor tree based on given buffer */ 358 int hcd_buffer_to_tree(hcd_reg1 *, int, hcd_configuration *); 359 360 /* Frees descriptor tree */ 361 void hcd_tree_cleanup(hcd_configuration *); 362 363 /* Find EP in a tree */ 364 hcd_endpoint * hcd_tree_find_ep(hcd_configuration *, hcd_reg1); 365 366 367 #endif /* !_HCD_COMMON_H_ */ 368