Changes in uspace/drv/ohci/hc.c [4125b7d:8790650] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/ohci/hc.c
r4125b7d r8790650 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, 113 106 BANDWIDTH_AVAILABLE_USB11); 114 107 CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n", 115 str_error(ret));108 ret, str_error(ret)); 116 109 117 110 hc_gain_control(instance); 118 111 ret = hc_init_memory(instance); 119 CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures: 120 str_error(ret));112 CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures:%s.\n", 113 ret, str_error(ret)); 121 114 hc_init_hw(instance); 122 fibril_mutex_initialize(&instance->guard); 123 124 rh_init(&instance->rh, instance->registers); 115 116 rh_init(&instance->rh, dev, instance->registers); 125 117 126 118 if (!interrupts) { … … 130 122 } 131 123 132 list_initialize(&instance->pending_batches); 133 #undef CHECK_RET_RETURN 134 return EOK; 135 } 136 /*----------------------------------------------------------------------------*/ 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) { 124 return EOK; 125 } 126 /*----------------------------------------------------------------------------*/ 127 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch) 128 { 129 assert(instance); 130 assert(batch); 131 132 /* check for root hub communication */ 133 if (batch->target.address == instance->rh.address) { 134 return rh_request(&instance->rh, batch); 135 } 136 137 transfer_list_add_batch( 138 instance->transfers[batch->transfer_type], batch); 139 140 switch (batch->transfer_type) { 167 141 case USB_TRANSFER_CONTROL: 168 142 instance->registers->control &= ~C_CLE; 169 endpoint_list_add_ep(170 &instance->lists[ep->transfer_type], hcd_ep);171 instance->registers->control_current = 0;143 instance->registers->command_status |= CS_CLF; 144 usb_log_debug2("Set control transfer filled: %x.\n", 145 instance->registers->command_status); 172 146 instance->registers->control |= C_CLE; 173 147 break; 174 148 case USB_TRANSFER_BULK: 175 instance->registers->control &= ~C_BLE; 176 endpoint_list_add_ep( 177 &instance->lists[ep->transfer_type], hcd_ep); 178 instance->registers->control |= C_BLE; 179 break; 180 case USB_TRANSFER_ISOCHRONOUS: 181 case USB_TRANSFER_INTERRUPT: 182 instance->registers->control &= (~C_PLE & ~C_IE); 183 endpoint_list_add_ep( 184 &instance->lists[ep->transfer_type], hcd_ep); 185 instance->registers->control |= C_PLE | C_IE; 149 instance->registers->command_status |= CS_BLF; 150 usb_log_debug2("Set bulk transfer filled: %x.\n", 151 instance->registers->command_status); 186 152 break; 187 153 default: 188 154 break; 189 155 } 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 fibril_mutex_unlock(&instance->guard);281 156 return EOK; 282 157 } … … 290 165 rh_interrupt(&instance->rh); 291 166 292 usb_log_debug("OHCI interrupt: %x.\n", status); 293 294 if (status & IS_WDH) { 295 fibril_mutex_lock(&instance->guard); 296 usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca, 297 instance->registers->hcca, 298 (void *) addr_to_phys(instance->hcca)); 299 usb_log_debug2("Periodic current: %#" PRIx32 ".\n", 300 instance->registers->periodic_current); 301 302 link_t *current = instance->pending_batches.next; 303 while (current != &instance->pending_batches) { 304 link_t *next = current->next; 305 usb_transfer_batch_t *batch = 306 usb_transfer_batch_from_link(current); 307 308 if (batch_is_complete(batch)) { 309 list_remove(current); 310 usb_transfer_batch_finish(batch); 311 } 312 current = next; 313 } 314 fibril_mutex_unlock(&instance->guard); 167 usb_log_info("OHCI interrupt: %x.\n", status); 168 169 170 LIST_INITIALIZE(done); 171 transfer_list_remove_finished(&instance->transfers_interrupt, &done); 172 transfer_list_remove_finished(&instance->transfers_isochronous, &done); 173 transfer_list_remove_finished(&instance->transfers_control, &done); 174 transfer_list_remove_finished(&instance->transfers_bulk, &done); 175 176 while (!list_empty(&done)) { 177 link_t *item = done.next; 178 list_remove(item); 179 usb_transfer_batch_t *batch = 180 list_get_instance(item, usb_transfer_batch_t, link); 181 usb_transfer_batch_finish(batch); 315 182 } 316 183 } … … 324 191 instance->registers->interrupt_status = status; 325 192 hc_interrupt(instance, status); 326 async_usleep( 50000);193 async_usleep(1000); 327 194 } 328 195 return EOK; … … 400 267 instance->registers->control); 401 268 402 /* Use HCCA */403 instance->registers->hcca = addr_to_phys(instance->hcca);404 405 /* Use queues */406 instance->registers->bulk_head =407 instance->lists[USB_TRANSFER_BULK].list_head_pa;408 usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n",409 instance->lists[USB_TRANSFER_BULK].list_head,410 instance->lists[USB_TRANSFER_BULK].list_head_pa);411 412 instance->registers->control_head =413 instance->lists[USB_TRANSFER_CONTROL].list_head_pa;414 usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n",415 instance->lists[USB_TRANSFER_CONTROL].list_head,416 instance->lists[USB_TRANSFER_CONTROL].list_head_pa);417 418 269 /* Enable queues */ 419 270 instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE); … … 445 296 assert(instance); 446 297 447 #define SETUP_ ENDPOINT_LIST(type) \298 #define SETUP_TRANSFER_LIST(type, name) \ 448 299 do { \ 449 const char *name = usb_str_transfer_type(type); \ 450 int ret = endpoint_list_init(&instance->lists[type], name); \ 300 int ret = transfer_list_init(&instance->type, name); \ 451 301 if (ret != EOK) { \ 452 usb_log_error("Failed(%d) to setup %s endpointlist.\n", \302 usb_log_error("Failed(%d) to setup %s transfer list.\n", \ 453 303 ret, name); \ 454 endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]); \455 endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \456 endpoint_list_fini(&instance->lists[USB_TRANSFER_CONTROL]); \457 endpoint_list_fini(&instance->lists[USB_TRANSFER_BULK]); \304 transfer_list_fini(&instance->transfers_isochronous); \ 305 transfer_list_fini(&instance->transfers_interrupt); \ 306 transfer_list_fini(&instance->transfers_control); \ 307 transfer_list_fini(&instance->transfers_bulk); \ 458 308 } \ 459 309 } while (0) 460 310 461 SETUP_ENDPOINT_LIST(USB_TRANSFER_ISOCHRONOUS); 462 SETUP_ENDPOINT_LIST(USB_TRANSFER_INTERRUPT); 463 SETUP_ENDPOINT_LIST(USB_TRANSFER_CONTROL); 464 SETUP_ENDPOINT_LIST(USB_TRANSFER_BULK); 465 #undef SETUP_ENDPOINT_LIST 466 endpoint_list_set_next(&instance->lists[USB_TRANSFER_INTERRUPT], 467 &instance->lists[USB_TRANSFER_ISOCHRONOUS]); 468 469 return EOK; 311 SETUP_TRANSFER_LIST(transfers_isochronous, "ISOCHRONOUS"); 312 SETUP_TRANSFER_LIST(transfers_interrupt, "INTERRUPT"); 313 SETUP_TRANSFER_LIST(transfers_control, "CONTROL"); 314 SETUP_TRANSFER_LIST(transfers_bulk, "BULK"); 315 316 transfer_list_set_next(&instance->transfers_interrupt, 317 &instance->transfers_isochronous); 318 319 /* Assign pointers to be used during scheduling */ 320 instance->transfers[USB_TRANSFER_INTERRUPT] = 321 &instance->transfers_interrupt; 322 instance->transfers[USB_TRANSFER_ISOCHRONOUS] = 323 &instance->transfers_interrupt; 324 instance->transfers[USB_TRANSFER_CONTROL] = 325 &instance->transfers_control; 326 instance->transfers[USB_TRANSFER_BULK] = 327 &instance->transfers_bulk; 328 329 return EOK; 330 #undef CHECK_RET_CLEAR_RETURN 470 331 } 471 332 /*----------------------------------------------------------------------------*/ … … 481 342 return ENOMEM; 482 343 bzero(instance->hcca, sizeof(hcca_t)); 483 usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca); 344 instance->registers->hcca = addr_to_phys(instance->hcca); 345 usb_log_debug2("OHCI HCCA initialized at %p(%p).\n", 346 instance->hcca, instance->registers->hcca); 347 348 /* Use queues */ 349 instance->registers->bulk_head = instance->transfers_bulk.list_head_pa; 350 usb_log_debug2("Bulk HEAD set to: %p(%p).\n", 351 instance->transfers_bulk.list_head, 352 instance->transfers_bulk.list_head_pa); 353 354 instance->registers->control_head = 355 instance->transfers_control.list_head_pa; 356 usb_log_debug2("Control HEAD set to: %p(%p).\n", 357 instance->transfers_control.list_head, 358 instance->transfers_control.list_head_pa); 484 359 485 360 unsigned i = 0; 486 361 for (; i < 32; ++i) { 487 362 instance->hcca->int_ep[i] = 488 instance-> lists[USB_TRANSFER_INTERRUPT].list_head_pa;489 } 490 usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",491 instance-> lists[USB_TRANSFER_INTERRUPT].list_head,492 instance-> lists[USB_TRANSFER_INTERRUPT].list_head_pa);363 instance->transfers_interrupt.list_head_pa; 364 } 365 usb_log_debug2("Interrupt HEADs set to: %p(%p).\n", 366 instance->transfers_interrupt.list_head, 367 instance->transfers_interrupt.list_head_pa); 493 368 494 369 return EOK;
Note:
See TracChangeset
for help on using the changeset viewer.