Changeset 110d795 in mainline
- Timestamp:
- 2017-07-22T23:07:40Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- aee352c
- Parents:
- 9af3281
- Location:
- uspace/drv/bus/usb/xhci
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/xhci/commands.c
r9af3281 r110d795 44 44 #include "hw_struct/trb.h" 45 45 46 int xhci_init_commands(xhci_hc_t *hc) 47 { 48 assert(hc); 49 50 list_initialize(&hc->commands); 51 return EOK; 52 } 53 54 int xhci_wait_for_command(xhci_hc_t *hc, xhci_cmd_t *cmd, uint32_t timeout) 55 { 56 uint32_t time = 0; 57 while (!cmd->completed) { 58 async_usleep(1000); 59 time += 1000; 60 61 if (time > timeout) 62 return ETIMEOUT; 63 } 64 65 return EOK; 66 } 67 68 xhci_cmd_t *xhci_alloc_command(void) 69 { 70 xhci_cmd_t *cmd = malloc32(sizeof(xhci_cmd_t)); 71 memset(cmd, 0, sizeof(xhci_cmd_t)); 72 73 link_initialize(&cmd->link); 74 75 /** 76 * Internal functions will set this to false, other are implicit 77 * owners unless they overwrite this field. 78 * TODO: Is this wise? 79 */ 80 cmd->has_owner = true; 81 82 return cmd; 83 } 84 85 void xhci_free_command(xhci_cmd_t *cmd) 86 { 87 // TODO: If we decide to copy trb, free it here. 88 if (cmd->ictx) 89 free32(cmd->ictx); 90 91 free32(cmd); 92 } 93 94 static inline xhci_cmd_t *get_next_command(xhci_hc_t *hc) 95 { 96 link_t *cmd_link = list_first(&hc->commands); 97 98 if (cmd_link != NULL) { 99 list_remove(cmd_link); 100 101 return list_get_instance(cmd_link, xhci_cmd_t, link); 102 } 103 104 return NULL; 105 } 106 46 107 static inline int ring_doorbell(xhci_hc_t *hc, unsigned doorbell, unsigned target) 47 108 { … … 65 126 66 127 return EOK; 128 } 129 130 static inline xhci_cmd_t *add_cmd(xhci_hc_t *hc, xhci_cmd_t *cmd) 131 { 132 if (cmd == NULL) { 133 cmd = xhci_alloc_command(); 134 if (cmd == NULL) 135 return cmd; 136 137 cmd->has_owner = false; 138 } 139 140 list_append(&cmd->link, &hc->commands); 141 cmd->trb = hc->command_ring.enqueue_trb; 142 143 return cmd; 67 144 } 68 145 … … 118 195 } 119 196 120 int xhci_send_no_op_command(xhci_hc_t *hc )197 int xhci_send_no_op_command(xhci_hc_t *hc, xhci_cmd_t *cmd) 121 198 { 122 199 assert(hc); … … 127 204 trb.control = host2xhci(32, XHCI_TRB_TYPE_NO_OP_CMD << 10); 128 205 129 return enqueue_trb(hc, &trb, 0, 0); 130 } 131 132 int xhci_send_enable_slot_command(xhci_hc_t *hc) 206 cmd = add_cmd(hc, cmd); 207 208 return enqueue_trb(hc, &trb, 0, 0); 209 } 210 211 int xhci_send_enable_slot_command(xhci_hc_t *hc, xhci_cmd_t *cmd) 133 212 { 134 213 assert(hc); … … 141 220 trb.control |= host2xhci(32, hc->command_ring.pcs); 142 221 143 return enqueue_trb(hc, &trb, 0, 0); 144 } 145 146 int xhci_send_disable_slot_command(xhci_hc_t *hc, uint32_t slot_id) 147 { 148 assert(hc); 222 cmd = add_cmd(hc, cmd); 223 224 return enqueue_trb(hc, &trb, 0, 0); 225 } 226 227 int xhci_send_disable_slot_command(xhci_hc_t *hc, xhci_cmd_t *cmd) 228 { 229 assert(hc); 230 assert(cmd); 149 231 150 232 xhci_trb_t trb; … … 153 235 trb.control = host2xhci(32, XHCI_TRB_TYPE_DISABLE_SLOT_CMD << 10); 154 236 trb.control |= host2xhci(32, hc->command_ring.pcs); 155 trb.control |= host2xhci(32, slot_id << 24); 156 157 return enqueue_trb(hc, &trb, 0, 0); 158 } 159 160 int xhci_send_address_device_command(xhci_hc_t *hc, uint32_t slot_id, 161 xhci_input_ctx_t *ictx) 162 { 163 assert(hc); 164 assert(ictx); 237 trb.control |= host2xhci(32, cmd->slot_id << 24); 238 239 add_cmd(hc, cmd); 240 241 return enqueue_trb(hc, &trb, 0, 0); 242 } 243 244 int xhci_send_address_device_command(xhci_hc_t *hc, xhci_cmd_t *cmd) 245 { 246 assert(hc); 247 assert(cmd); 248 assert(cmd->ictx); 165 249 166 250 /** … … 173 257 memset(&trb, 0, sizeof(trb)); 174 258 175 uint64_t phys_addr = (uint64_t) addr_to_phys( ictx);259 uint64_t phys_addr = (uint64_t) addr_to_phys(cmd->ictx); 176 260 trb.parameter = host2xhci(32, phys_addr & (~0xF)); 177 261 … … 185 269 trb.control = host2xhci(32, XHCI_TRB_TYPE_ADDRESS_DEVICE_CMD << 10); 186 270 trb.control |= host2xhci(32, hc->command_ring.pcs); 187 trb.control |= host2xhci(32, slot_id << 24); 188 189 return enqueue_trb(hc, &trb, 0, 0); 190 } 191 192 int xhci_send_configure_endpoint_command(xhci_hc_t *hc, uint32_t slot_id, 193 xhci_input_ctx_t *ictx) 194 { 195 assert(hc); 196 assert(ictx); 197 198 xhci_trb_t trb; 199 memset(&trb, 0, sizeof(trb)); 200 201 uint64_t phys_addr = (uint64_t) addr_to_phys(ictx); 271 trb.control |= host2xhci(32, cmd->slot_id << 24); 272 273 cmd = add_cmd(hc, cmd); 274 275 return enqueue_trb(hc, &trb, 0, 0); 276 } 277 278 int xhci_send_configure_endpoint_command(xhci_hc_t *hc, xhci_cmd_t *cmd) 279 { 280 assert(hc); 281 assert(cmd); 282 assert(cmd->ictx); 283 284 xhci_trb_t trb; 285 memset(&trb, 0, sizeof(trb)); 286 287 uint64_t phys_addr = (uint64_t) addr_to_phys(cmd->ictx); 202 288 trb.parameter = host2xhci(32, phys_addr & (~0xF)); 203 289 204 290 trb.control = host2xhci(32, XHCI_TRB_TYPE_CONFIGURE_ENDPOINT_CMD << 10); 205 291 trb.control |= host2xhci(32, hc->command_ring.pcs); 206 trb.control |= host2xhci(32, slot_id << 24); 207 208 return enqueue_trb(hc, &trb, 0, 0); 209 } 210 211 int xhci_send_evaluate_context_command(xhci_hc_t *hc, uint32_t slot_id, 212 xhci_input_ctx_t *ictx) 213 { 214 assert(hc); 215 assert(ictx); 292 trb.control |= host2xhci(32, cmd->slot_id << 24); 293 294 cmd = add_cmd(hc, cmd); 295 296 return enqueue_trb(hc, &trb, 0, 0); 297 } 298 299 int xhci_send_evaluate_context_command(xhci_hc_t *hc, xhci_cmd_t *cmd) 300 { 301 assert(hc); 302 assert(cmd); 303 assert(cmd->ictx); 216 304 217 305 /** … … 224 312 memset(&trb, 0, sizeof(trb)); 225 313 226 uint64_t phys_addr = (uint64_t) addr_to_phys( ictx);314 uint64_t phys_addr = (uint64_t) addr_to_phys(cmd->ictx); 227 315 trb.parameter = host2xhci(32, phys_addr & (~0xF)); 228 316 229 317 trb.control = host2xhci(32, XHCI_TRB_TYPE_EVALUATE_CONTEXT_CMD << 10); 230 318 trb.control |= host2xhci(32, hc->command_ring.pcs); 231 trb.control |= host2xhci(32, slot_id << 24); 232 233 return enqueue_trb(hc, &trb, 0, 0); 234 } 235 236 int xhci_send_reset_endpoint_command(xhci_hc_t *hc, uint32_t slot_id, uint32_t ep_id, uint8_t tcs) 237 { 238 assert(hc); 319 trb.control |= host2xhci(32, cmd->slot_id << 24); 320 321 cmd = add_cmd(hc, cmd); 322 323 return enqueue_trb(hc, &trb, 0, 0); 324 } 325 326 int xhci_send_reset_endpoint_command(xhci_hc_t *hc, xhci_cmd_t *cmd, uint32_t ep_id, uint8_t tcs) 327 { 328 assert(hc); 329 assert(cmd); 239 330 240 331 /** … … 249 340 trb.control |= host2xhci(32, (tcs & 0x1) << 9); 250 341 trb.control |= host2xhci(32, (ep_id & 0x5) << 16); 251 trb.control |= host2xhci(32, slot_id << 24); 252 253 return enqueue_trb(hc, &trb, 0, 0); 254 } 255 256 int xhci_send_stop_endpoint_command(xhci_hc_t *hc, uint32_t slot_id, uint32_t ep_id, uint8_t susp) 257 { 258 assert(hc); 342 trb.control |= host2xhci(32, cmd->slot_id << 24); 343 344 return enqueue_trb(hc, &trb, 0, 0); 345 } 346 347 int xhci_send_stop_endpoint_command(xhci_hc_t *hc, xhci_cmd_t *cmd, uint32_t ep_id, uint8_t susp) 348 { 349 assert(hc); 350 assert(cmd); 259 351 260 352 xhci_trb_t trb; … … 265 357 trb.control |= host2xhci(32, (ep_id & 0x5) << 16); 266 358 trb.control |= host2xhci(32, (susp & 0x1) << 23); 267 trb.control |= host2xhci(32, slot_id << 24); 268 269 return enqueue_trb(hc, &trb, 0, 0); 270 } 271 272 int xhci_send_reset_device_command(xhci_hc_t *hc, uint32_t slot_id) 273 { 274 assert(hc); 359 trb.control |= host2xhci(32, cmd->slot_id << 24); 360 361 cmd = add_cmd(hc, cmd); 362 363 return enqueue_trb(hc, &trb, 0, 0); 364 } 365 366 int xhci_send_reset_device_command(xhci_hc_t *hc, xhci_cmd_t *cmd) 367 { 368 assert(hc); 369 assert(cmd); 275 370 276 371 xhci_trb_t trb; … … 279 374 trb.control = host2xhci(32, XHCI_TRB_TYPE_RESET_DEVICE_CMD << 10); 280 375 trb.control |= host2xhci(32, hc->command_ring.pcs); 281 trb.control |= host2xhci(32, slot_id << 24);376 trb.control |= host2xhci(32, cmd->slot_id << 24); 282 377 283 378 return enqueue_trb(hc, &trb, 0, 0); … … 286 381 int xhci_handle_command_completion(xhci_hc_t *hc, xhci_trb_t *trb) 287 382 { 383 // TODO: Update dequeue ptrs. 384 // TODO: Possibly clone command trb, as it may get overwritten before 385 // it is processed (if somebody polls the command completion). 288 386 assert(hc); 289 387 assert(trb); 290 388 291 389 usb_log_debug("HC(%p) Command completed.", hc); 292 xhci_dump_trb(trb);293 390 294 391 int code; 295 392 uint32_t slot_id; 296 xhci_trb_t *command; 393 xhci_cmd_t *command; 394 xhci_trb_t *command_trb; 297 395 298 396 code = XHCI_DWORD_EXTRACT(trb->status, 31, 24); 299 command = (xhci_trb_t *) XHCI_QWORD_EXTRACT(trb->parameter, 63, 4);300 397 slot_id = XHCI_DWORD_EXTRACT(trb->control, 31, 24); 301 398 (void) slot_id; 302 399 303 if (TRB_TYPE(*command) != XHCI_TRB_TYPE_NO_OP_CMD) { 400 command = get_next_command(hc); 401 assert(command); 402 403 command_trb = command->trb; 404 405 code = XHCI_DWORD_EXTRACT(trb->status, 31, 24); 406 command->status = code; 407 408 slot_id = XHCI_DWORD_EXTRACT(trb->control, 31, 24); 409 command->slot_id = slot_id; 410 411 usb_log_debug2("Completed command trb:"); 412 xhci_dump_trb(command_trb); 413 if (TRB_TYPE(*command_trb) != XHCI_TRB_TYPE_NO_OP_CMD) { 304 414 if (code != XHCI_TRBC_SUCCESS) { 305 415 report_error(code); 306 xhci_dump_trb(command );416 xhci_dump_trb(command_trb); 307 417 } 308 418 } 309 419 310 switch (TRB_TYPE(*command )) {420 switch (TRB_TYPE(*command_trb)) { 311 421 case XHCI_TRB_TYPE_NO_OP_CMD: 312 422 assert(code = XHCI_TRBC_TRB_ERROR); 313 return EOK;423 break; 314 424 case XHCI_TRB_TYPE_ENABLE_SLOT_CMD: 315 return EOK;425 break; 316 426 case XHCI_TRB_TYPE_DISABLE_SLOT_CMD: 317 return EOK;427 break; 318 428 case XHCI_TRB_TYPE_ADDRESS_DEVICE_CMD: 319 return EOK;429 break; 320 430 case XHCI_TRB_TYPE_CONFIGURE_ENDPOINT_CMD: 321 return EOK;431 break; 322 432 case XHCI_TRB_TYPE_EVALUATE_CONTEXT_CMD: 323 return EOK;433 break; 324 434 case XHCI_TRB_TYPE_RESET_ENDPOINT_CMD: 325 return EOK;435 break; 326 436 case XHCI_TRB_TYPE_STOP_ENDPOINT_CMD: 327 437 // Note: If the endpoint was in the middle of a transfer, then the xHC 328 438 // will add a Transfer TRB before the Event TRB, research that and 329 439 // handle it appropriately! 330 return EOK;440 break; 331 441 case XHCI_TRB_TYPE_RESET_DEVICE_CMD: 332 return EOK;442 break; 333 443 default: 334 444 usb_log_debug2("Unsupported command trb."); 335 xhci_dump_trb(command); 445 xhci_dump_trb(command_trb); 446 447 command->completed = true; 336 448 return ENAK; 337 449 } 450 451 command->completed = true; 452 453 if (!command->has_owner) 454 xhci_free_command(command); 455 456 return EOK; 338 457 } 339 458 -
uspace/drv/bus/usb/xhci/commands.h
r9af3281 r110d795 37 37 #define XHCI_COMMANDS_H 38 38 39 #include <adt/list.h> 40 #include <stdbool.h> 41 39 42 typedef struct xhci_hc xhci_hc_t; 40 43 typedef struct xhci_trb xhci_trb_t; 41 44 typedef struct xhci_input_ctx xhci_input_ctx_t; 42 45 43 int xhci_send_no_op_command(xhci_hc_t *); 44 int xhci_send_enable_slot_command(xhci_hc_t *); 45 int xhci_send_disable_slot_command(xhci_hc_t *, uint32_t); 46 int xhci_send_address_device_command(xhci_hc_t *, uint32_t, xhci_input_ctx_t *); 47 int xhci_send_configure_endpoint_command(xhci_hc_t *, uint32_t, xhci_input_ctx_t *); 48 int xhci_send_evaluate_context_command(xhci_hc_t *, uint32_t, xhci_input_ctx_t *); 49 int xhci_send_reset_endpoint_command(xhci_hc_t *, uint32_t, uint32_t, uint8_t); 50 int xhci_send_stop_endpoint_command(xhci_hc_t *, uint32_t, uint32_t, uint8_t); 46 typedef struct xhci_command { 47 link_t link; 48 49 xhci_trb_t *trb; 50 xhci_input_ctx_t *ictx; 51 uint32_t slot_id; 52 uint32_t status; 53 54 bool completed; 55 bool has_owner; 56 } xhci_cmd_t; 57 58 int xhci_init_commands(xhci_hc_t *); 59 int xhci_wait_for_command(xhci_hc_t *, xhci_cmd_t *, uint32_t); 60 xhci_cmd_t *xhci_alloc_command(void); 61 void xhci_free_command(xhci_cmd_t *); 62 63 int xhci_send_no_op_command(xhci_hc_t *, xhci_cmd_t *); 64 int xhci_send_enable_slot_command(xhci_hc_t *, xhci_cmd_t *); 65 int xhci_send_disable_slot_command(xhci_hc_t *, xhci_cmd_t *); 66 int xhci_send_address_device_command(xhci_hc_t *, xhci_cmd_t *); 67 int xhci_send_configure_endpoint_command(xhci_hc_t *, xhci_cmd_t *); 68 int xhci_send_evaluate_context_command(xhci_hc_t *, xhci_cmd_t *); 69 int xhci_send_reset_endpoint_command(xhci_hc_t *, xhci_cmd_t *, uint32_t, uint8_t); 70 int xhci_send_stop_endpoint_command(xhci_hc_t *, xhci_cmd_t *, uint32_t, uint8_t); 51 71 // TODO: Set dequeue ptr (section 4.6.10). 52 int xhci_send_reset_device_command(xhci_hc_t *, uint32_t);72 int xhci_send_reset_device_command(xhci_hc_t *, xhci_cmd_t *); 53 73 // TODO: Force event (optional normative, for VMM, section 4.6.12). 54 74 // TODO: Negotiate bandwidth (optional normative, section 4.6.13). -
uspace/drv/bus/usb/xhci/hc.h
r9af3281 r110d795 73 73 unsigned max_slots; 74 74 bool ac64; 75 76 /* Command list */ 77 list_t commands; 75 78 } xhci_hc_t; 76 79
Note:
See TracChangeset
for help on using the changeset viewer.