Changes in uspace/drv/ohci/hc.c [d6522dd:aa9ccf7] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/ohci/hc.c
rd6522dd raa9ccf7 43 43 44 44 #include "hc.h" 45 #include "hcd_endpoint.h"46 45 47 46 static int interrupt_emulator(hc_t *instance); … … 56 55 assert(hub_fun); 57 56 58 int ret;59 60 57 usb_address_t hub_address = 61 58 device_keeper_get_free_address(&instance->manager, USB_SPEED_FULL); 62 if (hub_address <= 0) {63 usb_log_error("Failed to get OHCI root hub address.\n");64 return hub_address;65 }66 59 instance->rh.address = hub_address; 67 60 usb_device_keeper_bind( 68 61 &instance->manager, hub_address, hub_fun->handle); 69 62 70 ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL,71 USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0);72 i f (ret != EOK) {73 usb_log_error("Failed to add OHCI rh endpoint 0.\n");74 usb_device_keeper_release(&instance->manager, hub_address);75 return ret;76 }63 endpoint_t *ep = malloc(sizeof(endpoint_t)); 64 assert(ep); 65 int ret = endpoint_init(ep, hub_address, 0, USB_DIRECTION_BOTH, 66 USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64); 67 assert(ret == EOK); 68 ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, 0); 69 assert(ret == EOK); 77 70 78 71 char *match_str = NULL; 79 /* DDF needs heap allocated string */80 72 ret = asprintf(&match_str, "usb&class=hub"); 73 // ret = (match_str == NULL) ? ret : EOK; 81 74 if (ret < 0) { 82 75 usb_log_error( 83 76 "Failed(%d) to create root hub match-id string.\n", ret); 84 usb_device_keeper_release(&instance->manager, hub_address);85 77 return ret; 86 78 } … … 88 80 ret = ddf_fun_add_match_id(hub_fun, match_str, 100); 89 81 if (ret != EOK) { 90 usb_log_error("Failed add root hub match-id.\n");82 usb_log_error("Failed add create root hub match-id.\n"); 91 83 } 92 84 return ret; … … 109 101 ret, str_error(ret)); 110 102 103 instance->ddf_instance = fun; 111 104 usb_device_keeper_init(&instance->manager); 112 105 ret = usb_endpoint_manager_init(&instance->ep_manager, … … 122 115 fibril_mutex_initialize(&instance->guard); 123 116 124 rh_init(&instance->rh, instance->registers);117 rh_init(&instance->rh, dev, instance->registers); 125 118 126 119 if (!interrupts) { … … 130 123 } 131 124 132 list_initialize(&instance->pending_batches);133 #undef CHECK_RET_RETURN134 125 return EOK; 135 126 } 136 127 /*----------------------------------------------------------------------------*/ 137 int hc_add_endpoint( 138 hc_t *instance, usb_address_t address, usb_endpoint_t endpoint, 139 usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction, 140 size_t mps, size_t size, unsigned interval) 141 { 142 endpoint_t *ep = malloc(sizeof(endpoint_t)); 143 if (ep == NULL) 144 return ENOMEM; 145 int ret = 146 endpoint_init(ep, address, endpoint, direction, type, speed, mps); 147 if (ret != EOK) { 148 free(ep); 149 return ret; 150 } 151 152 hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep); 153 if (hcd_ep == NULL) { 154 endpoint_destroy(ep); 155 return ENOMEM; 156 } 157 158 ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size); 159 if (ret != EOK) { 160 hcd_endpoint_clear(ep); 161 endpoint_destroy(ep); 162 return ret; 163 } 164 165 /* Enqueue hcd_ep */ 166 switch (ep->transfer_type) { 128 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch) 129 { 130 assert(instance); 131 assert(batch); 132 133 /* check for root hub communication */ 134 if (batch->target.address == instance->rh.address) { 135 return rh_request(&instance->rh, batch); 136 } 137 138 fibril_mutex_lock(&instance->guard); 139 switch (batch->transfer_type) { 167 140 case USB_TRANSFER_CONTROL: 168 141 instance->registers->control &= ~C_CLE; 169 endpoint_list_add_ep( 170 &instance->lists[ep->transfer_type], hcd_ep); 142 transfer_list_add_batch( 143 instance->transfers[batch->transfer_type], batch); 144 instance->registers->command_status |= CS_CLF; 145 usb_log_debug2("Set CS control transfer filled: %x.\n", 146 instance->registers->command_status); 171 147 instance->registers->control_current = 0; 172 148 instance->registers->control |= C_CLE; … … 174 150 case USB_TRANSFER_BULK: 175 151 instance->registers->control &= ~C_BLE; 176 endpoint_list_add_ep( 177 &instance->lists[ep->transfer_type], hcd_ep); 152 transfer_list_add_batch( 153 instance->transfers[batch->transfer_type], batch); 154 instance->registers->command_status |= CS_BLF; 155 usb_log_debug2("Set bulk transfer filled: %x.\n", 156 instance->registers->command_status); 178 157 instance->registers->control |= C_BLE; 179 158 break; 159 case USB_TRANSFER_INTERRUPT: 180 160 case USB_TRANSFER_ISOCHRONOUS: 181 case USB_TRANSFER_INTERRUPT:182 161 instance->registers->control &= (~C_PLE & ~C_IE); 183 endpoint_list_add_ep(184 &instance->lists[ep->transfer_type], hcd_ep);162 transfer_list_add_batch( 163 instance->transfers[batch->transfer_type], batch); 185 164 instance->registers->control |= C_PLE | C_IE; 165 usb_log_debug2("Added periodic transfer: %x.\n", 166 instance->registers->periodic_current); 186 167 break; 187 168 default: 188 169 break; 189 170 } 190 191 return EOK;192 }193 /*----------------------------------------------------------------------------*/194 int hc_remove_endpoint(hc_t *instance, usb_address_t address,195 usb_endpoint_t endpoint, usb_direction_t direction)196 {197 assert(instance);198 fibril_mutex_lock(&instance->guard);199 endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,200 address, endpoint, direction, NULL);201 if (ep == NULL) {202 usb_log_error("Endpoint unregister failed: No such EP.\n");203 fibril_mutex_unlock(&instance->guard);204 return ENOENT;205 }206 207 hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);208 if (hcd_ep) {209 /* Dequeue hcd_ep */210 switch (ep->transfer_type) {211 case USB_TRANSFER_CONTROL:212 instance->registers->control &= ~C_CLE;213 endpoint_list_remove_ep(214 &instance->lists[ep->transfer_type], hcd_ep);215 instance->registers->control_current = 0;216 instance->registers->control |= C_CLE;217 break;218 case USB_TRANSFER_BULK:219 instance->registers->control &= ~C_BLE;220 endpoint_list_remove_ep(221 &instance->lists[ep->transfer_type], hcd_ep);222 instance->registers->control |= C_BLE;223 break;224 case USB_TRANSFER_ISOCHRONOUS:225 case USB_TRANSFER_INTERRUPT:226 instance->registers->control &= (~C_PLE & ~C_IE);227 endpoint_list_remove_ep(228 &instance->lists[ep->transfer_type], hcd_ep);229 instance->registers->control |= C_PLE | C_IE;230 break;231 default:232 break;233 }234 hcd_endpoint_clear(ep);235 } else {236 usb_log_warning("Endpoint without hcd equivalent structure.\n");237 }238 int ret = usb_endpoint_manager_unregister_ep(&instance->ep_manager,239 address, endpoint, direction);240 fibril_mutex_unlock(&instance->guard);241 return ret;242 }243 /*----------------------------------------------------------------------------*/244 endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,245 usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw)246 {247 assert(instance);248 fibril_mutex_lock(&instance->guard);249 endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,250 address, endpoint, direction, bw);251 fibril_mutex_unlock(&instance->guard);252 return ep;253 }254 /*----------------------------------------------------------------------------*/255 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)256 {257 assert(instance);258 assert(batch);259 assert(batch->ep);260 261 /* check for root hub communication */262 if (batch->ep->address == instance->rh.address) {263 return rh_request(&instance->rh, batch);264 }265 266 fibril_mutex_lock(&instance->guard);267 list_append(&batch->link, &instance->pending_batches);268 batch_commit(batch);269 switch (batch->ep->transfer_type) {270 case USB_TRANSFER_CONTROL:271 instance->registers->command_status |= CS_CLF;272 break;273 case USB_TRANSFER_BULK:274 instance->registers->command_status |= CS_BLF;275 break;276 default:277 break;278 }279 280 171 fibril_mutex_unlock(&instance->guard); 281 172 return EOK; … … 298 189 usb_log_debug2("Periodic current: %p.\n", 299 190 instance->registers->periodic_current); 300 301 link_t *current = instance->pending_batches.next; 302 while (current != &instance->pending_batches) { 303 link_t *next = current->next; 191 LIST_INITIALIZE(done); 192 transfer_list_remove_finished( 193 &instance->transfers_interrupt, &done); 194 transfer_list_remove_finished( 195 &instance->transfers_isochronous, &done); 196 transfer_list_remove_finished( 197 &instance->transfers_control, &done); 198 transfer_list_remove_finished( 199 &instance->transfers_bulk, &done); 200 201 while (!list_empty(&done)) { 202 link_t *item = done.next; 203 list_remove(item); 304 204 usb_transfer_batch_t *batch = 305 usb_transfer_batch_from_link(current); 306 307 if (batch_is_complete(batch)) { 308 list_remove(current); 309 usb_transfer_batch_finish(batch); 310 } 311 current = next; 205 list_get_instance(item, usb_transfer_batch_t, link); 206 usb_transfer_batch_finish(batch); 312 207 } 313 208 fibril_mutex_unlock(&instance->guard); … … 403 298 404 299 /* Use queues */ 405 instance->registers->bulk_head = 406 instance->lists[USB_TRANSFER_BULK].list_head_pa; 300 instance->registers->bulk_head = instance->transfers_bulk.list_head_pa; 407 301 usb_log_debug2("Bulk HEAD set to: %p(%p).\n", 408 instance-> lists[USB_TRANSFER_BULK].list_head,409 instance-> lists[USB_TRANSFER_BULK].list_head_pa);302 instance->transfers_bulk.list_head, 303 instance->transfers_bulk.list_head_pa); 410 304 411 305 instance->registers->control_head = 412 instance-> lists[USB_TRANSFER_CONTROL].list_head_pa;306 instance->transfers_control.list_head_pa; 413 307 usb_log_debug2("Control HEAD set to: %p(%p).\n", 414 instance-> lists[USB_TRANSFER_CONTROL].list_head,415 instance-> lists[USB_TRANSFER_CONTROL].list_head_pa);308 instance->transfers_control.list_head, 309 instance->transfers_control.list_head_pa); 416 310 417 311 /* Enable queues */ … … 444 338 assert(instance); 445 339 446 #define SETUP_ ENDPOINT_LIST(type) \340 #define SETUP_TRANSFER_LIST(type, name) \ 447 341 do { \ 448 const char *name = usb_str_transfer_type(type); \ 449 int ret = endpoint_list_init(&instance->lists[type], name); \ 342 int ret = transfer_list_init(&instance->type, name); \ 450 343 if (ret != EOK) { \ 451 usb_log_error("Failed(%d) to setup %s endpointlist.\n", \344 usb_log_error("Failed(%d) to setup %s transfer list.\n", \ 452 345 ret, name); \ 453 endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]); \454 endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \455 endpoint_list_fini(&instance->lists[USB_TRANSFER_CONTROL]); \456 endpoint_list_fini(&instance->lists[USB_TRANSFER_BULK]); \346 transfer_list_fini(&instance->transfers_isochronous); \ 347 transfer_list_fini(&instance->transfers_interrupt); \ 348 transfer_list_fini(&instance->transfers_control); \ 349 transfer_list_fini(&instance->transfers_bulk); \ 457 350 } \ 458 351 } while (0) 459 352 460 SETUP_ENDPOINT_LIST(USB_TRANSFER_ISOCHRONOUS); 461 SETUP_ENDPOINT_LIST(USB_TRANSFER_INTERRUPT); 462 SETUP_ENDPOINT_LIST(USB_TRANSFER_CONTROL); 463 SETUP_ENDPOINT_LIST(USB_TRANSFER_BULK); 464 #undef SETUP_ENDPOINT_LIST 465 endpoint_list_set_next(&instance->lists[USB_TRANSFER_INTERRUPT], 466 &instance->lists[USB_TRANSFER_ISOCHRONOUS]); 353 SETUP_TRANSFER_LIST(transfers_isochronous, "ISOCHRONOUS"); 354 SETUP_TRANSFER_LIST(transfers_interrupt, "INTERRUPT"); 355 SETUP_TRANSFER_LIST(transfers_control, "CONTROL"); 356 SETUP_TRANSFER_LIST(transfers_bulk, "BULK"); 357 #undef SETUP_TRANSFER_LIST 358 transfer_list_set_next(&instance->transfers_interrupt, 359 &instance->transfers_isochronous); 360 361 /* Assign pointers to be used during scheduling */ 362 instance->transfers[USB_TRANSFER_INTERRUPT] = 363 &instance->transfers_interrupt; 364 instance->transfers[USB_TRANSFER_ISOCHRONOUS] = 365 &instance->transfers_interrupt; 366 instance->transfers[USB_TRANSFER_CONTROL] = 367 &instance->transfers_control; 368 instance->transfers[USB_TRANSFER_BULK] = 369 &instance->transfers_bulk; 467 370 468 371 return EOK; … … 485 388 for (; i < 32; ++i) { 486 389 instance->hcca->int_ep[i] = 487 instance-> lists[USB_TRANSFER_INTERRUPT].list_head_pa;390 instance->transfers_interrupt.list_head_pa; 488 391 } 489 392 usb_log_debug2("Interrupt HEADs set to: %p(%p).\n", 490 instance-> lists[USB_TRANSFER_INTERRUPT].list_head,491 instance-> lists[USB_TRANSFER_INTERRUPT].list_head_pa);393 instance->transfers_interrupt.list_head, 394 instance->transfers_interrupt.list_head_pa); 492 395 493 396 return EOK;
Note:
See TracChangeset
for help on using the changeset viewer.