Changes in uspace/drv/bus/usb/ehci/hc.c [ddbd088:68e5406] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ehci/hc.c
rddbd088 r68e5406 45 45 #include <usb/debug.h> 46 46 #include <usb/usb.h> 47 #include <usb/host/util ity.h>47 #include <usb/host/utils/malloc32.h> 48 48 49 49 #include "ehci_batch.h" … … 89 89 }; 90 90 91 static void hc_start(hc_t *instance); 91 92 static int hc_init_memory(hc_t *instance); 92 93 … … 95 96 * @param[in] hw_res Device's resources. 96 97 * 98 * @param[out] irq 99 * 97 100 * @return Error code. 98 101 */ 99 int hc_gen_irq_code(irq_code_t *code, hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)102 int ehci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res, int *irq) 100 103 { 101 104 assert(code); 102 105 assert(hw_res); 103 hc_t *instance = hcd_to_hc(hcd);104 106 105 107 if (hw_res->irqs.count != 1 || hw_res->mem_ranges.count != 1) … … 128 130 129 131 memcpy(code->cmds, ehci_irq_commands, sizeof(ehci_irq_commands)); 132 ehci_caps_regs_t *caps = NULL; 133 134 int ret = pio_enable_range(®s, (void**)&caps); 135 if (ret != EOK) { 136 free(code->ranges); 137 free(code->cmds); 138 return ret; 139 } 130 140 131 141 ehci_regs_t *registers = 132 (ehci_regs_t *)(RNGABSPTR(regs) + EHCI_RD8(instance->caps->caplength));142 (ehci_regs_t *)(RNGABSPTR(regs) + EHCI_RD8(caps->caplength)); 133 143 code->cmds[0].addr = (void *) ®isters->usbsts; 134 144 code->cmds[3].addr = (void *) ®isters->usbsts; 135 145 EHCI_WR(code->cmds[1].value, EHCI_USED_INTERRUPTS); 136 146 137 usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d. ",147 usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n", 138 148 RNGABSPTR(regs), RNGSZ(regs), hw_res->irqs.irqs[0]); 139 149 140 return hw_res->irqs.irqs[0]; 150 *irq = hw_res->irqs.irqs[0]; 151 return EOK; 141 152 } 142 153 … … 148 159 * @return Error code 149 160 */ 150 int hc_ add(hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)151 { 152 hc_t *instance = hcd_to_hc(hcd);161 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts) 162 { 163 assert(instance); 153 164 assert(hw_res); 154 165 if (hw_res->mem_ranges.count != 1 || … … 161 172 if (ret != EOK) { 162 173 usb_log_error("HC(%p): Failed to gain access to device " 163 "registers: %s. ", instance, str_error(ret));174 "registers: %s.\n", instance, str_error(ret)); 164 175 return ret; 165 176 } 166 167 177 usb_log_info("HC(%p): Device registers at %"PRIx64" (%zuB) accessible.", 168 178 instance, hw_res->mem_ranges.ranges[0].address.absolute, … … 174 184 + EHCI_RD8(instance->caps->caplength)); 175 185 176 list_initialize(&instance->pending_ endpoints);186 list_initialize(&instance->pending_batches); 177 187 fibril_mutex_initialize(&instance->guard); 178 188 fibril_condvar_initialize(&instance->async_doorbell); … … 187 197 usb_log_info("HC(%p): Initializing RH(%p).", instance, &instance->rh); 188 198 ehci_rh_init( 189 &instance->rh, instance->caps, instance->registers, &instance->guard, 190 "ehci rh"); 191 192 ehci_bus_init(&instance->bus, instance); 193 hc_device_setup(hcd, (bus_t *) &instance->bus); 199 &instance->rh, instance->caps, instance->registers, "ehci rh"); 200 usb_log_debug("HC(%p): Starting HW.", instance); 201 hc_start(instance); 202 194 203 return EOK; 195 204 } … … 199 208 * @param[in] instance Host controller structure to use. 200 209 */ 201 int hc_gone(hc_device_t *hcd) 202 { 203 hc_t *hc = hcd_to_hc(hcd); 204 endpoint_list_fini(&hc->async_list); 205 endpoint_list_fini(&hc->int_list); 206 dma_buffer_free(&hc->dma_buffer); 207 return EOK; 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 208 219 }; 209 220 … … 213 224 assert(ep); 214 225 ehci_endpoint_t *ehci_ep = ehci_endpoint_get(ep); 215 usb_log_debug("HC(%p) enqueue EP(%d:%d:%s:%s) ", instance,216 ep-> device->address, ep->endpoint,226 usb_log_debug("HC(%p) enqueue EP(%d:%d:%s:%s)\n", instance, 227 ep->address, ep->endpoint, 217 228 usb_str_transfer_type_short(ep->transfer_type), 218 229 usb_str_direction(ep->direction)); … … 237 248 assert(ep); 238 249 ehci_endpoint_t *ehci_ep = ehci_endpoint_get(ep); 239 usb_log_debug("HC(%p) dequeue EP(%d:%d:%s:%s) ", instance,240 ep-> device->address, ep->endpoint,250 usb_log_debug("HC(%p) dequeue EP(%d:%d:%s:%s)\n", instance, 251 ep->address, ep->endpoint, 241 252 usb_str_transfer_type_short(ep->transfer_type), 242 253 usb_str_direction(ep->direction)); … … 262 273 } 263 274 264 int ehci_hc_status(bus_t *bus_base, uint32_t *status) 265 { 266 assert(bus_base); 275 int 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); 267 280 assert(status); 268 269 ehci_bus_t *bus = (ehci_bus_t *) bus_base;270 hc_t *hc = bus->hc;271 assert(hc);272 273 281 *status = 0; 274 if ( hc->registers) {275 *status = EHCI_RD( hc->registers->usbsts);276 EHCI_WR( hc->registers->usbsts, *status);277 } 278 usb_log_debug2("HC(%p): Read status: %x", hc, *status);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); 279 287 return EOK; 280 288 } … … 286 294 * @return Error code. 287 295 */ 288 int ehci_hc_schedule(usb_transfer_batch_t *batch) 289 { 290 assert(batch); 291 292 ehci_bus_t *bus = (ehci_bus_t *) endpoint_get_bus(batch->ep); 293 hc_t *hc = bus->hc; 294 assert(hc); 296 int 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); 295 301 296 302 /* Check for root hub communication */ 297 if (batch-> target.address == ehci_rh_get_address(&hc->rh)) {303 if (batch->ep->address == ehci_rh_get_address(&instance->rh)) { 298 304 usb_log_debug("HC(%p): Scheduling BATCH(%p) for RH(%p)", 299 hc, batch, &hc->rh); 300 return ehci_rh_schedule(&hc->rh, batch); 301 } 302 303 endpoint_t * const ep = batch->ep; 304 ehci_endpoint_t * const ehci_ep = ehci_endpoint_get(ep); 305 instance, batch, &instance->rh); 306 return ehci_rh_schedule(&instance->rh, batch); 307 } 305 308 ehci_transfer_batch_t *ehci_batch = ehci_transfer_batch_get(batch); 306 307 int err; 308 309 if ((err = ehci_transfer_batch_prepare(ehci_batch))) 310 return err; 311 312 fibril_mutex_lock(&hc->guard); 313 314 if ((err = endpoint_activate_locked(ep, batch))) { 315 fibril_mutex_unlock(&hc->guard); 316 return err; 317 } 318 319 usb_log_debug("HC(%p): Committing BATCH(%p)", hc, 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); 320 316 ehci_transfer_batch_commit(ehci_batch); 321 317 322 /* Enqueue endpoint to the checked list */ 323 usb_log_debug2("HC(%p): Appending BATCH(%p)", hc, batch); 324 list_append(&ehci_ep->pending_link, &hc->pending_endpoints); 325 326 fibril_mutex_unlock(&hc->guard); 318 fibril_mutex_unlock(&instance->guard); 327 319 return EOK; 328 320 } … … 333 325 * @param[in] status Value of the status register at the time of interrupt. 334 326 */ 335 void ehci_hc_interrupt(bus_t *bus_base, uint32_t status) 336 { 337 assert(bus_base); 338 339 ehci_bus_t *bus = (ehci_bus_t *) bus_base; 340 hc_t *hc = bus->hc; 341 assert(hc); 342 343 usb_log_debug2("HC(%p): Interrupt: %"PRIx32, hc, status); 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); 344 335 if (status & USB_STS_PORT_CHANGE_FLAG) { 345 ehci_rh_interrupt(& hc->rh);336 ehci_rh_interrupt(&instance->rh); 346 337 } 347 338 348 339 if (status & USB_STS_IRQ_ASYNC_ADVANCE_FLAG) { 349 fibril_mutex_lock(& hc->guard);350 usb_log_debug2("HC(%p): Signaling doorbell", hc);351 fibril_condvar_broadcast(& hc->async_doorbell);352 fibril_mutex_unlock(& hc->guard);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 344 } 354 345 355 346 if (status & (USB_STS_IRQ_FLAG | USB_STS_ERR_IRQ_FLAG)) { 356 fibril_mutex_lock(&hc->guard); 357 358 usb_log_debug2("HC(%p): Scanning %lu pending endpoints", hc, 359 list_count(&hc->pending_endpoints)); 360 list_foreach_safe(hc->pending_endpoints, current, next) { 361 ehci_endpoint_t *ep 362 = list_get_instance(current, ehci_endpoint_t, pending_link); 363 364 ehci_transfer_batch_t *batch 365 = ehci_transfer_batch_get(ep->base.active_batch); 366 assert(batch); 367 368 if (ehci_transfer_batch_check_completed(batch)) { 369 endpoint_deactivate_locked(&ep->base); 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)) { 370 356 list_remove(current); 371 hc_reset_toggles(&batch->base, &ehci_ep_toggle_reset); 372 usb_transfer_batch_finish(&batch->base); 357 ehci_transfer_batch_finish_dispose(batch); 373 358 } 374 359 } 375 fibril_mutex_unlock(&hc->guard); 376 377 360 fibril_mutex_unlock(&instance->guard); 378 361 } 379 362 380 363 if (status & USB_STS_HOST_ERROR_FLAG) { 381 usb_log_fatal("HCD(%p): HOST SYSTEM ERROR!", hc);364 usb_log_fatal("HCD(%p): HOST SYSTEM ERROR!", instance); 382 365 //TODO do something here 383 366 } … … 388 371 * @param[in] instance EHCI hc driver structure. 389 372 */ 390 int hc_start(hc_device_t *hcd) 391 { 392 hc_t *instance = hcd_to_hc(hcd); 393 usb_log_debug("HC(%p): Starting HW.", instance); 394 373 void hc_start(hc_t *instance) 374 { 375 assert(instance); 395 376 /* Turn off the HC if it's running, Reseting a running device is 396 377 * undefined */ … … 423 404 424 405 /* Enable periodic list */ 425 assert(instance->periodic_list );406 assert(instance->periodic_list_base); 426 407 uintptr_t phys_base = 427 addr_to_phys((void*)instance->periodic_list );408 addr_to_phys((void*)instance->periodic_list_base); 428 409 assert((phys_base & USB_PERIODIC_LIST_BASE_MASK) == phys_base); 429 410 EHCI_WR(instance->registers->periodiclistbase, phys_base); … … 444 425 usb_log_debug("HC(%p): HW started.", instance); 445 426 446 usb_log_debug2("HC(%p): Registers: "447 "\tUSBCMD(%p): %x(0x00080000 = at least 1ms between interrupts) "448 "\tUSBSTS(%p): %x(0x00001000 = HC halted) "449 "\tUSBINT(%p): %x(0x0 = no interrupts). "450 "\tCONFIG(%p): %x(0x0 = ports controlled by companion hc). ",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", 451 432 instance, 452 433 &instance->registers->usbcmd, EHCI_RD(instance->registers->usbcmd), … … 457 438 EHCI_WR(instance->registers->usbsts, EHCI_RD(instance->registers->usbsts)); 458 439 EHCI_WR(instance->registers->usbintr, EHCI_USED_INTERRUPTS); 459 460 return EOK;461 }462 463 /**464 * Setup roothub as a virtual hub.465 */466 int hc_setup_roothub(hc_device_t *hcd)467 {468 return hc_setup_virtual_root_hub(hcd, USB_SPEED_HIGH);469 440 } 470 441 … … 502 473 503 474 /* Take 1024 periodic list heads, we ignore low mem options */ 504 if (dma_buffer_alloc(&instance->dma_buffer, PAGE_SIZE)) { 475 instance->periodic_list_base = get_page(); 476 if (!instance->periodic_list_base) { 505 477 usb_log_error("HC(%p): Failed to get ISO schedule page.", 506 478 instance); … … 509 481 return ENOMEM; 510 482 } 511 instance->periodic_list = instance->dma_buffer.virt;512 483 513 484 usb_log_debug2("HC(%p): Initializing Periodic list.", instance); 514 for (unsigned i = 0; i < PAGE_SIZE/sizeof(link_pointer_t); ++i) 485 for (unsigned i = 0; 486 i < PAGE_SIZE/sizeof(instance->periodic_list_base[0]); ++i) 515 487 { 516 488 /* Disable everything for now */ 517 instance->periodic_list [i] =489 instance->periodic_list_base[i] = 518 490 LINK_POINTER_QH(addr_to_phys(instance->int_list.list_head)); 519 491 }
Note:
See TracChangeset
for help on using the changeset viewer.