Changeset df6ded8 in mainline for uspace/drv/bus/usb/ehci/hc.c
- Timestamp:
- 2018-02-28T16:37:50Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1b20da0
- Parents:
- f5e5f73 (diff), b2dca8de (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. - git-author:
- Jakub Jermar <jakub@…> (2018-02-28 16:06:42)
- git-committer:
- Jakub Jermar <jakub@…> (2018-02-28 16:37:50)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ehci/hc.c
rf5e5f73 rdf6ded8 1 1 /* 2 2 * Copyright (c) 2011 Jan Vesely 3 * Copyright (c) 2018 Ondrej Hlavaty 3 4 * All rights reserved. 4 5 * … … 45 46 #include <usb/debug.h> 46 47 #include <usb/usb.h> 47 #include <usb/host/util s/malloc32.h>48 #include <usb/host/utility.h> 48 49 49 50 #include "ehci_batch.h" … … 89 90 }; 90 91 91 static void hc_start(hc_t *instance);92 92 static errno_t hc_init_memory(hc_t *instance); 93 93 … … 100 100 * @return Error code. 101 101 */ 102 errno_t ehci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res, int *irq)102 errno_t hc_gen_irq_code(irq_code_t *code, hc_device_t *hcd, const hw_res_list_parsed_t *hw_res, int *irq) 103 103 { 104 104 assert(code); 105 105 assert(hw_res); 106 hc_t *instance = hcd_to_hc(hcd); 106 107 107 108 if (hw_res->irqs.count != 1 || hw_res->mem_ranges.count != 1) … … 130 131 131 132 memcpy(code->cmds, ehci_irq_commands, sizeof(ehci_irq_commands)); 132 ehci_caps_regs_t *caps = NULL;133 134 errno_t ret = pio_enable_range(®s, (void**)&caps);135 if (ret != EOK) {136 free(code->ranges);137 free(code->cmds);138 return ret;139 }140 133 141 134 ehci_regs_t *registers = 142 (ehci_regs_t *)(RNGABSPTR(regs) + EHCI_RD8(caps->caplength));135 (ehci_regs_t *)(RNGABSPTR(regs) + EHCI_RD8(instance->caps->caplength)); 143 136 code->cmds[0].addr = (void *) ®isters->usbsts; 144 137 code->cmds[3].addr = (void *) ®isters->usbsts; 145 138 EHCI_WR(code->cmds[1].value, EHCI_USED_INTERRUPTS); 146 139 147 usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d. \n",140 usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.", 148 141 RNGABSPTR(regs), RNGSZ(regs), hw_res->irqs.irqs[0]); 149 142 … … 159 152 * @return Error code 160 153 */ 161 errno_t hc_ init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts)162 { 163 assert(instance);154 errno_t hc_add(hc_device_t *hcd, const hw_res_list_parsed_t *hw_res) 155 { 156 hc_t *instance = hcd_to_hc(hcd); 164 157 assert(hw_res); 165 158 if (hw_res->mem_ranges.count != 1 || … … 172 165 if (ret != EOK) { 173 166 usb_log_error("HC(%p): Failed to gain access to device " 174 "registers: %s. \n", instance, str_error(ret));167 "registers: %s.", instance, str_error(ret)); 175 168 return ret; 176 169 } 170 177 171 usb_log_info("HC(%p): Device registers at %"PRIx64" (%zuB) accessible.", 178 172 instance, hw_res->mem_ranges.ranges[0].address.absolute, … … 184 178 + EHCI_RD8(instance->caps->caplength)); 185 179 186 list_initialize(&instance->pending_ batches);180 list_initialize(&instance->pending_endpoints); 187 181 fibril_mutex_initialize(&instance->guard); 188 182 fibril_condvar_initialize(&instance->async_doorbell); … … 197 191 usb_log_info("HC(%p): Initializing RH(%p).", instance, &instance->rh); 198 192 ehci_rh_init( 199 &instance->rh, instance->caps, instance->registers, "ehci rh"); 200 usb_log_debug("HC(%p): Starting HW.", instance); 201 hc_start(instance); 202 193 &instance->rh, instance->caps, instance->registers, &instance->guard, 194 "ehci rh"); 195 196 ehci_bus_init(&instance->bus, instance); 197 hc_device_setup(hcd, (bus_t *) &instance->bus); 203 198 return EOK; 204 199 } … … 208 203 * @param[in] instance Host controller structure to use. 209 204 */ 210 void hc_fini(hc_t *instance) 211 { 212 assert(instance); 213 //TODO: stop the hw 214 #if 0 215 endpoint_list_fini(&instance->async_list); 216 endpoint_list_fini(&instance->int_list); 217 return_page(instance->periodic_list_base); 218 #endif 205 int hc_gone(hc_device_t *hcd) 206 { 207 hc_t *hc = hcd_to_hc(hcd); 208 endpoint_list_fini(&hc->async_list); 209 endpoint_list_fini(&hc->int_list); 210 dma_buffer_free(&hc->dma_buffer); 211 return EOK; 219 212 }; 220 213 … … 224 217 assert(ep); 225 218 ehci_endpoint_t *ehci_ep = ehci_endpoint_get(ep); 226 usb_log_debug("HC(%p) enqueue EP(%d:%d:%s:%s) \n", instance,227 ep-> address, ep->endpoint,219 usb_log_debug("HC(%p) enqueue EP(%d:%d:%s:%s)", instance, 220 ep->device->address, ep->endpoint, 228 221 usb_str_transfer_type_short(ep->transfer_type), 229 222 usb_str_direction(ep->direction)); … … 248 241 assert(ep); 249 242 ehci_endpoint_t *ehci_ep = ehci_endpoint_get(ep); 250 usb_log_debug("HC(%p) dequeue EP(%d:%d:%s:%s) \n", instance,251 ep-> address, ep->endpoint,243 usb_log_debug("HC(%p) dequeue EP(%d:%d:%s:%s)", instance, 244 ep->device->address, ep->endpoint, 252 245 usb_str_transfer_type_short(ep->transfer_type), 253 246 usb_str_direction(ep->direction)); … … 273 266 } 274 267 275 errno_t ehci_hc_status(hcd_t *hcd, uint32_t *status) 276 { 277 assert(hcd); 278 hc_t *instance = hcd_get_driver_data(hcd); 279 assert(instance); 268 errno_t ehci_hc_status(bus_t *bus_base, uint32_t *status) 269 { 270 assert(bus_base); 280 271 assert(status); 272 273 ehci_bus_t *bus = (ehci_bus_t *) bus_base; 274 hc_t *hc = bus->hc; 275 assert(hc); 276 281 277 *status = 0; 282 if ( instance->registers) {283 *status = EHCI_RD( instance->registers->usbsts);284 EHCI_WR( instance->registers->usbsts, *status);285 } 286 usb_log_debug2("HC(%p): Read status: %x", instance, *status);278 if (hc->registers) { 279 *status = EHCI_RD(hc->registers->usbsts); 280 EHCI_WR(hc->registers->usbsts, *status); 281 } 282 usb_log_debug2("HC(%p): Read status: %x", hc, *status); 287 283 return EOK; 288 284 } … … 294 290 * @return Error code. 295 291 */ 296 errno_t ehci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch) 297 { 298 assert(hcd); 299 hc_t *instance = hcd_get_driver_data(hcd); 300 assert(instance); 292 errno_t ehci_hc_schedule(usb_transfer_batch_t *batch) 293 { 294 assert(batch); 295 296 ehci_bus_t *bus = (ehci_bus_t *) endpoint_get_bus(batch->ep); 297 hc_t *hc = bus->hc; 298 assert(hc); 301 299 302 300 /* Check for root hub communication */ 303 if (batch-> ep->address == ehci_rh_get_address(&instance->rh)) {301 if (batch->target.address == ehci_rh_get_address(&hc->rh)) { 304 302 usb_log_debug("HC(%p): Scheduling BATCH(%p) for RH(%p)", 305 instance, batch, &instance->rh); 306 return ehci_rh_schedule(&instance->rh, batch); 307 } 303 hc, batch, &hc->rh); 304 return ehci_rh_schedule(&hc->rh, batch); 305 } 306 307 endpoint_t * const ep = batch->ep; 308 ehci_endpoint_t * const ehci_ep = ehci_endpoint_get(ep); 308 309 ehci_transfer_batch_t *ehci_batch = ehci_transfer_batch_get(batch); 309 if (!ehci_batch) 310 return ENOMEM; 311 312 fibril_mutex_lock(&instance->guard); 313 usb_log_debug2("HC(%p): Appending BATCH(%p)", instance, batch); 314 list_append(&ehci_batch->link, &instance->pending_batches); 315 usb_log_debug("HC(%p): Committing BATCH(%p)", instance, batch); 310 311 int err; 312 313 if ((err = ehci_transfer_batch_prepare(ehci_batch))) 314 return err; 315 316 fibril_mutex_lock(&hc->guard); 317 318 if ((err = endpoint_activate_locked(ep, batch))) { 319 fibril_mutex_unlock(&hc->guard); 320 return err; 321 } 322 323 usb_log_debug("HC(%p): Committing BATCH(%p)", hc, batch); 316 324 ehci_transfer_batch_commit(ehci_batch); 317 325 318 fibril_mutex_unlock(&instance->guard); 326 /* Enqueue endpoint to the checked list */ 327 usb_log_debug2("HC(%p): Appending BATCH(%p)", hc, batch); 328 list_append(&ehci_ep->pending_link, &hc->pending_endpoints); 329 330 fibril_mutex_unlock(&hc->guard); 319 331 return EOK; 320 332 } … … 325 337 * @param[in] status Value of the status register at the time of interrupt. 326 338 */ 327 void ehci_hc_interrupt(hcd_t *hcd, uint32_t status) 328 { 329 assert(hcd); 330 hc_t *instance = hcd_get_driver_data(hcd); 331 status = EHCI_RD(status); 332 assert(instance); 333 334 usb_log_debug2("HC(%p): Interrupt: %"PRIx32, instance, status); 339 void ehci_hc_interrupt(bus_t *bus_base, uint32_t status) 340 { 341 assert(bus_base); 342 343 ehci_bus_t *bus = (ehci_bus_t *) bus_base; 344 hc_t *hc = bus->hc; 345 assert(hc); 346 347 usb_log_debug2("HC(%p): Interrupt: %"PRIx32, hc, status); 335 348 if (status & USB_STS_PORT_CHANGE_FLAG) { 336 ehci_rh_interrupt(& instance->rh);349 ehci_rh_interrupt(&hc->rh); 337 350 } 338 351 339 352 if (status & USB_STS_IRQ_ASYNC_ADVANCE_FLAG) { 340 fibril_mutex_lock(& instance->guard);341 usb_log_debug2("HC(%p): Signaling doorbell", instance);342 fibril_condvar_broadcast(& instance->async_doorbell);343 fibril_mutex_unlock(& instance->guard);353 fibril_mutex_lock(&hc->guard); 354 usb_log_debug2("HC(%p): Signaling doorbell", hc); 355 fibril_condvar_broadcast(&hc->async_doorbell); 356 fibril_mutex_unlock(&hc->guard); 344 357 } 345 358 346 359 if (status & (USB_STS_IRQ_FLAG | USB_STS_ERR_IRQ_FLAG)) { 347 fibril_mutex_lock(&instance->guard); 348 349 usb_log_debug2("HC(%p): Scanning %lu pending batches", instance, 350 list_count(&instance->pending_batches)); 351 list_foreach_safe(instance->pending_batches, current, next) { 352 ehci_transfer_batch_t *batch = 353 ehci_transfer_batch_from_link(current); 354 355 if (ehci_transfer_batch_is_complete(batch)) { 360 fibril_mutex_lock(&hc->guard); 361 362 usb_log_debug2("HC(%p): Scanning %lu pending endpoints", hc, 363 list_count(&hc->pending_endpoints)); 364 list_foreach_safe(hc->pending_endpoints, current, next) { 365 ehci_endpoint_t *ep 366 = list_get_instance(current, ehci_endpoint_t, pending_link); 367 368 ehci_transfer_batch_t *batch 369 = ehci_transfer_batch_get(ep->base.active_batch); 370 assert(batch); 371 372 if (ehci_transfer_batch_check_completed(batch)) { 373 endpoint_deactivate_locked(&ep->base); 356 374 list_remove(current); 357 ehci_transfer_batch_finish_dispose(batch); 375 hc_reset_toggles(&batch->base, &ehci_ep_toggle_reset); 376 usb_transfer_batch_finish(&batch->base); 358 377 } 359 378 } 360 fibril_mutex_unlock(&instance->guard); 379 fibril_mutex_unlock(&hc->guard); 380 381 361 382 } 362 383 363 384 if (status & USB_STS_HOST_ERROR_FLAG) { 364 usb_log_fatal("HCD(%p): HOST SYSTEM ERROR!", instance);385 usb_log_fatal("HCD(%p): HOST SYSTEM ERROR!", hc); 365 386 //TODO do something here 366 387 } … … 371 392 * @param[in] instance EHCI hc driver structure. 372 393 */ 373 void hc_start(hc_t *instance) 374 { 375 assert(instance); 394 int hc_start(hc_device_t *hcd) 395 { 396 hc_t *instance = hcd_to_hc(hcd); 397 usb_log_debug("HC(%p): Starting HW.", instance); 398 376 399 /* Turn off the HC if it's running, Reseting a running device is 377 400 * undefined */ … … 404 427 405 428 /* Enable periodic list */ 406 assert(instance->periodic_list _base);429 assert(instance->periodic_list); 407 430 uintptr_t phys_base = 408 addr_to_phys((void*)instance->periodic_list _base);431 addr_to_phys((void*)instance->periodic_list); 409 432 assert((phys_base & USB_PERIODIC_LIST_BASE_MASK) == phys_base); 410 433 EHCI_WR(instance->registers->periodiclistbase, phys_base); … … 425 448 usb_log_debug("HC(%p): HW started.", instance); 426 449 427 usb_log_debug2("HC(%p): Registers: \n"428 "\tUSBCMD(%p): %x(0x00080000 = at least 1ms between interrupts) \n"429 "\tUSBSTS(%p): %x(0x00001000 = HC halted) \n"430 "\tUSBINT(%p): %x(0x0 = no interrupts). \n"431 "\tCONFIG(%p): %x(0x0 = ports controlled by companion hc). \n",450 usb_log_debug2("HC(%p): Registers: " 451 "\tUSBCMD(%p): %x(0x00080000 = at least 1ms between interrupts)" 452 "\tUSBSTS(%p): %x(0x00001000 = HC halted)" 453 "\tUSBINT(%p): %x(0x0 = no interrupts)." 454 "\tCONFIG(%p): %x(0x0 = ports controlled by companion hc).", 432 455 instance, 433 456 &instance->registers->usbcmd, EHCI_RD(instance->registers->usbcmd), … … 438 461 EHCI_WR(instance->registers->usbsts, EHCI_RD(instance->registers->usbsts)); 439 462 EHCI_WR(instance->registers->usbintr, EHCI_USED_INTERRUPTS); 463 464 return EOK; 465 } 466 467 /** 468 * Setup roothub as a virtual hub. 469 */ 470 int hc_setup_roothub(hc_device_t *hcd) 471 { 472 return hc_setup_virtual_root_hub(hcd, USB_SPEED_HIGH); 440 473 } 441 474 … … 473 506 474 507 /* Take 1024 periodic list heads, we ignore low mem options */ 475 instance->periodic_list_base = get_page(); 476 if (!instance->periodic_list_base) { 508 if (dma_buffer_alloc(&instance->dma_buffer, PAGE_SIZE)) { 477 509 usb_log_error("HC(%p): Failed to get ISO schedule page.", 478 510 instance); … … 481 513 return ENOMEM; 482 514 } 515 instance->periodic_list = instance->dma_buffer.virt; 483 516 484 517 usb_log_debug2("HC(%p): Initializing Periodic list.", instance); 485 for (unsigned i = 0; 486 i < PAGE_SIZE/sizeof(instance->periodic_list_base[0]); ++i) 518 for (unsigned i = 0; i < PAGE_SIZE/sizeof(link_pointer_t); ++i) 487 519 { 488 520 /* Disable everything for now */ 489 instance->periodic_list _base[i] =521 instance->periodic_list[i] = 490 522 LINK_POINTER_QH(addr_to_phys(instance->int_list.list_head)); 491 523 }
Note:
See TracChangeset
for help on using the changeset viewer.