Changes in uspace/drv/ohci/hc.c [aa9ccf7:d6522dd] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/ohci/hc.c
raa9ccf7 rd6522dd 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, … … 115 122 fibril_mutex_initialize(&instance->guard); 116 123 117 rh_init(&instance->rh, dev,instance->registers);124 rh_init(&instance->rh, instance->registers); 118 125 119 126 if (!interrupts) { … … 123 130 } 124 131 125 return EOK; 126 } 127 /*----------------------------------------------------------------------------*/ 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) { 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) { 140 167 case USB_TRANSFER_CONTROL: 141 168 instance->registers->control &= ~C_CLE; 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); 169 endpoint_list_add_ep( 170 &instance->lists[ep->transfer_type], hcd_ep); 147 171 instance->registers->control_current = 0; 148 172 instance->registers->control |= C_CLE; … … 150 174 case USB_TRANSFER_BULK: 151 175 instance->registers->control &= ~C_BLE; 152 transfer_list_add_batch( 153 instance->transfers[batch->transfer_type], batch); 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: 271 instance->registers->command_status |= CS_CLF; 272 break; 273 case USB_TRANSFER_BULK: 154 274 instance->registers->command_status |= CS_BLF; 155 usb_log_debug2("Set bulk transfer filled: %x.\n",156 instance->registers->command_status);157 instance->registers->control |= C_BLE;158 break;159 case USB_TRANSFER_INTERRUPT:160 case USB_TRANSFER_ISOCHRONOUS:161 instance->registers->control &= (~C_PLE & ~C_IE);162 transfer_list_add_batch(163 instance->transfers[batch->transfer_type], batch);164 instance->registers->control |= C_PLE | C_IE;165 usb_log_debug2("Added periodic transfer: %x.\n",166 instance->registers->periodic_current);167 275 break; 168 276 default: 169 277 break; 170 278 } 279 171 280 fibril_mutex_unlock(&instance->guard); 172 281 return EOK; … … 189 298 usb_log_debug2("Periodic current: %p.\n", 190 299 instance->registers->periodic_current); 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); 300 301 link_t *current = instance->pending_batches.next; 302 while (current != &instance->pending_batches) { 303 link_t *next = current->next; 204 304 usb_transfer_batch_t *batch = 205 list_get_instance(item, usb_transfer_batch_t, link); 206 usb_transfer_batch_finish(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; 207 312 } 208 313 fibril_mutex_unlock(&instance->guard); … … 298 403 299 404 /* Use queues */ 300 instance->registers->bulk_head = instance->transfers_bulk.list_head_pa; 405 instance->registers->bulk_head = 406 instance->lists[USB_TRANSFER_BULK].list_head_pa; 301 407 usb_log_debug2("Bulk HEAD set to: %p(%p).\n", 302 instance-> transfers_bulk.list_head,303 instance-> transfers_bulk.list_head_pa);408 instance->lists[USB_TRANSFER_BULK].list_head, 409 instance->lists[USB_TRANSFER_BULK].list_head_pa); 304 410 305 411 instance->registers->control_head = 306 instance-> transfers_control.list_head_pa;412 instance->lists[USB_TRANSFER_CONTROL].list_head_pa; 307 413 usb_log_debug2("Control HEAD set to: %p(%p).\n", 308 instance-> transfers_control.list_head,309 instance-> transfers_control.list_head_pa);414 instance->lists[USB_TRANSFER_CONTROL].list_head, 415 instance->lists[USB_TRANSFER_CONTROL].list_head_pa); 310 416 311 417 /* Enable queues */ … … 338 444 assert(instance); 339 445 340 #define SETUP_ TRANSFER_LIST(type, name) \446 #define SETUP_ENDPOINT_LIST(type) \ 341 447 do { \ 342 int ret = transfer_list_init(&instance->type, name); \ 448 const char *name = usb_str_transfer_type(type); \ 449 int ret = endpoint_list_init(&instance->lists[type], name); \ 343 450 if (ret != EOK) { \ 344 usb_log_error("Failed(%d) to setup %s transferlist.\n", \451 usb_log_error("Failed(%d) to setup %s endpoint list.\n", \ 345 452 ret, name); \ 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); \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]); \ 350 457 } \ 351 458 } while (0) 352 459 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; 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]); 370 467 371 468 return EOK; … … 388 485 for (; i < 32; ++i) { 389 486 instance->hcca->int_ep[i] = 390 instance-> transfers_interrupt.list_head_pa;487 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa; 391 488 } 392 489 usb_log_debug2("Interrupt HEADs set to: %p(%p).\n", 393 instance-> transfers_interrupt.list_head,394 instance-> transfers_interrupt.list_head_pa);490 instance->lists[USB_TRANSFER_INTERRUPT].list_head, 491 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa); 395 492 396 493 return EOK;
Note:
See TracChangeset
for help on using the changeset viewer.