Changeset e1dbcbc in mainline for uspace/drv/ohci/hc.c
- Timestamp:
- 2011-04-29T13:43:01Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- a81a1d09
- Parents:
- 380e0364 (diff), f19f1b7 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/ohci/hc.c
r380e0364 re1dbcbc 43 43 44 44 #include "hc.h" 45 #include "hcd_endpoint.h" 45 46 46 47 static int interrupt_emulator(hc_t *instance); … … 55 56 assert(hub_fun); 56 57 58 int ret; 59 57 60 usb_address_t hub_address = 58 61 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 } 59 66 instance->rh.address = hub_address; 60 67 usb_device_keeper_bind( 61 68 &instance->manager, hub_address, hub_fun->handle); 62 69 63 endpoint_t *ep = malloc(sizeof(endpoint_t));64 assert(ep);65 i nt 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);70 ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL, 71 USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0); 72 if (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 } 70 77 71 78 char *match_str = NULL; 79 /* DDF needs heap allocated string */ 72 80 ret = asprintf(&match_str, "usb&class=hub"); 73 // ret = (match_str == NULL) ? ret : EOK;74 81 if (ret < 0) { 75 82 usb_log_error( 76 83 "Failed(%d) to create root hub match-id string.\n", ret); 84 usb_device_keeper_release(&instance->manager, hub_address); 77 85 return ret; 78 86 } … … 80 88 ret = ddf_fun_add_match_id(hub_fun, match_str, 100); 81 89 if (ret != EOK) { 82 usb_log_error("Failed add createroot hub match-id.\n");90 usb_log_error("Failed add root hub match-id.\n"); 83 91 } 84 92 return ret; … … 101 109 ret, str_error(ret)); 102 110 103 instance->ddf_instance = fun;104 111 usb_device_keeper_init(&instance->manager); 105 112 ret = usb_endpoint_manager_init(&instance->ep_manager, 106 113 BANDWIDTH_AVAILABLE_USB11); 107 114 CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n", 108 ret,str_error(ret));115 str_error(ret)); 109 116 110 117 hc_gain_control(instance); 111 118 ret = hc_init_memory(instance); 112 CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures: %s.\n",113 ret,str_error(ret));119 CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures: %s.\n", 120 str_error(ret)); 114 121 hc_init_hw(instance); 115 116 rh_init(&instance->rh, dev, instance->registers); 122 fibril_mutex_initialize(&instance->guard); 123 124 rh_init(&instance->rh, instance->registers); 117 125 118 126 if (!interrupts) { … … 122 130 } 123 131 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) { 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) { 141 167 case USB_TRANSFER_CONTROL: 142 168 instance->registers->control &= ~C_CLE; 169 endpoint_list_add_ep( 170 &instance->lists[ep->transfer_type], hcd_ep); 171 instance->registers->control_current = 0; 172 instance->registers->control |= C_CLE; 173 break; 174 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; 186 break; 187 default: 188 break; 189 } 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: 143 271 instance->registers->command_status |= CS_CLF; 144 usb_log_debug2("Set control transfer filled: %x.\n",145 instance->registers->command_status);146 instance->registers->control |= C_CLE;147 272 break; 148 273 case USB_TRANSFER_BULK: 149 274 instance->registers->command_status |= CS_BLF; 150 usb_log_debug2("Set bulk transfer filled: %x.\n",151 instance->registers->command_status);152 275 break; 153 276 default: 154 277 break; 155 278 } 279 280 fibril_mutex_unlock(&instance->guard); 156 281 return EOK; 157 282 } … … 165 290 rh_interrupt(&instance->rh); 166 291 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); 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); 182 315 } 183 316 } … … 191 324 instance->registers->interrupt_status = status; 192 325 hc_interrupt(instance, status); 193 async_usleep( 1000);326 async_usleep(50000); 194 327 } 195 328 return EOK; … … 267 400 instance->registers->control); 268 401 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 269 418 /* Enable queues */ 270 419 instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE); … … 296 445 assert(instance); 297 446 298 #define SETUP_ TRANSFER_LIST(type, name) \447 #define SETUP_ENDPOINT_LIST(type) \ 299 448 do { \ 300 int ret = transfer_list_init(&instance->type, name); \ 449 const char *name = usb_str_transfer_type(type); \ 450 int ret = endpoint_list_init(&instance->lists[type], name); \ 301 451 if (ret != EOK) { \ 302 usb_log_error("Failed(%d) to setup %s transferlist.\n", \452 usb_log_error("Failed(%d) to setup %s endpoint list.\n", \ 303 453 ret, name); \ 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); \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]); \ 308 458 } \ 309 459 } while (0) 310 460 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 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; 331 470 } 332 471 /*----------------------------------------------------------------------------*/ … … 342 481 return ENOMEM; 343 482 bzero(instance->hcca, sizeof(hcca_t)); 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); 483 usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca); 359 484 360 485 unsigned i = 0; 361 486 for (; i < 32; ++i) { 362 487 instance->hcca->int_ep[i] = 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);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); 368 493 369 494 return EOK;
Note:
See TracChangeset
for help on using the changeset viewer.