Changeset 32fb6bce in mainline
- Timestamp:
- 2017-12-18T22:50:21Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 7f70d1c
- Parents:
- 1ea0bbf
- git-author:
- Ondřej Hlavatý <aearsis@…> (2017-12-18 22:04:50)
- git-committer:
- Ondřej Hlavatý <aearsis@…> (2017-12-18 22:50:21)
- Location:
- uspace
- Files:
-
- 33 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ehci/ehci_bus.c
r1ea0bbf r32fb6bce 162 162 .parent = &usb2_bus_ops, 163 163 164 .interrupt = ehci_hc_interrupt, 165 .status = ehci_hc_status, 164 166 .endpoint_destroy = ehci_endpoint_destroy, 165 167 .endpoint_create = ehci_endpoint_create, … … 171 173 .batch_create = ehci_create_batch, 172 174 .batch_destroy = ehci_destroy_batch, 175 .batch_schedule = ehci_hc_schedule, 173 176 }; 174 177 175 int ehci_bus_init(ehci_bus_t *bus, hc d_t *hcd, hc_t *hc)178 int ehci_bus_init(ehci_bus_t *bus, hc_t *hc) 176 179 { 177 180 assert(hc); … … 181 184 bus_t *bus_base = (bus_t *) bus; 182 185 183 usb2_bus_init(usb2_bus, hcd,BANDWIDTH_AVAILABLE_USB11);186 usb2_bus_init(usb2_bus, BANDWIDTH_AVAILABLE_USB11); 184 187 bus_base->ops = &ehci_bus_ops; 185 188 -
uspace/drv/bus/usb/ehci/ehci_bus.h
r1ea0bbf r32fb6bce 63 63 void ehci_bus_prepare_ops(void); 64 64 65 int ehci_bus_init(ehci_bus_t *, hc d_t *, hc_t *);65 int ehci_bus_init(ehci_bus_t *, hc_t *); 66 66 67 67 /** Get and convert assigned ehci_endpoint_t structure 68 68 * @param[in] ep USBD endpoint structure. 69 * @return Pointer to assigned hcdendpoint structure69 * @return Pointer to assigned ehci endpoint structure 70 70 */ 71 71 static inline ehci_endpoint_t * ehci_endpoint_get(const endpoint_t *ep) -
uspace/drv/bus/usb/ehci/hc.c
r1ea0bbf r32fb6bce 97 97 * @return Error code. 98 98 */ 99 int ehci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)99 int hc_gen_irq_code(irq_code_t *code, hc_device_t *hcd, const hw_res_list_parsed_t *hw_res) 100 100 { 101 101 assert(code); 102 102 assert(hw_res); 103 104 hc_t *instance = hcd_get_driver_data(hcd); 103 hc_t *instance = hcd_to_hc(hcd); 105 104 106 105 if (hw_res->irqs.count != 1 || hw_res->mem_ranges.count != 1) … … 149 148 * @return Error code 150 149 */ 151 int hc_ init(hc_t *instance, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)152 { 153 assert(instance);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); 154 153 assert(hw_res); 155 154 if (hw_res->mem_ranges.count != 1 || … … 190 189 &instance->rh, instance->caps, instance->registers, "ehci rh"); 191 190 192 ehci_bus_init(&instance->bus, hcd, instance); 191 ehci_bus_init(&instance->bus, instance); 192 hc_device_setup(hcd, (bus_t *) &instance->bus); 193 193 return EOK; 194 194 } … … 198 198 * @param[in] instance Host controller structure to use. 199 199 */ 200 void hc_fini(hc_t *instance)200 int hc_gone(hc_device_t *instance) 201 201 { 202 202 assert(instance); 203 return EOK; 203 204 //TODO: stop the hw 204 205 #if 0 … … 263 264 } 264 265 265 int ehci_hc_status(hcd_t *hcd, uint32_t *status) 266 { 267 assert(hcd); 268 hc_t *instance = hcd_get_driver_data(hcd); 269 assert(instance); 266 int ehci_hc_status(bus_t *bus_base, uint32_t *status) 267 { 268 assert(bus_base); 270 269 assert(status); 270 271 ehci_bus_t *bus = (ehci_bus_t *) bus_base; 272 hc_t *hc = bus->hc; 273 assert(hc); 274 271 275 *status = 0; 272 if ( instance->registers) {273 *status = EHCI_RD( instance->registers->usbsts);274 EHCI_WR( instance->registers->usbsts, *status);275 } 276 usb_log_debug2("HC(%p): Read status: %x", instance, *status);276 if (hc->registers) { 277 *status = EHCI_RD(hc->registers->usbsts); 278 EHCI_WR(hc->registers->usbsts, *status); 279 } 280 usb_log_debug2("HC(%p): Read status: %x", hc, *status); 277 281 return EOK; 278 282 } … … 284 288 * @return Error code. 285 289 */ 286 int ehci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch) 287 { 288 assert(hcd); 289 hc_t *instance = hcd_get_driver_data(hcd); 290 assert(instance); 290 int ehci_hc_schedule(usb_transfer_batch_t *batch) 291 { 292 assert(batch); 293 294 ehci_bus_t *bus = (ehci_bus_t *) endpoint_get_bus(batch->ep); 295 hc_t *hc = bus->hc; 296 assert(hc); 291 297 292 298 /* Check for root hub communication */ 293 if (batch->target.address == ehci_rh_get_address(& instance->rh)) {299 if (batch->target.address == ehci_rh_get_address(&hc->rh)) { 294 300 usb_log_debug("HC(%p): Scheduling BATCH(%p) for RH(%p)", 295 instance, batch, &instance->rh);296 return ehci_rh_schedule(& instance->rh, batch);301 hc, batch, &hc->rh); 302 return ehci_rh_schedule(&hc->rh, batch); 297 303 } 298 304 … … 303 309 return err; 304 310 305 fibril_mutex_lock(& instance->guard);306 usb_log_debug2("HC(%p): Appending BATCH(%p)", instance, batch);307 list_append(&ehci_batch->link, & instance->pending_batches);308 usb_log_debug("HC(%p): Committing BATCH(%p)", instance, batch);311 fibril_mutex_lock(&hc->guard); 312 usb_log_debug2("HC(%p): Appending BATCH(%p)", hc, batch); 313 list_append(&ehci_batch->link, &hc->pending_batches); 314 usb_log_debug("HC(%p): Committing BATCH(%p)", hc, batch); 309 315 ehci_transfer_batch_commit(ehci_batch); 310 316 311 fibril_mutex_unlock(& instance->guard);317 fibril_mutex_unlock(&hc->guard); 312 318 return EOK; 313 319 } … … 318 324 * @param[in] status Value of the status register at the time of interrupt. 319 325 */ 320 void ehci_hc_interrupt(hcd_t *hcd, uint32_t status) 321 { 322 assert(hcd); 323 hc_t *instance = hcd_get_driver_data(hcd); 324 status = EHCI_RD(status); 325 assert(instance); 326 327 usb_log_debug2("HC(%p): Interrupt: %"PRIx32, instance, status); 326 void ehci_hc_interrupt(bus_t *bus_base, uint32_t status) 327 { 328 assert(bus_base); 329 330 ehci_bus_t *bus = (ehci_bus_t *) bus_base; 331 hc_t *hc = bus->hc; 332 assert(hc); 333 334 usb_log_debug2("HC(%p): Interrupt: %"PRIx32, hc, status); 328 335 if (status & USB_STS_PORT_CHANGE_FLAG) { 329 ehci_rh_interrupt(& instance->rh);336 ehci_rh_interrupt(&hc->rh); 330 337 } 331 338 332 339 if (status & USB_STS_IRQ_ASYNC_ADVANCE_FLAG) { 333 fibril_mutex_lock(& instance->guard);334 usb_log_debug2("HC(%p): Signaling doorbell", instance);335 fibril_condvar_broadcast(& instance->async_doorbell);336 fibril_mutex_unlock(& instance->guard);340 fibril_mutex_lock(&hc->guard); 341 usb_log_debug2("HC(%p): Signaling doorbell", hc); 342 fibril_condvar_broadcast(&hc->async_doorbell); 343 fibril_mutex_unlock(&hc->guard); 337 344 } 338 345 339 346 if (status & (USB_STS_IRQ_FLAG | USB_STS_ERR_IRQ_FLAG)) { 340 fibril_mutex_lock(& instance->guard);341 342 usb_log_debug2("HC(%p): Scanning %lu pending batches", instance,343 list_count(& instance->pending_batches));344 list_foreach_safe( instance->pending_batches, current, next) {347 fibril_mutex_lock(&hc->guard); 348 349 usb_log_debug2("HC(%p): Scanning %lu pending batches", hc, 350 list_count(&hc->pending_batches)); 351 list_foreach_safe(hc->pending_batches, current, next) { 345 352 ehci_transfer_batch_t *batch = 346 353 ehci_transfer_batch_from_link(current); … … 351 358 } 352 359 } 353 fibril_mutex_unlock(& instance->guard);360 fibril_mutex_unlock(&hc->guard); 354 361 } 355 362 356 363 if (status & USB_STS_HOST_ERROR_FLAG) { 357 usb_log_fatal("HCD(%p): HOST SYSTEM ERROR!", instance);364 usb_log_fatal("HCD(%p): HOST SYSTEM ERROR!", hc); 358 365 //TODO do something here 359 366 } … … 364 371 * @param[in] instance EHCI hc driver structure. 365 372 */ 366 int hc_start(hc_ t *instance, bool interrupts)367 { 368 assert(instance);373 int hc_start(hc_device_t *hcd) 374 { 375 hc_t *instance = hcd_to_hc(hcd); 369 376 usb_log_debug("HC(%p): Starting HW.", instance); 370 377 -
uspace/drv/bus/usb/ehci/hc.h
r1ea0bbf r32fb6bce 55 55 /** Main EHCI driver structure */ 56 56 typedef struct hc { 57 /* Common device header */ 58 hc_device_t base; 59 57 60 /** Memory mapped CAPS register area */ 58 61 ehci_caps_regs_t *caps; … … 85 88 } hc_t; 86 89 87 int hc_init(hc_t *instance, hcd_t *hcd, const hw_res_list_parsed_t *hw_res); 88 int hc_start(hc_t *instance, bool interrupts); 89 void hc_fini(hc_t *instance); 90 static inline hc_t *hcd_to_hc(hc_device_t *hcd) 91 { 92 assert(hcd); 93 return (hc_t *) hcd; 94 } 90 95 91 void hc_enqueue_endpoint(hc_t * instance, const endpoint_t *ep);92 void hc_dequeue_endpoint(hc_t * instance, const endpoint_t *ep);96 void hc_enqueue_endpoint(hc_t *, const endpoint_t *); 97 void hc_dequeue_endpoint(hc_t *, const endpoint_t *); 93 98 94 int ehci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res); 99 /* Boottime operations */ 100 int hc_add(hc_device_t *, const hw_res_list_parsed_t *); 101 int hc_start(hc_device_t *); 102 int hc_gen_irq_code(irq_code_t *, hc_device_t *, const hw_res_list_parsed_t *); 103 int hc_gone(hc_device_t *); 95 104 96 void ehci_hc_interrupt(hcd_t *hcd, uint32_t status); 97 int ehci_hc_status(hcd_t *hcd, uint32_t *status); 98 int ehci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch); 105 /** Runtime operations */ 106 void ehci_hc_interrupt(bus_t *, uint32_t); 107 int ehci_hc_status(bus_t *, uint32_t *); 108 int ehci_hc_schedule(usb_transfer_batch_t *); 109 99 110 #endif 100 111 /** -
uspace/drv/bus/usb/ehci/main.c
r1ea0bbf r32fb6bce 35 35 */ 36 36 37 #include <ddf/driver.h>38 #include <ddf/interrupt.h>39 #include <device/hw_res.h>40 #include <errno.h>41 #include <str_error.h>42 37 #include <io/logctl.h> 43 44 #include <usb_iface.h> 45 #include <usb/debug.h> 38 #include <usb/host/hcd.h> 46 39 #include <usb/host/ddf_helpers.h> 47 40 … … 51 44 #define NAME "ehci" 52 45 53 static int ehci_driver_init(hcd_t *, const hw_res_list_parsed_t *, ddf_dev_t *); 54 static int ehci_driver_claim(hcd_t *, ddf_dev_t *); 55 static int ehci_driver_start(hcd_t *, bool); 56 static void ehci_driver_fini(hcd_t *); 46 static const hc_driver_t ehci_driver = { 47 .name = NAME, 48 .hc_device_size = sizeof(hc_t), 57 49 58 static const ddf_hc_driver_t ehci_hc_driver = { 59 .name = "EHCI-PCI", 60 .init = ehci_driver_init, 61 .irq_code_gen = ehci_hc_gen_irq_code, 62 .claim = ehci_driver_claim, 63 .start = ehci_driver_start, 50 .hc_add = hc_add, 51 .irq_code_gen = hc_gen_irq_code, 52 .claim = disable_legacy, 53 .start = hc_start, 64 54 .setup_root_hub = hcd_setup_virtual_root_hub, 65 .fini = ehci_driver_fini, 66 .ops = { 67 .schedule = ehci_hc_schedule, 68 .irq_hook = ehci_hc_interrupt, 69 .status_hook = ehci_hc_status, 70 } 55 .hc_gone = hc_gone, 71 56 }; 72 73 74 static int ehci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, ddf_dev_t *device)75 {76 assert(hcd);77 assert(hcd_get_driver_data(hcd) == NULL);78 79 hc_t *instance = malloc(sizeof(hc_t));80 if (!instance)81 return ENOMEM;82 83 const int ret = hc_init(instance, hcd, res);84 if (ret == EOK) {85 hcd_set_implementation(hcd, instance, &ehci_hc_driver.ops, &instance->bus.base.base);86 } else {87 free(instance);88 }89 return ret;90 }91 92 static int ehci_driver_claim(hcd_t *hcd, ddf_dev_t *dev)93 {94 hc_t *instance = hcd_get_driver_data(hcd);95 assert(instance);96 97 return disable_legacy(instance, dev);98 }99 100 static int ehci_driver_start(hcd_t *hcd, bool irq) {101 hc_t *instance = hcd_get_driver_data(hcd);102 assert(instance);103 104 return hc_start(instance, irq);105 }106 107 static void ehci_driver_fini(hcd_t *hcd)108 {109 assert(hcd);110 hc_t *hc = hcd_get_driver_data(hcd);111 if (hc)112 hc_fini(hc);113 114 free(hc);115 hcd_set_implementation(hcd, NULL, NULL, NULL);116 }117 118 /** Initializes a new ddf driver instance of EHCI hcd.119 *120 * @param[in] device DDF instance of the device to initialize.121 * @return Error code.122 */123 static int ehci_dev_add(ddf_dev_t *device)124 {125 usb_log_debug("ehci_dev_add() called\n");126 assert(device);127 128 return hcd_ddf_add_hc(device, &ehci_hc_driver);129 130 }131 132 static int ehci_fun_online(ddf_fun_t *fun)133 {134 return hcd_ddf_device_online(fun);135 }136 137 static int ehci_fun_offline(ddf_fun_t *fun)138 {139 return hcd_ddf_device_offline(fun);140 }141 142 143 static const driver_ops_t ehci_driver_ops = {144 .dev_add = ehci_dev_add,145 .fun_online = ehci_fun_online,146 .fun_offline = ehci_fun_offline147 };148 149 static const driver_t ehci_driver = {150 .name = NAME,151 .driver_ops = &ehci_driver_ops152 };153 154 57 155 58 /** Initializes global driver structures (NONE). … … 165 68 log_init(NAME); 166 69 logctl_set_log_level(NAME, LVL_NOTE); 167 return ddf_driver_main(&ehci_driver);70 return hc_driver_main(&ehci_driver); 168 71 } 169 72 -
uspace/drv/bus/usb/ehci/res.c
r1ea0bbf r32fb6bce 45 45 #include <pci_dev_iface.h> 46 46 47 #include "hc.h" 47 48 #include "res.h" 48 49 #include "ehci_regs.h" … … 172 173 } 173 174 174 int disable_legacy(hc_ t *hc, ddf_dev_t *device)175 int disable_legacy(hc_device_t *hcd) 175 176 { 176 assert(device);177 178 async_sess_t *parent_sess = ddf_dev_parent_sess_get( device);177 hc_t *hc = hcd_to_hc(hcd); 178 179 async_sess_t *parent_sess = ddf_dev_parent_sess_get(hcd->ddf_dev); 179 180 if (parent_sess == NULL) 180 181 return ENOMEM; -
uspace/drv/bus/usb/ehci/res.h
r1ea0bbf r32fb6bce 36 36 #define DRV_EHCI_PCI_H 37 37 38 #include <ddf/driver.h> 39 #include <device/hw_res_parsed.h> 38 typedef struct hc_device hc_device_t; 40 39 41 #include "hc.h" 42 43 extern int disable_legacy(hc_t *, ddf_dev_t *); 40 extern int disable_legacy(hc_device_t *); 44 41 45 42 #endif -
uspace/drv/bus/usb/ohci/hc.c
r1ea0bbf r32fb6bce 101 101 * @return Error code. 102 102 */ 103 int ohci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)103 int hc_gen_irq_code(irq_code_t *code, hc_device_t *hcd, const hw_res_list_parsed_t *hw_res) 104 104 { 105 105 assert(code); … … 149 149 * @return Error code 150 150 */ 151 int hc_ init(hc_t *instance, const hw_res_list_parsed_t *hw_res)152 { 153 assert(instance);151 int hc_add(hc_device_t *hcd, const hw_res_list_parsed_t *hw_res) 152 { 153 hc_t *instance = hcd_to_hc(hcd); 154 154 assert(hw_res); 155 155 if (hw_res->mem_ranges.count != 1 || … … 186 186 * @param[in] instance Host controller structure to use. 187 187 */ 188 void hc_fini(hc_t *instance)188 int hc_gone(hc_device_t *instance) 189 189 { 190 190 assert(instance); 191 191 /* TODO: implement*/ 192 }; 192 return ENOTSUP; 193 } 193 194 194 195 void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep) … … 260 261 } 261 262 262 int ohci_hc_status( hcd_t *hcd, uint32_t *status)263 { 264 assert( hcd);263 int ohci_hc_status(bus_t *bus_base, uint32_t *status) 264 { 265 assert(bus_base); 265 266 assert(status); 266 hc_t *instance = hcd_get_driver_data(hcd); 267 assert(instance); 268 269 if (instance->registers){ 270 *status = OHCI_RD(instance->registers->interrupt_status); 271 OHCI_WR(instance->registers->interrupt_status, *status); 267 268 ohci_bus_t *bus = (ohci_bus_t *) bus_base; 269 hc_t *hc = bus->hc; 270 assert(hc); 271 272 if (hc->registers){ 273 *status = OHCI_RD(hc->registers->interrupt_status); 274 OHCI_WR(hc->registers->interrupt_status, *status); 272 275 } 273 276 return EOK; … … 280 283 * @return Error code. 281 284 */ 282 int ohci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch) 283 { 284 assert(hcd); 285 hc_t *instance = hcd_get_driver_data(hcd); 286 assert(instance); 285 int ohci_hc_schedule(usb_transfer_batch_t *batch) 286 { 287 assert(batch); 288 289 ohci_bus_t *bus = (ohci_bus_t *) endpoint_get_bus(batch->ep); 290 hc_t *hc = bus->hc; 291 assert(hc); 287 292 288 293 /* Check for root hub communication */ 289 if (batch->target.address == ohci_rh_get_address(& instance->rh)) {294 if (batch->target.address == ohci_rh_get_address(&hc->rh)) { 290 295 usb_log_debug("OHCI root hub request.\n"); 291 return ohci_rh_schedule(& instance->rh, batch);296 return ohci_rh_schedule(&hc->rh, batch); 292 297 } 293 298 ohci_transfer_batch_t *ohci_batch = ohci_transfer_batch_get(batch); … … 299 304 return err; 300 305 301 fibril_mutex_lock(& instance->guard);302 list_append(&ohci_batch->link, & instance->pending_batches);306 fibril_mutex_lock(&hc->guard); 307 list_append(&ohci_batch->link, &hc->pending_batches); 303 308 ohci_transfer_batch_commit(ohci_batch); 304 309 … … 307 312 { 308 313 case USB_TRANSFER_CONTROL: 309 OHCI_SET( instance->registers->command_status, CS_CLF);314 OHCI_SET(hc->registers->command_status, CS_CLF); 310 315 break; 311 316 case USB_TRANSFER_BULK: 312 OHCI_SET( instance->registers->command_status, CS_BLF);317 OHCI_SET(hc->registers->command_status, CS_BLF); 313 318 break; 314 319 default: 315 320 break; 316 321 } 317 fibril_mutex_unlock(& instance->guard);322 fibril_mutex_unlock(&hc->guard); 318 323 return EOK; 319 324 } … … 324 329 * @param[in] status Value of the status register at the time of interrupt. 325 330 */ 326 void ohci_hc_interrupt(hcd_t *hcd, uint32_t status) 327 { 328 assert(hcd); 329 hc_t *instance = hcd_get_driver_data(hcd); 331 void ohci_hc_interrupt(bus_t *bus_base, uint32_t status) 332 { 333 assert(bus_base); 334 335 ohci_bus_t *bus = (ohci_bus_t *) bus_base; 336 hc_t *hc = bus->hc; 337 assert(hc); 338 330 339 status = OHCI_RD(status); 331 assert( instance);340 assert(hc); 332 341 if ((status & ~I_SF) == 0) /* ignore sof status */ 333 342 return; 334 usb_log_debug2("OHCI(%p) interrupt: %x.\n", instance, status);343 usb_log_debug2("OHCI(%p) interrupt: %x.\n", hc, status); 335 344 if (status & I_RHSC) 336 ohci_rh_interrupt(& instance->rh);345 ohci_rh_interrupt(&hc->rh); 337 346 338 347 if (status & I_WDH) { 339 fibril_mutex_lock(& instance->guard);340 usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca,341 OHCI_RD( instance->registers->hcca),342 (void *) addr_to_phys( instance->hcca));348 fibril_mutex_lock(&hc->guard); 349 usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", hc->hcca, 350 OHCI_RD(hc->registers->hcca), 351 (void *) addr_to_phys(hc->hcca)); 343 352 usb_log_debug2("Periodic current: %#" PRIx32 ".\n", 344 OHCI_RD( instance->registers->periodic_current));345 346 link_t *current = list_first(& instance->pending_batches);347 while (current && current != & instance->pending_batches.head) {353 OHCI_RD(hc->registers->periodic_current)); 354 355 link_t *current = list_first(&hc->pending_batches); 356 while (current && current != &hc->pending_batches.head) { 348 357 link_t *next = current->next; 349 358 ohci_transfer_batch_t *batch = … … 357 366 current = next; 358 367 } 359 fibril_mutex_unlock(& instance->guard);368 fibril_mutex_unlock(&hc->guard); 360 369 } 361 370 362 371 if (status & I_UE) { 363 372 usb_log_fatal("Error like no other!\n"); 364 hc_start( instance);373 hc_start(&hc->base); 365 374 } 366 375 … … 374 383 * @param[in] instance OHCI hc driver structure. 375 384 */ 376 void hc_gain_control(hc_t *instance)377 { 378 assert(instance);385 int hc_gain_control(hc_device_t *hcd) 386 { 387 hc_t *instance = hcd_to_hc(hcd); 379 388 380 389 usb_log_debug("Requesting OHCI control.\n"); … … 409 418 C_HCFS_SET(instance->registers->control, C_HCFS_RESET); 410 419 async_usleep(50000); 411 return ;420 return EOK; 412 421 } 413 422 … … 418 427 if (hc_status == C_HCFS_OPERATIONAL) { 419 428 usb_log_info("BIOS driver: HC operational.\n"); 420 return ;429 return EOK; 421 430 } 422 431 /* HC is suspended assert resume for 20ms */ … … 424 433 async_usleep(20000); 425 434 usb_log_info("BIOS driver: HC resumed.\n"); 426 return ;435 return EOK; 427 436 } 428 437 … … 431 440 usb_log_debug("Host controller found in reset state.\n"); 432 441 async_usleep(50000); 442 return EOK; 433 443 } 434 444 … … 437 447 * @param[in] instance OHCI hc driver structure. 438 448 */ 439 void hc_start(hc_t *instance) 440 { 449 int hc_start(hc_device_t *hcd) 450 { 451 hc_t *instance = hcd_to_hc(hcd); 441 452 ohci_rh_init(&instance->rh, instance->registers, "ohci rh"); 442 453 … … 489 500 490 501 /* Enable interrupts */ 491 if (instance-> hw_interrupts) {502 if (instance->base.irq_cap >= 0) { 492 503 OHCI_WR(instance->registers->interrupt_enable, 493 504 OHCI_USED_INTERRUPTS); … … 508 519 usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n", 509 520 OHCI_RD(instance->registers->control)); 521 522 return EOK; 510 523 } 511 524 … … 555 568 memset(&instance->rh, 0, sizeof(instance->rh)); 556 569 /* Init queues */ 557 constint ret = hc_init_transfer_lists(instance);570 int ret = hc_init_transfer_lists(instance); 558 571 if (ret != EOK) { 559 572 return ret; … … 574 587 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa); 575 588 589 if ((ret = ohci_bus_init(&instance->bus, instance))) { 590 usb_log_error("HC(%p): Failed to setup bus : %s", 591 instance, str_error(ret)); 592 return ret; 593 } 594 595 hc_device_setup(&instance->base, (bus_t *) &instance->bus); 596 576 597 return EOK; 577 598 } -
uspace/drv/bus/usb/ohci/hc.h
r1ea0bbf r32fb6bce 58 58 /** Main OHCI driver structure */ 59 59 typedef struct hc { 60 /** Common hcd header */ 61 hc_device_t base; 62 60 63 /** Memory mapped I/O registers area */ 61 64 ohci_regs_t *registers; … … 70 73 list_t pending_batches; 71 74 72 /** Fibril for periodic checks if interrupts can't be used */73 fid_t interrupt_emulator;74 75 75 /** Guards schedule and endpoint manipulation */ 76 76 fibril_mutex_t guard; 77 78 /** interrupts available */79 bool hw_interrupts;80 77 81 78 /** USB hub emulation structure */ … … 86 83 } hc_t; 87 84 88 extern int hc_init(hc_t *, const hw_res_list_parsed_t *); 89 extern void hc_gain_control(hc_t *instance); 90 extern void hc_start(hc_t *instance); 91 extern void hc_fini(hc_t *); 85 static inline hc_t * hcd_to_hc(hc_device_t *hcd) 86 { 87 assert(hcd); 88 return (hc_t *) hcd; 89 } 90 91 extern int hc_add(hc_device_t *, const hw_res_list_parsed_t *); 92 extern int hc_gen_irq_code(irq_code_t *, hc_device_t *, const hw_res_list_parsed_t *); 93 extern int hc_gain_control(hc_device_t *); 94 extern int hc_start(hc_device_t *); 95 extern int hc_gone(hc_device_t *); 92 96 93 97 extern void hc_enqueue_endpoint(hc_t *, const endpoint_t *); 94 98 extern void hc_dequeue_endpoint(hc_t *, const endpoint_t *); 95 99 96 int ohci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res); 97 98 extern void ohci_hc_interrupt(hcd_t *, uint32_t); 99 extern int ohci_hc_status(hcd_t *, uint32_t *); 100 extern int ohci_hc_schedule(hcd_t *, usb_transfer_batch_t *); 100 extern int ohci_hc_schedule(usb_transfer_batch_t *); 101 extern int ohci_hc_status(bus_t *, uint32_t *); 102 extern void ohci_hc_interrupt(bus_t *, uint32_t); 101 103 102 104 #endif -
uspace/drv/bus/usb/ohci/main.c
r1ea0bbf r32fb6bce 48 48 49 49 #define NAME "ohci" 50 static int ohci_driver_init(hcd_t *, const hw_res_list_parsed_t *, ddf_dev_t *);51 static int ohci_driver_start(hcd_t *, bool);52 static int ohci_driver_claim(hcd_t *, ddf_dev_t *);53 static void ohci_driver_fini(hcd_t *);54 50 55 static const ddf_hc_driver_t ohci_hc_driver = { 56 .irq_code_gen = ohci_hc_gen_irq_code, 57 .init = ohci_driver_init, 58 .claim = ohci_driver_claim, 59 .start = ohci_driver_start, 51 static const hc_driver_t ohci_driver = { 52 .name = NAME, 53 .hc_device_size = sizeof(hc_t), 54 55 .hc_add = hc_add, 56 .irq_code_gen = hc_gen_irq_code, 57 .claim = hc_gain_control, 58 .start = hc_start, 60 59 .setup_root_hub = hcd_setup_virtual_root_hub, 61 .fini = ohci_driver_fini, 62 .name = "OHCI", 63 .ops = { 64 .schedule = ohci_hc_schedule, 65 .irq_hook = ohci_hc_interrupt, 66 .status_hook = ohci_hc_status, 67 }, 68 }; 69 70 71 static int ohci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, ddf_dev_t *device) 72 { 73 int err; 74 75 assert(hcd); 76 assert(hcd_get_driver_data(hcd) == NULL); 77 78 hc_t *instance = malloc(sizeof(hc_t)); 79 if (!instance) 80 return ENOMEM; 81 82 if ((err = hc_init(instance, res)) != EOK) 83 goto err; 84 85 if ((err = ohci_bus_init(&instance->bus, hcd, instance))) 86 goto err; 87 88 hcd_set_implementation(hcd, instance, &ohci_hc_driver.ops, &instance->bus.base.base); 89 90 return EOK; 91 92 err: 93 free(instance); 94 return err; 95 } 96 97 static int ohci_driver_claim(hcd_t *hcd, ddf_dev_t *dev) 98 { 99 hc_t *hc = hcd_get_driver_data(hcd); 100 assert(hc); 101 102 hc_gain_control(hc); 103 104 return EOK; 105 } 106 107 static int ohci_driver_start(hcd_t *hcd, bool interrupts) 108 { 109 hc_t *hc = hcd_get_driver_data(hcd); 110 assert(hc); 111 112 hc->hw_interrupts = interrupts; 113 hc_start(hc); 114 return EOK; 115 } 116 117 static void ohci_driver_fini(hcd_t *hcd) 118 { 119 assert(hcd); 120 hc_t *hc = hcd_get_driver_data(hcd); 121 if (hc) 122 hc_fini(hc); 123 124 hcd_set_implementation(hcd, NULL, NULL, NULL); 125 free(hc); 126 } 127 128 /** Initializes a new ddf driver instance of OHCI hcd. 129 * 130 * @param[in] device DDF instance of the device to initialize. 131 * @return Error code. 132 */ 133 static int ohci_dev_add(ddf_dev_t *device) 134 { 135 usb_log_debug("ohci_dev_add() called\n"); 136 assert(device); 137 return hcd_ddf_add_hc(device, &ohci_hc_driver); 138 } 139 140 static int ohci_fun_online(ddf_fun_t *fun) 141 { 142 return hcd_ddf_device_online(fun); 143 } 144 145 static int ohci_fun_offline(ddf_fun_t *fun) 146 { 147 return hcd_ddf_device_offline(fun); 148 } 149 150 151 static const driver_ops_t ohci_driver_ops = { 152 .dev_add = ohci_dev_add, 153 .fun_online = ohci_fun_online, 154 .fun_offline = ohci_fun_offline 155 }; 156 157 static const driver_t ohci_driver = { 158 .name = NAME, 159 .driver_ops = &ohci_driver_ops 60 .hc_gone = hc_gone, 160 61 }; 161 62 … … 171 72 { 172 73 log_init(NAME); 173 return ddf_driver_main(&ohci_driver);74 return hc_driver_main(&ohci_driver); 174 75 } 175 76 -
uspace/drv/bus/usb/ohci/ohci_bus.c
r1ea0bbf r32fb6bce 158 158 .parent = &usb2_bus_ops, 159 159 160 .interrupt = ohci_hc_interrupt, 161 .status = ohci_hc_status, 162 160 163 .endpoint_destroy = ohci_endpoint_destroy, 161 164 .endpoint_create = ohci_endpoint_create, … … 167 170 .batch_create = ohci_create_batch, 168 171 .batch_destroy = ohci_destroy_batch, 172 .batch_schedule = ohci_hc_schedule, 169 173 }; 170 174 171 175 172 int ohci_bus_init(ohci_bus_t *bus, hc d_t *hcd, hc_t *hc)176 int ohci_bus_init(ohci_bus_t *bus, hc_t *hc) 173 177 { 174 178 assert(hc); 175 179 assert(bus); 176 180 177 178 181 usb2_bus_t *usb2_bus = (usb2_bus_t *) bus; 179 182 bus_t *bus_base = (bus_t *) bus; 180 183 181 usb2_bus_init(usb2_bus, hcd,BANDWIDTH_AVAILABLE_USB11);184 usb2_bus_init(usb2_bus, BANDWIDTH_AVAILABLE_USB11); 182 185 bus_base->ops = &ohci_bus_ops; 183 186 -
uspace/drv/bus/usb/ohci/ohci_bus.h
r1ea0bbf r32fb6bce 62 62 } ohci_bus_t; 63 63 64 int ohci_bus_init(ohci_bus_t *, hc d_t *, hc_t *);64 int ohci_bus_init(ohci_bus_t *, hc_t *); 65 65 66 66 /** Get and convert assigned ohci_endpoint_t structure -
uspace/drv/bus/usb/uhci/hc.c
r1ea0bbf r32fb6bce 95 95 96 96 static void hc_init_hw(const hc_t *instance); 97 static int hc_init_mem_structures(hc_t *instance, hc d_t *);97 static int hc_init_mem_structures(hc_t *instance, hc_device_t *); 98 98 static int hc_init_transfer_lists(hc_t *instance); 99 99 … … 107 107 * @return Error code. 108 108 */ 109 int uhci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)109 int hc_gen_irq_code(irq_code_t *code, hc_device_t *hcd, const hw_res_list_parsed_t *hw_res) 110 110 { 111 111 assert(code); … … 156 156 * - resume from suspend state (not implemented) 157 157 */ 158 void uhci_hc_interrupt(hcd_t *hcd, uint32_t status) 159 { 160 assert(hcd); 161 hc_t *instance = hcd_get_driver_data(hcd); 162 assert(instance); 158 static void hc_interrupt(bus_t *bus, uint32_t status) 159 { 160 hc_t *instance = bus_to_hc(bus); 161 163 162 /* Lower 2 bits are transaction error and transaction complete */ 164 163 if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) { … … 199 198 } else { 200 199 usb_log_fatal("Too many UHCI hardware failures!.\n"); 201 hc_ fini(instance);200 hc_gone(&instance->base); 202 201 } 203 202 } … … 215 214 * interrupt fibrils. 216 215 */ 217 int hc_ init(hc_t *instance, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)218 { 219 assert(instance);216 int hc_add(hc_device_t *hcd, const hw_res_list_parsed_t *hw_res) 217 { 218 hc_t *instance = hcd_to_hc(hcd); 220 219 assert(hw_res); 221 220 if (hw_res->io_ranges.count != 1 || … … 249 248 } 250 249 251 void hc_start(hc_t *instance) 252 { 250 int hc_start(hc_device_t *hcd) 251 { 252 hc_t *instance = hcd_to_hc(hcd); 253 253 hc_init_hw(instance); 254 254 (void)hc_debug_checker; 255 255 256 uhci_rh_init(&instance->rh, instance->registers->ports, "uhci");256 return uhci_rh_init(&instance->rh, instance->registers->ports, "uhci"); 257 257 } 258 258 … … 261 261 * @param[in] instance Host controller structure to use. 262 262 */ 263 void hc_fini(hc_t *instance)263 int hc_gone(hc_device_t *instance) 264 264 { 265 265 assert(instance); 266 266 //TODO Implement 267 return ENOTSUP; 267 268 } 268 269 … … 294 295 pio_write_32(®isters->flbaseadd, pa); 295 296 296 if (instance-> hw_interrupts) {297 if (instance->base.irq_cap >= 0) { 297 298 /* Enable all interrupts, but resume interrupt */ 298 299 pio_write_16(&instance->registers->usbintr, … … 320 321 } 321 322 323 static int hc_status(bus_t *, uint32_t *); 324 static int hc_schedule(usb_transfer_batch_t *); 325 322 326 static const bus_ops_t uhci_bus_ops = { 323 327 .parent = &usb2_bus_ops, 324 328 329 .interrupt = hc_interrupt, 330 .status = hc_status, 331 325 332 .endpoint_count_bw = bandwidth_count_usb11, 326 333 .batch_create = create_transfer_batch, 334 .batch_schedule = hc_schedule, 327 335 .batch_destroy = destroy_transfer_batch, 328 336 }; … … 338 346 * - frame list page (needs to be one UHCI hw accessible 4K page) 339 347 */ 340 int hc_init_mem_structures(hc_t *instance, hc d_t *hcd)348 int hc_init_mem_structures(hc_t *instance, hc_device_t *hcd) 341 349 { 342 350 int err; 343 351 assert(instance); 344 352 345 if ((err = usb2_bus_init(&instance->bus, hcd,BANDWIDTH_AVAILABLE_USB11)))353 if ((err = usb2_bus_init(&instance->bus, BANDWIDTH_AVAILABLE_USB11))) 346 354 return err; 347 355 348 356 bus_t *bus = (bus_t *) &instance->bus; 349 357 bus->ops = &uhci_bus_ops; 358 359 hc_device_setup(&instance->base, bus); 350 360 351 361 /* Init USB frame list page */ … … 438 448 } 439 449 440 int uhci_hc_status(hcd_t *hcd, uint32_t *status)441 { 442 assert(hcd);450 static int hc_status(bus_t *bus, uint32_t *status) 451 { 452 hc_t *instance = bus_to_hc(bus); 443 453 assert(status); 444 hc_t *instance = hcd_get_driver_data(hcd);445 assert(instance);446 454 447 455 *status = 0; … … 462 470 * Checks for bandwidth availability and appends the batch to the proper queue. 463 471 */ 464 int uhci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch) 465 { 466 assert(hcd); 467 hc_t *instance = hcd_get_driver_data(hcd); 468 assert(instance); 472 static int hc_schedule(usb_transfer_batch_t *batch) 473 { 474 hc_t *instance = bus_to_hc(endpoint_get_bus(batch->ep)); 469 475 assert(batch); 470 476 -
uspace/drv/bus/usb/uhci/hc.h
r1ea0bbf r32fb6bce 100 100 /** Main UHCI driver structure */ 101 101 typedef struct hc { 102 /* Common hc_device header */ 103 hc_device_t base; 104 102 105 uhci_rh_t rh; 103 106 usb2_bus_t bus; … … 119 122 /** Pointer table to the above lists, helps during scheduling */ 120 123 transfer_list_t *transfers[2][4]; 121 /** Indicator of hw interrupts availability */122 bool hw_interrupts;123 124 124 125 /** Number of hw failures detected. */ … … 126 127 } hc_t; 127 128 128 extern int hc_init(hc_t *, hcd_t *, const hw_res_list_parsed_t *); 129 extern void hc_start(hc_t *); 130 extern void hc_fini(hc_t *); 129 static inline hc_t *hcd_to_hc(hc_device_t *hcd) 130 { 131 assert(hcd); 132 return (hc_t *) hcd; 133 } 131 134 132 extern int uhci_hc_gen_irq_code(irq_code_t *, hcd_t *,const hw_res_list_parsed_t *); 135 static inline hc_t *bus_to_hc(bus_t *bus) 136 { 137 assert(bus); 138 return member_to_inst(bus, hc_t, bus); 139 } 133 140 134 extern void uhci_hc_interrupt(hcd_t *, uint32_t); 135 extern int uhci_hc_status(hcd_t *, uint32_t *); 136 extern int uhci_hc_schedule(hcd_t *, usb_transfer_batch_t *); 141 extern int hc_add(hc_device_t *, const hw_res_list_parsed_t *); 142 extern int hc_gen_irq_code(irq_code_t *, hc_device_t *, const hw_res_list_parsed_t *); 143 extern int hc_start(hc_device_t *); 144 extern int hc_gone(hc_device_t *); 137 145 138 146 #endif -
uspace/drv/bus/usb/uhci/main.c
r1ea0bbf r32fb6bce 49 49 #define NAME "uhci" 50 50 51 static int uhci_driver_init(hcd_t *, const hw_res_list_parsed_t *, ddf_dev_t *); 52 static int uhci_driver_start(hcd_t *, bool); 53 static void uhci_driver_fini(hcd_t *); 54 static int disable_legacy(hcd_t *, ddf_dev_t *); 51 static int disable_legacy(hc_device_t *); 55 52 56 static const ddf_hc_driver_t uhci_hc_driver = { 57 .claim = disable_legacy, 58 .irq_code_gen = uhci_hc_gen_irq_code, 59 .init = uhci_driver_init, 60 .start = uhci_driver_start, 53 static const hc_driver_t uhci_driver = { 54 .name = NAME, 55 .hc_device_size = sizeof(hc_t), 56 .claim = disable_legacy, 57 .irq_code_gen = hc_gen_irq_code, 58 .hc_add = hc_add, 59 .start = hc_start, 61 60 .setup_root_hub = hcd_setup_virtual_root_hub, 62 .fini = uhci_driver_fini, 63 .name = "UHCI", 64 .ops = { 65 .schedule = uhci_hc_schedule, 66 .irq_hook = uhci_hc_interrupt, 67 .status_hook = uhci_hc_status, 68 }, 61 .hc_gone = hc_gone, 69 62 }; 70 71 static int uhci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, ddf_dev_t *device)72 {73 int err;74 75 assert(hcd);76 assert(hcd_get_driver_data(hcd) == NULL);77 78 hc_t *instance = malloc(sizeof(hc_t));79 if (!instance)80 return ENOMEM;81 82 if ((err = hc_init(instance, hcd, res)) != EOK)83 goto err;84 85 hcd_set_implementation(hcd, instance, &uhci_hc_driver.ops, &instance->bus.base);86 87 return EOK;88 89 err:90 free(instance);91 return err;92 }93 94 static int uhci_driver_start(hcd_t *hcd, bool interrupts)95 {96 assert(hcd);97 hc_t *hc = hcd_get_driver_data(hcd);98 99 hc->hw_interrupts = interrupts;100 hc_start(hc);101 return EOK;102 }103 104 static void uhci_driver_fini(hcd_t *hcd)105 {106 assert(hcd);107 hc_t *hc = hcd_get_driver_data(hcd);108 if (hc)109 hc_fini(hc);110 111 hcd_set_implementation(hcd, NULL, NULL, NULL);112 free(hc);113 }114 63 115 64 /** Call the PCI driver with a request to clear legacy support register … … 118 67 * @return Error code. 119 68 */ 120 static int disable_legacy(hc d_t *hcd, ddf_dev_t *device)69 static int disable_legacy(hc_device_t *hcd) 121 70 { 122 assert( device);71 assert(hcd); 123 72 124 async_sess_t *parent_sess = ddf_dev_parent_sess_get( device);73 async_sess_t *parent_sess = ddf_dev_parent_sess_get(hcd->ddf_dev); 125 74 if (parent_sess == NULL) 126 75 return ENOMEM; … … 130 79 return pci_config_space_write_16(parent_sess, 0xc0, 0xaf00); 131 80 } 132 133 /** Initialize a new ddf driver instance for uhci hc and hub.134 *135 * @param[in] device DDF instance of the device to initialize.136 * @return Error code.137 */138 static int uhci_dev_add(ddf_dev_t *device)139 {140 usb_log_debug2("uhci_dev_add() called\n");141 assert(device);142 return hcd_ddf_add_hc(device, &uhci_hc_driver);143 }144 145 static int uhci_fun_online(ddf_fun_t *fun)146 {147 return hcd_ddf_device_online(fun);148 }149 150 static int uhci_fun_offline(ddf_fun_t *fun)151 {152 return hcd_ddf_device_offline(fun);153 }154 155 static const driver_ops_t uhci_driver_ops = {156 .dev_add = uhci_dev_add,157 .fun_online = uhci_fun_online,158 .fun_offline = uhci_fun_offline159 };160 161 static const driver_t uhci_driver = {162 .name = NAME,163 .driver_ops = &uhci_driver_ops164 };165 166 81 167 82 /** Initialize global driver structures (NONE). … … 178 93 log_init(NAME); 179 94 logctl_set_log_level(NAME, LVL_DEBUG2); 180 return ddf_driver_main(&uhci_driver);95 return hc_driver_main(&uhci_driver); 181 96 } 182 97 /** -
uspace/drv/bus/usb/vhc/main.c
r1ea0bbf r32fb6bce 69 69 return ret; 70 70 } 71 vhc_init(vhc, dev_to_hcd(dev));72 71 return EOK; 73 72 } 74 73 75 hcd_ops_t vhc_hc_ops = {76 .schedule = vhc_schedule,77 };78 79 74 static int vhc_dev_add(ddf_dev_t *dev) 80 75 { 76 /* Initialize generic structures */ 77 int ret = hcd_ddf_setup_hc(dev, sizeof(vhc_data_t)); 78 if (ret != EOK) { 79 usb_log_error("Failed to init HCD structures: %s.\n", 80 str_error(ret)); 81 return ret; 82 } 83 vhc_data_t *vhc = ddf_dev_data_get(dev); 84 vhc_init(vhc); 85 86 hc_device_setup(&vhc->base, (bus_t *) &vhc->bus); 87 81 88 /* Initialize virtual structure */ 82 89 ddf_fun_t *ctl_fun = NULL; 83 intret = vhc_control_node(dev, &ctl_fun);90 ret = vhc_control_node(dev, &ctl_fun); 84 91 if (ret != EOK) { 85 92 usb_log_error("Failed to setup control node.\n"); 86 93 return ret; 87 94 } 88 vhc_data_t *data = ddf_fun_data_get(ctl_fun);89 90 /* Initialize generic structures */91 ret = hcd_ddf_setup_hc(dev);92 if (ret != EOK) {93 usb_log_error("Failed to init HCD structures: %s.\n",94 str_error(ret));95 ddf_fun_destroy(ctl_fun);96 return ret;97 }98 99 hcd_set_implementation(dev_to_hcd(dev), data, &vhc_hc_ops, &data->bus.base);100 95 101 96 /* Add virtual hub device */ 102 ret = vhc_virtdev_plug_hub( data, &data->hub, NULL, 0);97 ret = vhc_virtdev_plug_hub(vhc, &vhc->hub, NULL, 0); 103 98 if (ret != EOK) { 104 99 usb_log_error("Failed to plug root hub: %s.\n", str_error(ret)); … … 111 106 * needs to be ready at this time. 112 107 */ 113 ret = hcd_setup_virtual_root_hub( dev_to_hcd(dev), dev);108 ret = hcd_setup_virtual_root_hub(&vhc->base); 114 109 if (ret != EOK) { 115 110 usb_log_error("Failed to init VHC root hub: %s\n", -
uspace/drv/bus/usb/vhc/transfer.c
r1ea0bbf r32fb6bce 40 40 static bool is_set_address_transfer(vhc_transfer_t *transfer) 41 41 { 42 if (transfer->batch ->target.endpoint != 0) {43 return false; 44 } 45 if (transfer->batch ->ep->transfer_type != USB_TRANSFER_CONTROL) {46 return false; 47 } 48 if (transfer->batch ->dir != USB_DIRECTION_OUT) {42 if (transfer->batch.target.endpoint != 0) { 43 return false; 44 } 45 if (transfer->batch.ep->transfer_type != USB_TRANSFER_CONTROL) { 46 return false; 47 } 48 if (transfer->batch.dir != USB_DIRECTION_OUT) { 49 49 return false; 50 50 } 51 51 const usb_device_request_setup_packet_t *setup 52 = &transfer->batch ->setup.packet;52 = &transfer->batch.setup.packet; 53 53 if (setup->request_type != 0) { 54 54 return false; … … 150 150 assert(outcome != ENAK); 151 151 assert(transfer); 152 assert(transfer->batch); 153 transfer->batch->error = outcome; 154 transfer->batch->transfered_size = data_transfer_size; 155 usb_transfer_batch_finish(transfer->batch); 152 transfer->batch.error = outcome; 153 transfer->batch.transfered_size = data_transfer_size; 154 usb_transfer_batch_finish(&transfer->batch); 156 155 free(transfer); 156 } 157 158 static usb_transfer_batch_t *batch_create(endpoint_t *ep) 159 { 160 vhc_transfer_t *transfer = calloc(1, sizeof(vhc_transfer_t)); 161 usb_transfer_batch_init(&transfer->batch, ep); 162 link_initialize(&transfer->link); 163 return &transfer->batch; 157 164 } 158 165 159 166 static const bus_ops_t vhc_bus_ops = { 160 167 .parent = &usb2_bus_ops, 168 161 169 .endpoint_count_bw = bandwidth_count_usb11, 170 .batch_create = batch_create, 171 .batch_schedule = vhc_schedule, 162 172 }; 163 173 164 int vhc_init(vhc_data_t *instance , hcd_t *hcd)174 int vhc_init(vhc_data_t *instance) 165 175 { 166 176 assert(instance); 167 177 list_initialize(&instance->devices); 168 178 fibril_mutex_initialize(&instance->guard); 169 usb2_bus_init(&instance->bus, hcd,BANDWIDTH_AVAILABLE_USB11);179 usb2_bus_init(&instance->bus, BANDWIDTH_AVAILABLE_USB11); 170 180 instance->bus.base.ops = &vhc_bus_ops; 171 instance->magic = 0xDEADBEEF;172 181 return virthub_init(&instance->hub, "root hub"); 173 182 } 174 183 175 int vhc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch) 176 { 177 assert(hcd); 184 int vhc_schedule(usb_transfer_batch_t *batch) 185 { 178 186 assert(batch); 179 vhc_data_t *vhc = hcd_get_driver_data(hcd); 187 vhc_transfer_t *transfer = (vhc_transfer_t *) batch; 188 vhc_data_t *vhc = bus_to_vhc(endpoint_get_bus(batch->ep)); 180 189 assert(vhc); 181 182 vhc_transfer_t *transfer = malloc(sizeof(vhc_transfer_t));183 if (!transfer)184 return ENOMEM;185 link_initialize(&transfer->link);186 transfer->batch = batch;187 190 188 191 fibril_mutex_lock(&vhc->guard); … … 192 195 list_foreach(vhc->devices, link, vhc_virtdev_t, dev) { 193 196 fibril_mutex_lock(&dev->guard); 194 if (dev->address == transfer->batch ->target.address) {197 if (dev->address == transfer->batch.target.address) { 195 198 if (!targets) { 196 199 list_append(&transfer->link, &dev->transfer_queue); … … 227 230 size_t data_transfer_size = 0; 228 231 if (dev->dev_sess) { 229 rc = process_transfer_remote( transfer->batch,232 rc = process_transfer_remote(&transfer->batch, 230 233 dev->dev_sess, &data_transfer_size); 231 234 } else if (dev->dev_local != NULL) { 232 rc = process_transfer_local( transfer->batch,235 rc = process_transfer_local(&transfer->batch, 233 236 dev->dev_local, &data_transfer_size); 234 237 } else { … … 244 247 if (is_set_address_transfer(transfer)) { 245 248 usb_device_request_setup_packet_t *setup = 246 (void*) transfer->batch ->setup.buffer;249 (void*) transfer->batch.setup.buffer; 247 250 dev->address = setup->value; 248 251 usb_log_debug2("Address changed to %d\n", -
uspace/drv/bus/usb/vhc/vhcd.h
r1ea0bbf r32fb6bce 39 39 #include <usbvirt/device.h> 40 40 #include <async.h> 41 #include <macros.h> 41 42 42 43 #include <usb/host/hcd.h> 43 44 #include <usb/host/usb2_bus.h> 45 #include <usb/host/usb_transfer_batch.h> 44 46 45 47 #define NAME "vhc" … … 56 58 57 59 typedef struct { 58 uint32_t magic; 60 hc_device_t base; 61 62 usb2_bus_t bus; 63 ddf_fun_t *virtual_fun; 59 64 list_t devices; 60 65 fibril_mutex_t guard; 61 66 usbvirt_device_t hub; 62 usb2_bus_t bus;63 67 } vhc_data_t; 64 68 65 69 typedef struct { 70 usb_transfer_batch_t batch; 66 71 link_t link; 67 usb_transfer_batch_t *batch;68 72 } vhc_transfer_t; 73 74 static inline vhc_data_t *hcd_to_vhc(hc_device_t *hcd) 75 { 76 assert(hcd); 77 return (vhc_data_t *) hcd; 78 } 79 80 static inline vhc_data_t *bus_to_vhc(bus_t *bus) 81 { 82 assert(bus); 83 return member_to_inst(bus, vhc_data_t, bus); 84 } 69 85 70 86 void on_client_close(ddf_fun_t *fun); … … 77 93 void vhc_virtdev_unplug(vhc_data_t *, uintptr_t); 78 94 79 int vhc_init(vhc_data_t * instance, hcd_t *);80 int vhc_schedule( hcd_t *hcd, usb_transfer_batch_t *batch);95 int vhc_init(vhc_data_t *); 96 int vhc_schedule(usb_transfer_batch_t *); 81 97 int vhc_transfer_queue_processor(void *arg); 82 98 -
uspace/drv/bus/usb/xhci/bus.c
r1ea0bbf r32fb6bce 111 111 112 112 uint16_t max_packet_size; 113 if ((err = hcd_get_ep0_max_packet_size(&max_packet_size, hc->hcd, &dev->base)))113 if ((err = hcd_get_ep0_max_packet_size(&max_packet_size, (bus_t *) &hc->bus, &dev->base))) 114 114 return err; 115 115 … … 168 168 169 169 /* Read the device descriptor, derive the match ids */ 170 if ((err = hcd_d df_device_explore(dev))) {170 if ((err = hcd_device_explore(dev))) { 171 171 usb_log_error("Device(%d): Failed to explore device: %s", dev->address, str_error(err)); 172 172 goto err_address; … … 233 233 /* Destroy DDF device. */ 234 234 /* XXX: Not a good idea, this method should not destroy devices. */ 235 hcd_ddf_ device_destroy(dev);235 hcd_ddf_fun_destroy(dev); 236 236 237 237 return EOK; … … 501 501 BIND_OP(batch_destroy) 502 502 #undef BIND_OP 503 504 .interrupt = hc_interrupt, 505 .status = hc_status, 506 .batch_schedule = hc_schedule, 503 507 }; 504 508 … … 507 511 assert(bus); 508 512 509 bus_init(&bus->base, hc->hcd,sizeof(xhci_device_t));513 bus_init(&bus->base, sizeof(xhci_device_t)); 510 514 511 515 bus->devices_by_slot = calloc(hc->max_slots, sizeof(xhci_device_t *)); -
uspace/drv/bus/usb/xhci/hc.c
r1ea0bbf r32fb6bce 432 432 * Used only when polling. Shall supplement the irq_commands. 433 433 */ 434 int hc_status(xhci_hc_t *hc, uint32_t *status) 435 { 434 int hc_status(bus_t *bus, uint32_t *status) 435 { 436 xhci_hc_t *hc = bus_to_hc(bus); 436 437 int ip = XHCI_REG_RD(hc->rt_regs->ir, XHCI_INTR_IP); 437 438 if (ip) { … … 449 450 } 450 451 451 int hc_schedule( xhci_hc_t *hc,usb_transfer_batch_t *batch)452 int hc_schedule(usb_transfer_batch_t *batch) 452 453 { 453 454 assert(batch); 454 assert(batch->ep);455 xhci_hc_t *hc = bus_to_hc(endpoint_get_bus(batch->ep)); 455 456 456 457 if (!batch->target.address) { … … 532 533 } 533 534 534 void hc_interrupt(xhci_hc_t *hc, uint32_t status) 535 { 535 void hc_interrupt(bus_t *bus, uint32_t status) 536 { 537 xhci_hc_t *hc = bus_to_hc(bus); 536 538 status = xhci2host(32, status); 537 539 -
uspace/drv/bus/usb/xhci/hc.h
r1ea0bbf r32fb6bce 51 51 52 52 typedef struct xhci_hc { 53 /** Common HC device header */ 54 hc_device_t base; 55 53 56 /* MMIO range */ 54 57 addr_range_t mmio_range; … … 86 89 xhci_port_speed_t speeds [16]; 87 90 uint8_t speed_to_psiv [USB_SPEED_MAX]; 91 } xhci_hc_t; 88 92 89 /* TODO: Hack. Figure out a better way. */ 90 hcd_t *hcd; 91 } xhci_hc_t; 93 static inline xhci_hc_t *bus_to_hc(bus_t *bus) 94 { 95 assert(bus); 96 return member_to_inst(bus, xhci_hc_t, bus); 97 } 92 98 93 99 typedef struct xhci_endpoint xhci_endpoint_t; … … 99 105 int hc_irq_code_gen(irq_code_t *, xhci_hc_t *, const hw_res_list_parsed_t *); 100 106 int hc_start(xhci_hc_t *, bool); 101 int hc_schedule(xhci_hc_t *hc, usb_transfer_batch_t *batch);102 int hc_status(xhci_hc_t *, uint32_t *);103 void hc_interrupt(xhci_hc_t *, uint32_t);104 107 void hc_fini(xhci_hc_t *); 105 108 int hc_ring_doorbell(xhci_hc_t *, unsigned, unsigned); … … 113 116 int hc_update_endpoint(xhci_hc_t *, uint32_t, uint8_t, xhci_ep_ctx_t *); 114 117 118 int hc_schedule(usb_transfer_batch_t *batch); 119 int hc_status(bus_t *, uint32_t *); 120 void hc_interrupt(bus_t *, uint32_t); 121 115 122 #endif 116 123 -
uspace/drv/bus/usb/xhci/main.c
r1ea0bbf r32fb6bce 47 47 #define NAME "xhci" 48 48 49 static int hc_driver_init(hcd_t *, const hw_res_list_parsed_t *, ddf_dev_t *); 50 static int hcd_irq_code_gen(irq_code_t *, hcd_t *, const hw_res_list_parsed_t *); 51 static int hcd_claim(hcd_t *, ddf_dev_t *); 52 static int hcd_start(hcd_t *, bool); 53 static int hcd_status(hcd_t *, uint32_t *); 54 static void hcd_interrupt(hcd_t *, uint32_t); 55 static int hcd_schedule(hcd_t *, usb_transfer_batch_t *); 56 static void hc_driver_fini(hcd_t *); 49 static inline xhci_hc_t *hcd_to_hc(hc_device_t *hcd) 50 { 51 assert(hcd); 52 return (xhci_hc_t *) hcd; 53 } 57 54 58 static const ddf_hc_driver_t xhci_ddf_hc_driver = { 59 .name = "XHCI-PCI", 60 .init = hc_driver_init, 55 static int hcd_hc_add(hc_device_t *hcd, const hw_res_list_parsed_t *hw_res) 56 { 57 int err; 58 xhci_hc_t *hc = hcd_to_hc(hcd); 59 hc_device_setup(hcd, (bus_t *) &hc->bus); 60 61 if ((err = hc_init_mmio(hc, hw_res))) 62 return err; 63 64 if ((err = hc_init_memory(hc, hcd->ddf_dev))) 65 return err; 66 67 return EOK; 68 } 69 70 static int hcd_irq_code_gen(irq_code_t *code, hc_device_t *hcd, const hw_res_list_parsed_t *hw_res) 71 { 72 xhci_hc_t *hc = hcd_to_hc(hcd); 73 return hc_irq_code_gen(code, hc, hw_res); 74 } 75 76 static int hcd_claim(hc_device_t *hcd) 77 { 78 xhci_hc_t *hc = hcd_to_hc(hcd); 79 return hc_claim(hc, hcd->ddf_dev); 80 } 81 82 static int hcd_start(hc_device_t *hcd) 83 { 84 xhci_hc_t *hc = hcd_to_hc(hcd); 85 return hc_start(hc, hcd->irq_cap >= 0); 86 } 87 88 static int hcd_hc_gone(hc_device_t *hcd) 89 { 90 xhci_hc_t *hc = hcd_to_hc(hcd); 91 hc_fini(hc); 92 return EOK; 93 } 94 95 static const hc_driver_t xhci_driver = { 96 .name = NAME, 97 .hc_device_size = sizeof(xhci_hc_t), 98 99 .hc_add = hcd_hc_add, 61 100 .irq_code_gen = hcd_irq_code_gen, 62 101 .claim = hcd_claim, 63 102 .start = hcd_start, 64 .setup_root_hub = NULL, 65 .fini = hc_driver_fini, 66 .ops = { 67 .schedule = hcd_schedule, 68 .irq_hook = hcd_interrupt, 69 .status_hook = hcd_status, 70 } 103 .hc_gone = hcd_hc_gone, 71 104 }; 72 73 static int hc_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *hw_res, ddf_dev_t *device)74 {75 int err;76 77 xhci_hc_t *hc = malloc(sizeof(xhci_hc_t));78 if (!hc)79 return ENOMEM;80 81 if ((err = hc_init_mmio(hc, hw_res)))82 goto err;83 84 hc->hcd = hcd;85 86 if ((err = hc_init_memory(hc, device)))87 goto err;88 89 hcd_set_implementation(hcd, hc, &xhci_ddf_hc_driver.ops, &hc->bus.base);90 91 return EOK;92 err:93 free(hc);94 return err;95 }96 97 static int hcd_irq_code_gen(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)98 {99 xhci_hc_t *hc = hcd_get_driver_data(hcd);100 assert(hc);101 102 return hc_irq_code_gen(code, hc, hw_res);103 }104 105 static int hcd_claim(hcd_t *hcd, ddf_dev_t *dev)106 {107 xhci_hc_t *hc = hcd_get_driver_data(hcd);108 assert(hc);109 110 return hc_claim(hc, dev);111 }112 113 static int hcd_start(hcd_t *hcd, bool irq)114 {115 xhci_hc_t *hc = hcd_get_driver_data(hcd);116 assert(hc);117 118 return hc_start(hc, irq);119 }120 121 static int hcd_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)122 {123 xhci_hc_t *hc = hcd_get_driver_data(hcd);124 assert(hc);125 126 return hc_schedule(hc, batch);127 }128 129 static int hcd_status(hcd_t *hcd, uint32_t *status)130 {131 xhci_hc_t *hc = hcd_get_driver_data(hcd);132 assert(hc);133 assert(status);134 135 return hc_status(hc, status);136 }137 138 static void hcd_interrupt(hcd_t *hcd, uint32_t status)139 {140 xhci_hc_t *hc = hcd_get_driver_data(hcd);141 assert(hc);142 143 hc_interrupt(hc, status);144 }145 146 static void hc_driver_fini(hcd_t *hcd)147 {148 xhci_hc_t *hc = hcd_get_driver_data(hcd);149 assert(hc);150 151 hc_fini(hc);152 153 free(hc);154 }155 156 /** Initializes a new ddf driver instance of XHCI hcd.157 *158 * @param[in] device DDF instance of the device to initialize.159 * @return Error code.160 */161 static int xhci_dev_add(ddf_dev_t *device)162 {163 usb_log_info("Adding device %s", ddf_dev_get_name(device));164 return hcd_ddf_add_hc(device, &xhci_ddf_hc_driver);165 }166 167 static int xhci_fun_online(ddf_fun_t *fun)168 {169 return hcd_ddf_device_online(fun);170 }171 172 static int xhci_fun_offline(ddf_fun_t *fun)173 {174 return hcd_ddf_device_offline(fun);175 }176 177 178 static const driver_ops_t xhci_driver_ops = {179 .dev_add = xhci_dev_add,180 .fun_online = xhci_fun_online,181 .fun_offline = xhci_fun_offline182 };183 184 static const driver_t xhci_driver = {185 .name = NAME,186 .driver_ops = &xhci_driver_ops187 };188 189 105 190 106 /** Initializes global driver structures (NONE). … … 200 116 log_init(NAME); 201 117 logctl_set_log_level(NAME, LVL_DEBUG2); 202 return ddf_driver_main(&xhci_driver);118 return hc_driver_main(&xhci_driver); 203 119 } 204 120 -
uspace/drv/bus/usb/xhci/rh.c
r1ea0bbf r32fb6bce 94 94 xhci_bus_t *bus = &rh->hc->bus; 95 95 96 device_t *dev = hcd_ddf_ device_create(rh->hc_device, &bus->base);96 device_t *dev = hcd_ddf_fun_create(&rh->hc->base); 97 97 if (!dev) { 98 98 usb_log_error("Failed to create USB device function."); … … 132 132 133 133 err_usb_dev: 134 hcd_ddf_ device_destroy(dev);134 hcd_ddf_fun_destroy(dev); 135 135 return err; 136 136 } -
uspace/lib/usbhost/include/usb/host/bus.h
r1ea0bbf r32fb6bce 43 43 #define LIBUSBHOST_HOST_BUS_H 44 44 45 #include <usb/usb.h>46 #include <usb/request.h>47 #include <usb/host/hcd.h>48 49 45 #include <assert.h> 50 46 #include <fibril_synch.h> 51 47 #include <stdbool.h> 48 #include <usb/host/hcd.h> 49 #include <usb/request.h> 50 #include <usb/usb.h> 51 #include <usbhc_iface.h> 52 52 53 53 typedef struct hcd hcd_t; … … 94 94 95 95 /* Global operations on the bus */ 96 void (*interrupt)(bus_t *, uint32_t); 97 int (*status)(bus_t *, uint32_t *); 96 98 int (*reserve_default_address)(bus_t *, usb_speed_t); 97 99 int (*release_default_address)(bus_t *); … … 116 118 117 119 /* Operations on batch */ 118 void (*batch_destroy)(usb_transfer_batch_t *); /**< Optional */ 120 void (*batch_destroy)(usb_transfer_batch_t *); /**< Optional */ 121 int (*batch_schedule)(usb_transfer_batch_t *); 119 122 }; 120 123 … … 129 132 fibril_mutex_t guard; 130 133 131 /* TODO: get rid of this one. */ 132 hcd_t *hcd; 133 134 /* Size of the device_t extended structure */ 134 135 size_t device_size; 135 136 … … 140 141 } bus_t; 141 142 142 void bus_init(bus_t *, hcd_t *,size_t);143 void bus_init(bus_t *, size_t); 143 144 int bus_device_init(device_t *, bus_t *); 144 145 … … 150 151 int bus_device_online(device_t *); 151 152 int bus_device_offline(device_t *); 153 154 int bus_device_send_batch(device_t *, usb_target_t, 155 usb_direction_t direction, char *, size_t, uint64_t, 156 usbhc_iface_transfer_callback_t, void *, const char *); 157 158 ssize_t bus_device_send_batch_sync(device_t *, usb_target_t, 159 usb_direction_t direction, char *, size_t, uint64_t, 160 const char *); 152 161 153 162 int bus_endpoint_add(device_t *, const usb_endpoint_desc_t *, endpoint_t **); -
uspace/lib/usbhost/include/usb/host/ddf_helpers.h
r1ea0bbf r32fb6bce 39 39 #include <ddf/driver.h> 40 40 #include <ddf/interrupt.h> 41 #include <device/hw_res_parsed.h>42 41 #include <usb/usb.h> 43 42 44 43 #include <usb/host/hcd.h> 45 44 46 typedef int (*driver_init_t)(hcd_t *, const hw_res_list_parsed_t *, ddf_dev_t *); 47 typedef int (*irq_code_gen_t)(irq_code_t *, hcd_t *, const hw_res_list_parsed_t *); 48 typedef int (*claim_t)(hcd_t *, ddf_dev_t *); 49 typedef int (*driver_start_t)(hcd_t *, bool irq); 50 typedef int (*setup_root_hub_t)(hcd_t *, ddf_dev_t *); 45 int hcd_ddf_setup_hc(ddf_dev_t *, size_t); 46 void hcd_ddf_clean_hc(hc_device_t *); 51 47 52 typedef void (*driver_stop_t)(hcd_t *); 53 typedef void (*driver_fini_t)(hcd_t *); 48 int hcd_setup_virtual_root_hub(hc_device_t *); 54 49 55 /** 56 * All callbacks are optional. 57 */ 58 typedef struct { 59 hcd_ops_t ops; 60 const char *name; 50 device_t *hcd_ddf_fun_create(hc_device_t *); 51 void hcd_ddf_fun_destroy(device_t *); 61 52 62 interrupt_handler_t *irq_handler; /**< Handler of IRQ. Do have generic implementation. */ 53 int hcd_device_explore(device_t *); 63 54 64 /* Initialization sequence: */ 65 driver_init_t init; /**< Initialize internal structures, memory */ 66 claim_t claim; /**< Claim device from BIOS */ 67 irq_code_gen_t irq_code_gen; /**< Generate IRQ handling code */ 68 driver_start_t start; /**< Start the HC */ 69 setup_root_hub_t setup_root_hub; /**< Setup the root hub */ 55 int hcd_ddf_enable_interrupt(hc_device_t *hcd, int); 56 int hcd_ddf_get_registers(hc_device_t *hcd, hw_res_list_parsed_t *hw_res); 70 57 71 /* Destruction sequence: */ 72 driver_stop_t stop; /**< Stop the HC (counterpart of start) */ 73 driver_fini_t fini; /**< Destroy internal structures (counterpart of init) */ 74 } ddf_hc_driver_t; 75 76 int hcd_ddf_add_hc(ddf_dev_t *device, const ddf_hc_driver_t *driver); 77 78 int hcd_ddf_setup_hc(ddf_dev_t *device); 79 void hcd_ddf_clean_hc(ddf_dev_t *device); 80 81 int hcd_setup_virtual_root_hub(hcd_t *, ddf_dev_t *); 82 83 device_t *hcd_ddf_device_create(ddf_dev_t *, bus_t *); 84 void hcd_ddf_device_destroy(device_t *); 85 int hcd_ddf_device_explore(device_t *); 86 int hcd_ddf_device_online(ddf_fun_t *); 87 int hcd_ddf_device_offline(ddf_fun_t *); 88 89 hcd_t *dev_to_hcd(ddf_dev_t *dev); 90 91 int hcd_ddf_enable_interrupt(ddf_dev_t *device, int); 92 int hcd_ddf_get_registers(ddf_dev_t *device, hw_res_list_parsed_t *hw_res); 93 int hcd_ddf_setup_interrupts(ddf_dev_t *device, 94 const hw_res_list_parsed_t *hw_res, 95 interrupt_handler_t handler, 96 irq_code_gen_t gen_irq_code); 97 void ddf_hcd_gen_irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev); 58 void hcd_ddf_gen_irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev); 98 59 99 60 #endif -
uspace/lib/usbhost/include/usb/host/endpoint.h
r1ea0bbf r32fb6bce 109 109 ssize_t endpoint_count_bw(endpoint_t *, size_t); 110 110 111 int endpoint_send_batch(endpoint_t *, usb_target_t, usb_direction_t, 112 char *, size_t, uint64_t, usbhc_iface_transfer_callback_t, void *, 113 const char *); 114 111 115 static inline bus_t *endpoint_get_bus(endpoint_t *ep) 112 116 { -
uspace/lib/usbhost/include/usb/host/hcd.h
r1ea0bbf r32fb6bce 37 37 #define LIBUSBHOST_HOST_HCD_H 38 38 39 #include <assert.h> 40 #include <mem.h> 41 #include <stddef.h> 42 #include <stdint.h> 43 #include <usb/usb.h> 44 #include <usbhc_iface.h> 39 #include <ddf/driver.h> 40 #include <usb/request.h> 45 41 46 typedef struct h cd hcd_t;42 typedef struct hw_resource_list_parsed hw_res_list_parsed_t; 47 43 typedef struct bus bus_t; 48 44 typedef struct device device_t; 49 typedef struct usb_transfer_batch usb_transfer_batch_t;50 45 51 typedef int (*schedule_hook_t)(hcd_t *, usb_transfer_batch_t *); 52 typedef void (*interrupt_hook_t)(hcd_t *, uint32_t); 53 typedef int (*status_hook_t)(hcd_t *, uint32_t *); 46 /* Treat this header as read-only in driver code. 47 * It could be opaque, but why to complicate matters. 48 */ 49 typedef struct hc_device { 50 /* Bus instance */ 51 bus_t *bus; 54 52 55 typedef struct { 56 /** Transfer scheduling, implement in device driver. */ 57 schedule_hook_t schedule; 58 /** Hook to be called on device interrupt, passes ARG1 */ 59 interrupt_hook_t irq_hook; 60 /** Periodic polling hook */ 61 status_hook_t status_hook; 62 } hcd_ops_t; 53 /* Managed DDF device */ 54 ddf_dev_t *ddf_dev; 63 55 64 /** Generic host controller driver structure. */ 65 struct hcd { 66 /** Endpoint manager. */ 67 bus_t *bus; 56 /* Control function */ 57 ddf_fun_t *ctl_fun; 58 59 /* Result of enabling HW IRQs */ 60 int irq_cap; 68 61 69 62 /** Interrupt replacement fibril */ 70 63 fid_t polling_fibril; 71 64 72 /* * Driver implementation*/73 hcd_ops_t ops;65 /* This structure is meant to be extended by driver code. */ 66 } hc_device_t; 74 67 75 /** Device specific driver data. */ 76 void * driver_data; 77 }; 68 typedef struct hc_driver { 69 const char *name; 78 70 79 extern void hcd_init(hcd_t *); 71 /** Size of the device data to be allocated, and passed as the 72 * hc_device_t. */ 73 size_t hc_device_size; 80 74 81 static inline void hcd_set_implementation(hcd_t *hcd, void *data, 82 const hcd_ops_t *ops, bus_t *bus) 83 { 84 assert(hcd); 85 if (ops) { 86 hcd->driver_data = data; 87 hcd->ops = *ops; 88 hcd->bus = bus; 89 } else { 90 memset(&hcd->ops, 0, sizeof(hcd->ops)); 91 } 75 /** Initialize device structures. */ 76 int (*hc_add)(hc_device_t *, const hw_res_list_parsed_t *); 77 78 /** Generate IRQ code to handle interrupts. */ 79 int (*irq_code_gen)(irq_code_t *, hc_device_t *, const hw_res_list_parsed_t *); 80 81 /** Claim device from BIOS. */ 82 int (*claim)(hc_device_t *); 83 84 /** Start the host controller. */ 85 int (*start)(hc_device_t *); 86 87 /** Setup the virtual roothub. */ 88 int (*setup_root_hub)(hc_device_t *); 89 90 /** Stop the host controller (after start has been called) */ 91 int (*stop)(hc_device_t *); 92 93 /** HC was asked to be removed (after hc_add has been called) */ 94 int (*hc_remove)(hc_device_t *); 95 96 /** HC is gone. */ 97 int (*hc_gone)(hc_device_t *); 98 } hc_driver_t; 99 100 /* Drivers should call this before leaving hc_add */ 101 static inline void hc_device_setup(hc_device_t *hcd, bus_t *bus) { 102 hcd->bus = bus; 92 103 } 93 104 94 static inline void * hcd_get_driver_data(hcd_t *hcd)105 static inline hc_device_t *dev_to_hcd(ddf_dev_t *dev) 95 106 { 96 assert(hcd); 97 return hcd->driver_data; 107 return ddf_dev_data_get(dev); 98 108 } 99 109 100 extern int hcd_get_ep0_max_packet_size(uint16_t *, hcd_t *, device_t *); 110 int hc_driver_main(const hc_driver_t *); 111 112 /* TODO: These are a kind of utility functions, they should probably go 113 * somewhere else. 114 */ 115 extern int hcd_get_ep0_max_packet_size(uint16_t *, bus_t *, device_t *); 101 116 extern void hcd_setup_device_tt(device_t *); 102 103 extern int hcd_send_batch(hcd_t *, device_t *, usb_target_t,104 usb_direction_t direction, char *, size_t, uint64_t,105 usbhc_iface_transfer_callback_t, void *, const char *);106 107 extern ssize_t hcd_send_batch_sync(hcd_t *, device_t *, usb_target_t,108 usb_direction_t direction, char *, size_t, uint64_t,109 const char *);110 117 111 118 /** How many toggles need to be reset */ … … 116 123 } toggle_reset_mode_t; 117 124 125 extern toggle_reset_mode_t hcd_get_request_toggle_reset_mode( 126 const usb_device_request_setup_packet_t *request); 127 118 128 #endif 119 129 -
uspace/lib/usbhost/include/usb/host/usb2_bus.h
r1ea0bbf r32fb6bce 66 66 extern const bus_ops_t usb2_bus_ops; 67 67 68 extern int usb2_bus_init(usb2_bus_t *, hcd_t *,size_t);68 extern int usb2_bus_init(usb2_bus_t *, size_t); 69 69 70 70 #endif -
uspace/lib/usbhost/src/bus.c
r1ea0bbf r32fb6bce 46 46 * Initializes the bus structure. 47 47 */ 48 void bus_init(bus_t *bus, hcd_t *hcd, size_t device_size) 49 { 50 assert(bus); 51 assert(hcd); 48 void bus_init(bus_t *bus, size_t device_size) 49 { 50 assert(bus); 52 51 assert(device_size >= sizeof(device_t)); 53 52 memset(bus, 0, sizeof(bus_t)); 54 53 55 54 fibril_mutex_initialize(&bus->guard); 56 bus->hcd = hcd;57 55 bus->device_size = device_size; 58 56 } … … 61 59 { 62 60 assert(bus); 63 assert(bus->hcd);64 61 65 62 memset(dev, 0, sizeof(*dev)); … … 258 255 } 259 256 257 /** Prepare generic usb_transfer_batch and schedule it. 258 * @param device Device for which to send the batch 259 * @param target address and endpoint number. 260 * @param setup_data Data to use in setup stage (Control communication type) 261 * @param in Callback for device to host communication. 262 * @param out Callback for host to device communication. 263 * @param arg Callback parameter. 264 * @param name Communication identifier (for nicer output). 265 * @return Error code. 266 */ 267 int bus_device_send_batch(device_t *device, usb_target_t target, 268 usb_direction_t direction, char *data, size_t size, uint64_t setup_data, 269 usbhc_iface_transfer_callback_t on_complete, void *arg, const char *name) 270 { 271 assert(device->address == target.address); 272 273 /* Temporary reference */ 274 endpoint_t *ep = bus_find_endpoint(device, target, direction); 275 if (ep == NULL) { 276 usb_log_error("Endpoint(%d:%d) not registered for %s.\n", 277 device->address, target.endpoint, name); 278 return ENOENT; 279 } 280 281 assert(ep->device == device); 282 283 const int err = endpoint_send_batch(ep, target, direction, data, size, setup_data, 284 on_complete, arg, name); 285 286 /* Temporary reference */ 287 endpoint_del_ref(ep); 288 289 return err; 290 } 291 292 typedef struct { 293 fibril_mutex_t done_mtx; 294 fibril_condvar_t done_cv; 295 unsigned done; 296 297 size_t transfered_size; 298 int error; 299 } sync_data_t; 300 301 static int sync_transfer_complete(void *arg, int error, size_t transfered_size) 302 { 303 sync_data_t *d = arg; 304 assert(d); 305 d->transfered_size = transfered_size; 306 d->error = error; 307 fibril_mutex_lock(&d->done_mtx); 308 d->done = 1; 309 fibril_condvar_broadcast(&d->done_cv); 310 fibril_mutex_unlock(&d->done_mtx); 311 return EOK; 312 } 313 314 ssize_t bus_device_send_batch_sync(device_t *device, usb_target_t target, 315 usb_direction_t direction, char *data, size_t size, uint64_t setup_data, 316 const char *name) 317 { 318 sync_data_t sd = { .done = 0 }; 319 fibril_mutex_initialize(&sd.done_mtx); 320 fibril_condvar_initialize(&sd.done_cv); 321 322 const int ret = bus_device_send_batch(device, target, direction, 323 data, size, setup_data, 324 sync_transfer_complete, &sd, name); 325 if (ret != EOK) 326 return ret; 327 328 fibril_mutex_lock(&sd.done_mtx); 329 while (!sd.done) { 330 fibril_condvar_wait_timeout(&sd.done_cv, &sd.done_mtx, 3000000); 331 if (!sd.done) 332 usb_log_debug2("Still waiting..."); 333 } 334 fibril_mutex_unlock(&sd.done_mtx); 335 336 return (sd.error == EOK) 337 ? (ssize_t) sd.transfered_size 338 : (ssize_t) sd.error; 339 } 340 260 341 /** 261 342 * @} -
uspace/lib/usbhost/src/ddf_helpers.c
r1ea0bbf r32fb6bce 53 53 #include "ddf_helpers.h" 54 54 55 typedef struct hc_dev { 56 ddf_fun_t *ctl_fun; 57 hcd_t hcd; 58 } hc_dev_t; 59 60 static hc_dev_t *dev_to_hc_dev(ddf_dev_t *dev) 61 { 62 return ddf_dev_data_get(dev); 63 } 64 65 hcd_t *dev_to_hcd(ddf_dev_t *dev) 66 { 67 hc_dev_t *hc_dev = dev_to_hc_dev(dev); 68 if (!hc_dev) { 69 usb_log_error("Invalid HCD device.\n"); 70 return NULL; 71 } 72 return &hc_dev->hcd; 73 } 74 75 76 static int hcd_ddf_new_device(hcd_t *hcd, ddf_dev_t *hc, device_t *hub_dev, unsigned port); 55 56 static int hcd_ddf_new_device(hc_device_t *hcd, ddf_dev_t *hc, device_t *hub_dev, unsigned port); 77 57 static int hcd_ddf_remove_device(ddf_dev_t *device, device_t *hub, unsigned port); 78 58 … … 89 69 { 90 70 assert(fun); 91 hc d_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));71 hc_device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun)); 92 72 device_t *dev = ddf_fun_data_get(fun); 93 73 assert(hcd); … … 113 93 { 114 94 assert(fun); 115 hc d_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));95 hc_device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun)); 116 96 device_t *dev = ddf_fun_data_get(fun); 117 97 assert(hcd); … … 138 118 { 139 119 assert(fun); 140 hc d_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));120 hc_device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun)); 141 121 device_t *dev = ddf_fun_data_get(fun); 142 122 assert(hcd); … … 152 132 { 153 133 assert(fun); 154 hc d_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));134 hc_device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun)); 155 135 device_t *dev = ddf_fun_data_get(fun); 156 136 assert(hcd); … … 167 147 ddf_dev_t *hc = ddf_fun_get_dev(fun); 168 148 assert(hc); 169 hc d_t *hcd = dev_to_hcd(hc);149 hc_device_t *hcd = dev_to_hcd(hc); 170 150 assert(hcd); 171 151 device_t *hub = ddf_fun_data_get(fun); … … 218 198 { 219 199 assert(fun); 220 hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));221 200 device_t *dev = ddf_fun_data_get(fun); 222 201 assert(dev); … … 224 203 target.address = dev->address; 225 204 226 return hcd_send_batch(hcd,dev, target, USB_DIRECTION_IN,205 return bus_device_send_batch(dev, target, USB_DIRECTION_IN, 227 206 data, size, setup_data, 228 207 callback, arg, "READ"); … … 244 223 { 245 224 assert(fun); 246 hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));247 225 device_t *dev = ddf_fun_data_get(fun); 248 226 assert(dev); … … 250 228 target.address = dev->address; 251 229 252 return hcd_send_batch(hcd,dev, target, USB_DIRECTION_OUT,230 return bus_device_send_batch(dev, target, USB_DIRECTION_OUT, 253 231 (char *) data, size, setup_data, 254 232 callback, arg, "WRITE"); … … 337 315 assert(device); 338 316 339 hc d_t *hcd = dev_to_hcd(device);317 hc_device_t *hcd = dev_to_hcd(device); 340 318 assert(hcd); 341 319 assert(hcd->bus); 342 343 hc_dev_t *hc_dev = dev_to_hc_dev(device);344 assert(hc_dev);345 320 346 321 fibril_mutex_lock(&hub->guard); … … 374 349 } 375 350 376 device_t *hcd_ddf_ device_create(ddf_dev_t *hc, bus_t *bus)351 device_t *hcd_ddf_fun_create(hc_device_t *hc) 377 352 { 378 353 /* Create DDF function for the new device */ 379 ddf_fun_t *fun = ddf_fun_create(hc , fun_inner, NULL);354 ddf_fun_t *fun = ddf_fun_create(hc->ddf_dev, fun_inner, NULL); 380 355 if (!fun) 381 356 return NULL; … … 384 359 385 360 /* Create USB device node for the new device */ 386 device_t *dev = ddf_fun_data_alloc(fun, bus->device_size);361 device_t *dev = ddf_fun_data_alloc(fun, hc->bus->device_size); 387 362 if (!dev) { 388 363 ddf_fun_destroy(fun); … … 390 365 } 391 366 392 bus_device_init(dev, bus);367 bus_device_init(dev, hc->bus); 393 368 dev->fun = fun; 394 369 return dev; 395 370 } 396 371 397 void hcd_ddf_ device_destroy(device_t *dev)372 void hcd_ddf_fun_destroy(device_t *dev) 398 373 { 399 374 assert(dev); … … 402 377 } 403 378 404 int hcd_d df_device_explore(device_t *device)379 int hcd_device_explore(device_t *device) 405 380 { 406 381 int err; … … 421 396 usb_log_debug("Device(%d): Requesting full device descriptor.", 422 397 device->address); 423 ssize_t got = hcd_send_batch_sync(device->bus->hcd,device, control_ep, USB_DIRECTION_IN,398 ssize_t got = bus_device_send_batch_sync(device, control_ep, USB_DIRECTION_IN, 424 399 (char *) &desc, sizeof(desc), *(uint64_t *)&get_device_desc, 425 400 "read device descriptor"); … … 447 422 } 448 423 449 int hcd_ddf_device_online(ddf_fun_t *fun) 450 { 451 assert(fun); 452 453 hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun)); 454 device_t *dev = ddf_fun_data_get(fun); 455 assert(dev); 456 assert(hcd->bus); 457 458 usb_log_info("Device(%d): Requested to be brought online.", dev->address); 459 460 return bus_device_online(dev); 461 } 462 463 int hcd_ddf_device_offline(ddf_fun_t *fun) 464 { 465 assert(fun); 466 467 hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun)); 468 device_t *dev = ddf_fun_data_get(fun); 469 assert(dev); 470 assert(hcd->bus); 471 472 usb_log_info("Device(%d): Requested to be taken offline.", dev->address); 473 474 return bus_device_offline(dev); 475 } 476 477 static int hcd_ddf_new_device(hcd_t *hcd, ddf_dev_t *hc, device_t *hub, unsigned port) 424 static int hcd_ddf_new_device(hc_device_t *hcd, ddf_dev_t *hc, device_t *hub, unsigned port) 478 425 { 479 426 int err; … … 483 430 assert(hc); 484 431 485 device_t *dev = hcd_ddf_ device_create(hc, hcd->bus);432 device_t *dev = hcd_ddf_fun_create(hcd); 486 433 if (!dev) { 487 434 usb_log_error("Failed to create USB device function."); … … 516 463 517 464 err_usb_dev: 518 hcd_ddf_ device_destroy(dev);465 hcd_ddf_fun_destroy(dev); 519 466 return err; 520 467 } … … 525 472 * @return Error code 526 473 */ 527 int hcd_setup_virtual_root_hub(hc d_t *hcd, ddf_dev_t *hc)474 int hcd_setup_virtual_root_hub(hc_device_t *hcd) 528 475 { 529 476 int err; 530 477 531 assert(hc); 532 assert(hcd); 533 assert(hcd->bus); 478 assert(hcd); 534 479 535 480 if ((err = bus_reserve_default_address(hcd->bus, USB_SPEED_MAX))) { … … 538 483 } 539 484 540 device_t *dev = hcd_ddf_ device_create(hc, hcd->bus);485 device_t *dev = hcd_ddf_fun_create(hcd); 541 486 if (!dev) { 542 487 usb_log_error("Failed to create function for the root hub."); … … 561 506 562 507 err_usb_dev: 563 hcd_ddf_ device_destroy(dev);508 hcd_ddf_fun_destroy(dev); 564 509 err_default_address: 565 510 bus_release_default_address(hcd->bus); … … 577 522 * This function does all the ddf work for hc driver. 578 523 */ 579 int hcd_ddf_setup_hc(ddf_dev_t *device )524 int hcd_ddf_setup_hc(ddf_dev_t *device, size_t size) 580 525 { 581 526 assert(device); 582 527 583 hc_dev _t *instance = ddf_dev_data_alloc(device, sizeof(hc_dev_t));528 hc_device_t *instance = ddf_dev_data_alloc(device, size); 584 529 if (instance == NULL) { 585 530 usb_log_error("Failed to allocate HCD ddf structure.\n"); 586 531 return ENOMEM; 587 532 } 588 hcd_init(&instance->hcd);533 instance->ddf_dev = device; 589 534 590 535 int ret = ENOMEM; … … 618 563 } 619 564 620 void hcd_ddf_clean_hc(ddf_dev_t *device) 621 { 622 assert(device); 623 hc_dev_t *hc = dev_to_hc_dev(device); 624 assert(hc); 625 const int ret = ddf_fun_unbind(hc->ctl_fun); 626 if (ret == EOK) 627 ddf_fun_destroy(hc->ctl_fun); 628 } 629 630 //TODO: Cache parent session in HCD 565 void hcd_ddf_clean_hc(hc_device_t *hcd) 566 { 567 if (ddf_fun_unbind(hcd->ctl_fun) == EOK) 568 ddf_fun_destroy(hcd->ctl_fun); 569 } 570 631 571 /** Call the parent driver with a request to enable interrupt 632 572 * … … 635 575 * @return Error code. 636 576 */ 637 int hcd_ddf_enable_interrupt( ddf_dev_t *device, int inum)638 { 639 async_sess_t *parent_sess = ddf_dev_parent_sess_get( device);577 int hcd_ddf_enable_interrupt(hc_device_t *hcd, int inum) 578 { 579 async_sess_t *parent_sess = ddf_dev_parent_sess_get(hcd->ddf_dev); 640 580 if (parent_sess == NULL) 641 581 return EIO; … … 644 584 } 645 585 646 //TODO: Cache parent session in HCD 647 int hcd_ddf_get_registers(ddf_dev_t *device, hw_res_list_parsed_t *hw_res) 648 { 649 async_sess_t *parent_sess = ddf_dev_parent_sess_get(device); 586 int hcd_ddf_get_registers(hc_device_t *hcd, hw_res_list_parsed_t *hw_res) 587 { 588 async_sess_t *parent_sess = ddf_dev_parent_sess_get(hcd->ddf_dev); 650 589 if (parent_sess == NULL) 651 590 return EIO; … … 658 597 } 659 598 660 // TODO: move this someplace else661 static inline void irq_code_clean(irq_code_t *code)662 {663 if (code) {664 free(code->ranges);665 free(code->cmds);666 code->ranges = NULL;667 code->cmds = NULL;668 code->rangecount = 0;669 code->cmdcount = 0;670 }671 }672 673 /** Register interrupt handler674 *675 * @param[in] device Host controller DDF device676 * @param[in] regs Register range677 * @param[in] irq Interrupt number678 * @paran[in] handler Interrupt handler679 * @param[in] gen_irq_code IRQ code generator.680 *681 * @return IRQ capability handle on success.682 * @return Negative error code.683 */684 int hcd_ddf_setup_interrupts(ddf_dev_t *device,685 const hw_res_list_parsed_t *hw_res,686 interrupt_handler_t handler,687 irq_code_gen_t gen_irq_code)688 {689 assert(device);690 691 hcd_t *hcd = dev_to_hcd(device);692 693 if (!handler || !gen_irq_code)694 return ENOTSUP;695 696 irq_code_t irq_code = {0};697 698 const int irq = gen_irq_code(&irq_code, hcd, hw_res);699 if (irq < 0) {700 usb_log_error("Failed to generate IRQ code: %s.\n",701 str_error(irq));702 return irq;703 }704 705 /* Register handler to avoid interrupt lockup */706 const int irq_cap = register_interrupt_handler(device, irq, handler,707 &irq_code);708 irq_code_clean(&irq_code);709 if (irq_cap < 0) {710 usb_log_error("Failed to register interrupt handler: %s.\n",711 str_error(irq_cap));712 return irq_cap;713 }714 715 /* Enable interrupts */716 int ret = hcd_ddf_enable_interrupt(device, irq);717 if (ret != EOK) {718 usb_log_error("Failed to enable interrupts: %s.\n",719 str_error(ret));720 unregister_interrupt_handler(device, irq_cap);721 return ret;722 }723 return irq_cap;724 }725 726 /** IRQ handling callback, forward status from call to diver structure.727 *728 * @param[in] dev DDF instance of the device to use.729 * @param[in] iid (Unused).730 * @param[in] call Pointer to the call from kernel.731 */732 void ddf_hcd_gen_irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev)733 {734 assert(dev);735 hcd_t *hcd = dev_to_hcd(dev);736 if (!hcd || !hcd->ops.irq_hook) {737 usb_log_error("Interrupt on not yet initialized device.\n");738 return;739 }740 const uint32_t status = IPC_GET_ARG1(*call);741 hcd->ops.irq_hook(hcd, status);742 }743 744 static int interrupt_polling(void *arg)745 {746 hcd_t *hcd = arg;747 assert(hcd);748 if (!hcd->ops.status_hook || !hcd->ops.irq_hook)749 return ENOTSUP;750 uint32_t status = 0;751 while (hcd->ops.status_hook(hcd, &status) == EOK) {752 hcd->ops.irq_hook(hcd, status);753 status = 0;754 /* We should wait 1 frame - 1ms here, but this polling is a755 * lame crutch anyway so don't hog the system. 10ms is still756 * good enough for emergency mode */757 async_usleep(10000);758 }759 return EOK;760 }761 762 /** Initialize hc and rh DDF structures and their respective drivers.763 *764 * @param device DDF instance of the device to use765 * @param speed Maximum supported speed766 * @param bw Available bandwidth (arbitrary units)767 * @param bw_count Bandwidth computing function768 * @param irq_handler IRQ handling function769 * @param gen_irq_code Function to generate IRQ pseudocode770 * (it needs to return used irq number)771 * @param driver_init Function to initialize HC driver772 * @param driver_fini Function to cleanup HC driver773 * @return Error code774 *775 * This function does all the preparatory work for hc and rh drivers:776 * - gets device's hw resources777 * - attempts to enable interrupts778 * - registers interrupt handler779 * - calls driver specific initialization780 * - registers root hub781 */782 int hcd_ddf_add_hc(ddf_dev_t *device, const ddf_hc_driver_t *driver)783 {784 assert(driver);785 786 int ret = EOK;787 788 hw_res_list_parsed_t hw_res;789 ret = hcd_ddf_get_registers(device, &hw_res);790 if (ret != EOK) {791 usb_log_error("Failed to get register memory addresses "792 "for `%s': %s.\n", ddf_dev_get_name(device),793 str_error(ret));794 return ret;795 }796 797 ret = hcd_ddf_setup_hc(device);798 if (ret != EOK) {799 usb_log_error("Failed to setup generic HCD.\n");800 goto err_hw_res;801 }802 803 hcd_t *hcd = dev_to_hcd(device);804 805 if (driver->init)806 ret = driver->init(hcd, &hw_res, device);807 if (ret != EOK) {808 usb_log_error("Failed to init HCD.\n");809 goto err_hcd;810 }811 812 /* Setup interrupts */813 interrupt_handler_t *irq_handler =814 driver->irq_handler ? driver->irq_handler : ddf_hcd_gen_irq_handler;815 const int irq_cap = hcd_ddf_setup_interrupts(device, &hw_res,816 irq_handler, driver->irq_code_gen);817 bool irqs_enabled = !(irq_cap < 0);818 if (irqs_enabled) {819 usb_log_debug("Hw interrupts enabled.\n");820 }821 822 /* Claim the device from BIOS */823 if (driver->claim)824 ret = driver->claim(hcd, device);825 if (ret != EOK) {826 usb_log_error("Failed to claim `%s' for driver `%s': %s",827 ddf_dev_get_name(device), driver->name, str_error(ret));828 goto err_irq;829 }830 831 /* Start hw driver */832 if (driver->start)833 ret = driver->start(hcd, irqs_enabled);834 if (ret != EOK) {835 usb_log_error("Failed to start HCD: %s.\n", str_error(ret));836 goto err_irq;837 }838 839 /* Need working irq replacement to setup root hub */840 if (!irqs_enabled && hcd->ops.status_hook) {841 hcd->polling_fibril = fibril_create(interrupt_polling, hcd);842 if (hcd->polling_fibril == 0) {843 usb_log_error("Failed to create polling fibril\n");844 ret = ENOMEM;845 goto err_started;846 }847 fibril_add_ready(hcd->polling_fibril);848 usb_log_warning("Failed to enable interrupts: %s."849 " Falling back to polling.\n", str_error(irq_cap));850 }851 852 /*853 * Creating root hub registers a new USB device so HC854 * needs to be ready at this time.855 */856 if (driver->setup_root_hub)857 ret = driver->setup_root_hub(hcd, device);858 if (ret != EOK) {859 usb_log_error("Failed to setup HC root hub: %s.\n",860 str_error(ret));861 goto err_polling;862 }863 864 usb_log_info("Controlling new `%s' device `%s'.\n",865 driver->name, ddf_dev_get_name(device));866 return EOK;867 868 err_polling:869 // TODO: Stop the polling fibril (refactor the interrupt_polling func)870 //871 err_started:872 if (driver->stop)873 driver->stop(hcd);874 err_irq:875 unregister_interrupt_handler(device, irq_cap);876 if (driver->fini)877 driver->fini(hcd);878 err_hcd:879 hcd_ddf_clean_hc(device);880 err_hw_res:881 hw_res_list_parsed_clean(&hw_res);882 return ret;883 }884 885 599 /** 886 600 * @} -
uspace/lib/usbhost/src/endpoint.c
r1ea0bbf r32fb6bce 39 39 #include <mem.h> 40 40 #include <stdlib.h> 41 #include <str_error.h> 42 #include <usb/debug.h> 43 #include <usb/host/hcd.h> 41 44 42 45 #include "usb_transfer_batch.h" … … 187 190 } 188 191 192 /** Prepare generic usb_transfer_batch and schedule it. 193 * @param ep Endpoint for which the batch shall be created. 194 * @param target address and endpoint number. 195 * @param setup_data Data to use in setup stage (Control communication type) 196 * @param in Callback for device to host communication. 197 * @param out Callback for host to device communication. 198 * @param arg Callback parameter. 199 * @param name Communication identifier (for nicer output). 200 * @return Error code. 201 */ 202 int endpoint_send_batch(endpoint_t *ep, usb_target_t target, 203 usb_direction_t direction, char *data, size_t size, uint64_t setup_data, 204 usbhc_iface_transfer_callback_t on_complete, void *arg, const char *name) 205 { 206 usb_log_debug2("%s %d:%d %zu(%zu).\n", 207 name, target.address, target.endpoint, size, ep->max_packet_size); 208 209 bus_t *bus = endpoint_get_bus(ep); 210 const bus_ops_t *ops = BUS_OPS_LOOKUP(bus->ops, batch_schedule); 211 if (!ops) { 212 usb_log_error("HCD does not implement scheduler.\n"); 213 return ENOTSUP; 214 } 215 216 const size_t bw = endpoint_count_bw(ep, size); 217 /* Check if we have enough bandwidth reserved */ 218 if (ep->bandwidth < bw) { 219 usb_log_error("Endpoint(%d:%d) %s needs %zu bw " 220 "but only %zu is reserved.\n", 221 ep->device->address, ep->endpoint, name, bw, ep->bandwidth); 222 return ENOSPC; 223 } 224 225 usb_transfer_batch_t *batch = usb_transfer_batch_create(ep); 226 if (!batch) { 227 usb_log_error("Failed to create transfer batch.\n"); 228 return ENOMEM; 229 } 230 231 batch->target = target; 232 batch->buffer = data; 233 batch->buffer_size = size; 234 batch->setup.packed = setup_data; 235 batch->dir = direction; 236 batch->on_complete = on_complete; 237 batch->on_complete_data = arg; 238 239 /* Check for commands that reset toggle bit */ 240 if (ep->transfer_type == USB_TRANSFER_CONTROL) 241 batch->toggle_reset_mode 242 = hcd_get_request_toggle_reset_mode(&batch->setup.packet); 243 244 const int ret = ops->batch_schedule(batch); 245 if (ret != EOK) { 246 usb_log_warning("Batch %p failed to schedule: %s", batch, str_error(ret)); 247 usb_transfer_batch_destroy(batch); 248 } 249 250 return ret; 251 } 252 189 253 /** 190 254 * @} -
uspace/lib/usbhost/src/hcd.c
r1ea0bbf r32fb6bce 36 36 #include <assert.h> 37 37 #include <async.h> 38 #include <ddf/interrupt.h> 38 39 #include <errno.h> 39 40 #include <macros.h> … … 45 46 46 47 #include "bus.h" 48 #include "ddf_helpers.h" 47 49 #include "endpoint.h" 48 50 #include "usb_transfer_batch.h" … … 50 52 #include "hcd.h" 51 53 52 53 /** Initialize hcd_t structure. 54 * Initializes device and endpoint managers. Sets data and hook pointer to NULL. 55 * 56 * @param hcd hcd_t structure to initialize, non-null. 57 * @param max_speed Maximum supported USB speed (full, high). 58 * @param bandwidth Available bandwidth, passed to endpoint manager. 59 * @param bw_count Bandwidth compute function, passed to endpoint manager. 60 */ 61 void hcd_init(hcd_t *hcd) { 54 int hc_dev_add(ddf_dev_t *); 55 int hc_dev_remove(ddf_dev_t *); 56 int hc_dev_gone(ddf_dev_t *); 57 int hc_fun_online(ddf_fun_t *); 58 int hc_fun_offline(ddf_fun_t *); 59 60 static driver_ops_t hc_driver_ops = { 61 .dev_add = hc_dev_add, 62 .dev_remove = hc_dev_remove, 63 .dev_gone = hc_dev_gone, 64 .fun_online = hc_fun_offline, 65 .fun_offline = hc_fun_offline, 66 }; 67 68 static const hc_driver_t *hc_driver; 69 70 int hc_driver_main(const hc_driver_t *driver) 71 { 72 driver_t ddf_driver = { 73 .name = driver->name, 74 .driver_ops = &hc_driver_ops, 75 }; 76 77 /* Remember ops to call. */ 78 hc_driver = driver; 79 80 return ddf_driver_main(&ddf_driver); 81 } 82 83 /** IRQ handling callback, forward status from call to diver structure. 84 * 85 * @param[in] dev DDF instance of the device to use. 86 * @param[in] iid (Unused). 87 * @param[in] call Pointer to the call from kernel. 88 */ 89 static void irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev) 90 { 91 assert(dev); 92 hc_device_t *hcd = dev_to_hcd(dev); 93 94 const bus_ops_t *ops = BUS_OPS_LOOKUP(hcd->bus->ops, interrupt); 95 assert(ops); 96 97 const uint32_t status = IPC_GET_ARG1(*call); 98 ops->interrupt(hcd->bus, status); 99 } 100 101 /** Worker for the HW interrupt replacement fibril. 102 */ 103 static int interrupt_polling(void *arg) 104 { 105 hc_device_t *hcd = arg; 62 106 assert(hcd); 63 64 hcd_set_implementation(hcd, NULL, NULL, NULL); 107 bus_t *bus = hcd->bus; 108 109 const bus_ops_t *interrupt_ops = BUS_OPS_LOOKUP(bus->ops, interrupt); 110 const bus_ops_t *status_ops = BUS_OPS_LOOKUP(bus->ops, status); 111 if (!interrupt_ops || !status_ops) 112 return ENOTSUP; 113 114 uint32_t status = 0; 115 while (status_ops->status(bus, &status) == EOK) { 116 interrupt_ops->interrupt(bus, status); 117 status = 0; 118 /* We should wait 1 frame - 1ms here, but this polling is a 119 * lame crutch anyway so don't hog the system. 10ms is still 120 * good enough for emergency mode */ 121 async_usleep(10000); 122 } 123 return EOK; 124 } 125 126 static inline void irq_code_clean(irq_code_t *code) 127 { 128 if (code) { 129 free(code->ranges); 130 free(code->cmds); 131 code->ranges = NULL; 132 code->cmds = NULL; 133 code->rangecount = 0; 134 code->cmdcount = 0; 135 } 136 } 137 138 /** Register interrupt handler 139 * 140 * @param[in] device Host controller DDF device 141 * @param[in] regs Register range 142 * @param[in] irq Interrupt number 143 * @paran[in] handler Interrupt handler 144 * @param[in] gen_irq_code IRQ code generator. 145 * 146 * @return IRQ capability handle on success. 147 * @return Negative error code. 148 */ 149 static int hcd_ddf_setup_interrupts(hc_device_t *hcd, const hw_res_list_parsed_t *hw_res) 150 { 151 assert(hcd); 152 irq_code_t irq_code = {0}; 153 154 if (!hc_driver->irq_code_gen) 155 return ENOTSUP; 156 157 const int irq = hc_driver->irq_code_gen(&irq_code, hcd, hw_res); 158 if (irq < 0) { 159 usb_log_error("Failed to generate IRQ code: %s.\n", 160 str_error(irq)); 161 return irq; 162 } 163 164 /* Register handler to avoid interrupt lockup */ 165 const int irq_cap = register_interrupt_handler(hcd->ddf_dev, irq, irq_handler, &irq_code); 166 irq_code_clean(&irq_code); 167 if (irq_cap < 0) { 168 usb_log_error("Failed to register interrupt handler: %s.\n", 169 str_error(irq_cap)); 170 return irq_cap; 171 } 172 173 /* Enable interrupts */ 174 int ret = hcd_ddf_enable_interrupt(hcd, irq); 175 if (ret != EOK) { 176 usb_log_error("Failed to enable interrupts: %s.\n", 177 str_error(ret)); 178 unregister_interrupt_handler(hcd->ddf_dev, irq_cap); 179 return ret; 180 } 181 return irq_cap; 182 } 183 184 /** Initialize HC in memory of the driver. 185 * 186 * @param device DDF instance of the device to use 187 * @return Error code 188 * 189 * This function does all the preparatory work for hc and rh drivers: 190 * - gets device's hw resources 191 * - attempts to enable interrupts 192 * - registers interrupt handler 193 * - calls driver specific initialization 194 * - registers root hub 195 */ 196 int hc_dev_add(ddf_dev_t *device) 197 { 198 int ret = EOK; 199 assert(device); 200 201 if (!hc_driver->hc_add) { 202 usb_log_error("Driver '%s' does not support adding devices.", hc_driver->name); 203 return ENOTSUP; 204 } 205 206 ret = hcd_ddf_setup_hc(device, hc_driver->hc_device_size); 207 if (ret != EOK) { 208 usb_log_error("Failed to setup HC device.\n"); 209 return ret; 210 } 211 212 hc_device_t *hcd = dev_to_hcd(device); 213 214 hw_res_list_parsed_t hw_res; 215 ret = hcd_ddf_get_registers(hcd, &hw_res); 216 if (ret != EOK) { 217 usb_log_error("Failed to get register memory addresses " 218 "for `%s': %s.\n", ddf_dev_get_name(device), 219 str_error(ret)); 220 goto err_hcd; 221 } 222 223 ret = hc_driver->hc_add(hcd, &hw_res); 224 if (ret != EOK) { 225 usb_log_error("Failed to init HCD.\n"); 226 goto err_hw_res; 227 } 228 229 assert(hcd->bus); 230 231 /* Setup interrupts */ 232 hcd->irq_cap = hcd_ddf_setup_interrupts(hcd, &hw_res); 233 if (hcd->irq_cap >= 0) { 234 usb_log_debug("Hw interrupts enabled.\n"); 235 } 236 237 /* Claim the device from BIOS */ 238 if (hc_driver->claim) 239 ret = hc_driver->claim(hcd); 240 if (ret != EOK) { 241 usb_log_error("Failed to claim `%s' for `%s': %s", 242 ddf_dev_get_name(device), hc_driver->name, str_error(ret)); 243 goto err_irq; 244 } 245 246 /* Start hw */ 247 if (hc_driver->start) 248 ret = hc_driver->start(hcd); 249 if (ret != EOK) { 250 usb_log_error("Failed to start HCD: %s.\n", str_error(ret)); 251 goto err_irq; 252 } 253 254 const bus_ops_t *ops = BUS_OPS_LOOKUP(hcd->bus->ops, status); 255 256 /* Need working irq replacement to setup root hub */ 257 if (hcd->irq_cap < 0 && ops) { 258 hcd->polling_fibril = fibril_create(interrupt_polling, hcd->bus); 259 if (!hcd->polling_fibril) { 260 usb_log_error("Failed to create polling fibril\n"); 261 ret = ENOMEM; 262 goto err_started; 263 } 264 fibril_add_ready(hcd->polling_fibril); 265 usb_log_warning("Failed to enable interrupts: %s." 266 " Falling back to polling.\n", str_error(hcd->irq_cap)); 267 } 268 269 /* 270 * Creating root hub registers a new USB device so HC 271 * needs to be ready at this time. 272 */ 273 if (hc_driver->setup_root_hub) 274 ret = hc_driver->setup_root_hub(hcd); 275 if (ret != EOK) { 276 usb_log_error("Failed to setup HC root hub: %s.\n", 277 str_error(ret)); 278 goto err_polling; 279 } 280 281 usb_log_info("Controlling new `%s' device `%s'.\n", 282 hc_driver->name, ddf_dev_get_name(device)); 283 return EOK; 284 285 err_polling: 286 // TODO: Stop the polling fibril (refactor the interrupt_polling func) 287 // 288 err_started: 289 if (hc_driver->stop) 290 hc_driver->stop(hcd); 291 err_irq: 292 unregister_interrupt_handler(device, hcd->irq_cap); 293 if (hc_driver->hc_remove) 294 hc_driver->hc_remove(hcd); 295 err_hw_res: 296 hw_res_list_parsed_clean(&hw_res); 297 err_hcd: 298 hcd_ddf_clean_hc(hcd); 299 return ret; 300 } 301 302 int hc_dev_remove(ddf_dev_t *dev) 303 { 304 int err; 305 hc_device_t *hcd = dev_to_hcd(dev); 306 307 if (hc_driver->stop) 308 if ((err = hc_driver->stop(hcd))) 309 return err; 310 311 unregister_interrupt_handler(dev, hcd->irq_cap); 312 313 if (hc_driver->hc_remove) 314 if ((err = hc_driver->hc_remove(hcd))) 315 return err; 316 317 hcd_ddf_clean_hc(hcd); 318 319 // TODO probably not complete 320 321 return EOK; 322 } 323 324 int hc_dev_gone(ddf_dev_t *dev) 325 { 326 int err = ENOTSUP; 327 hc_device_t *hcd = dev_to_hcd(dev); 328 329 if (hc_driver->hc_gone) 330 err = hc_driver->hc_gone(hcd); 331 332 hcd_ddf_clean_hc(hcd); 333 334 return err; 335 } 336 337 int hc_fun_online(ddf_fun_t *fun) 338 { 339 assert(fun); 340 341 device_t *dev = ddf_fun_data_get(fun); 342 assert(dev); 343 344 usb_log_info("Device(%d): Requested to be brought online.", dev->address); 345 return bus_device_online(dev); 346 } 347 348 int hc_fun_offline(ddf_fun_t *fun) 349 { 350 assert(fun); 351 352 device_t *dev = ddf_fun_data_get(fun); 353 assert(dev); 354 355 usb_log_info("Device(%d): Requested to be taken offline.", dev->address); 356 return bus_device_offline(dev); 65 357 } 66 358 … … 72 364 * @return Max packet size for EP 0 73 365 */ 74 int hcd_get_ep0_max_packet_size(uint16_t *mps, hcd_t *hcd, device_t *dev)366 int hcd_get_ep0_max_packet_size(uint16_t *mps, bus_t *bus, device_t *dev) 75 367 { 76 368 assert(mps); … … 97 389 98 390 usb_log_debug("Requesting first 8B of device descriptor to determine MPS."); 99 ssize_t got = hcd_send_batch_sync(hcd,dev, control_ep, USB_DIRECTION_IN,391 ssize_t got = bus_device_send_batch_sync(dev, control_ep, USB_DIRECTION_IN, 100 392 (char *) &desc, CTRL_PIPE_MIN_PACKET_SIZE, *(uint64_t *)&get_device_desc_8, 101 393 "read first 8 bytes of dev descriptor"); … … 156 448 * 157 449 */ 158 statictoggle_reset_mode_t hcd_get_request_toggle_reset_mode(450 toggle_reset_mode_t hcd_get_request_toggle_reset_mode( 159 451 const usb_device_request_setup_packet_t *request) 160 452 { … … 186 478 } 187 479 188 /** Prepare generic usb_transfer_batch and schedule it.189 * @param hcd Host controller driver.190 * @param target address and endpoint number.191 * @param setup_data Data to use in setup stage (Control communication type)192 * @param in Callback for device to host communication.193 * @param out Callback for host to device communication.194 * @param arg Callback parameter.195 * @param name Communication identifier (for nicer output).196 * @return Error code.197 */198 int hcd_send_batch(hcd_t *hcd, device_t *device, usb_target_t target,199 usb_direction_t direction, char *data, size_t size, uint64_t setup_data,200 usbhc_iface_transfer_callback_t on_complete, void *arg, const char *name)201 {202 assert(hcd);203 assert(device->address == target.address);204 205 if (!hcd->ops.schedule) {206 usb_log_error("HCD does not implement scheduler.\n");207 return ENOTSUP;208 }209 210 endpoint_t *ep = bus_find_endpoint(device, target, direction);211 if (ep == NULL) {212 usb_log_error("Endpoint(%d:%d) not registered for %s.\n",213 device->address, target.endpoint, name);214 return ENOENT;215 }216 217 // TODO cut here aka provide helper to call with instance of endpoint_t in hand218 assert(ep->device == device);219 220 usb_log_debug2("%s %d:%d %zu(%zu).\n",221 name, target.address, target.endpoint, size, ep->max_packet_size);222 223 const size_t bw = endpoint_count_bw(ep, size);224 /* Check if we have enough bandwidth reserved */225 if (ep->bandwidth < bw) {226 usb_log_error("Endpoint(%d:%d) %s needs %zu bw "227 "but only %zu is reserved.\n",228 device->address, ep->endpoint, name, bw, ep->bandwidth);229 return ENOSPC;230 }231 232 usb_transfer_batch_t *batch = usb_transfer_batch_create(ep);233 if (!batch) {234 usb_log_error("Failed to create transfer batch.\n");235 return ENOMEM;236 }237 238 batch->target = target;239 batch->buffer = data;240 batch->buffer_size = size;241 batch->setup.packed = setup_data;242 batch->dir = direction;243 batch->on_complete = on_complete;244 batch->on_complete_data = arg;245 246 /* Check for commands that reset toggle bit */247 if (ep->transfer_type == USB_TRANSFER_CONTROL)248 batch->toggle_reset_mode249 = hcd_get_request_toggle_reset_mode(&batch->setup.packet);250 251 const int ret = hcd->ops.schedule(hcd, batch);252 if (ret != EOK) {253 usb_log_warning("Batch %p failed to schedule: %s", batch, str_error(ret));254 usb_transfer_batch_destroy(batch);255 }256 257 /* Drop our own reference to ep. */258 endpoint_del_ref(ep);259 260 return ret;261 }262 263 typedef struct {264 fibril_mutex_t done_mtx;265 fibril_condvar_t done_cv;266 unsigned done;267 268 size_t transfered_size;269 int error;270 } sync_data_t;271 272 static int sync_transfer_complete(void *arg, int error, size_t transfered_size)273 {274 sync_data_t *d = arg;275 assert(d);276 d->transfered_size = transfered_size;277 d->error = error;278 fibril_mutex_lock(&d->done_mtx);279 d->done = 1;280 fibril_condvar_broadcast(&d->done_cv);281 fibril_mutex_unlock(&d->done_mtx);282 return EOK;283 }284 285 ssize_t hcd_send_batch_sync(hcd_t *hcd, device_t *device, usb_target_t target,286 usb_direction_t direction, char *data, size_t size, uint64_t setup_data,287 const char *name)288 {289 assert(hcd);290 sync_data_t sd = { .done = 0 };291 fibril_mutex_initialize(&sd.done_mtx);292 fibril_condvar_initialize(&sd.done_cv);293 294 const int ret = hcd_send_batch(hcd, device, target, direction,295 data, size, setup_data,296 sync_transfer_complete, &sd, name);297 if (ret != EOK)298 return ret;299 300 fibril_mutex_lock(&sd.done_mtx);301 while (!sd.done)302 fibril_condvar_wait(&sd.done_cv, &sd.done_mtx);303 fibril_mutex_unlock(&sd.done_mtx);304 305 return (sd.error == EOK)306 ? (ssize_t) sd.transfered_size307 : (ssize_t) sd.error;308 }309 310 480 311 481 /** -
uspace/lib/usbhost/src/usb2_bus.c
r1ea0bbf r32fb6bce 205 205 206 206 usb2_bus_t *bus = (usb2_bus_t *) dev->bus; 207 hcd_t *hcd = (hcd_t *) bus->base.hcd;208 207 209 208 /* The default address is currently reserved for this device */ … … 231 230 232 231 uint16_t max_packet_size; 233 if ((err = hcd_get_ep0_max_packet_size(&max_packet_size, hcd, dev)))232 if ((err = hcd_get_ep0_max_packet_size(&max_packet_size, &bus->base, dev))) 234 233 goto err_address; 235 234 … … 238 237 239 238 usb_log_debug("Device(%d): Setting USB address.", address); 240 err = hcd_send_batch_sync(hcd,dev, usb2_default_target, USB_DIRECTION_OUT,239 err = bus_device_send_batch_sync(dev, usb2_default_target, USB_DIRECTION_OUT, 241 240 NULL, 0, *(uint64_t *)&set_address, "set address"); 242 241 if (err != 0) { … … 315 314 316 315 /* Read the device descriptor, derive the match ids */ 317 if ((err = hcd_d df_device_explore(dev))) {316 if ((err = hcd_device_explore(dev))) { 318 317 usb_log_error("Device(%d): Failed to explore device: %s", dev->address, str_error(err)); 319 318 release_address(bus, dev->address); … … 463 462 * @return Error code. 464 463 */ 465 int usb2_bus_init(usb2_bus_t *bus, hcd_t *hcd,size_t available_bandwidth)464 int usb2_bus_init(usb2_bus_t *bus, size_t available_bandwidth) 466 465 { 467 466 assert(bus); 468 467 469 bus_init(&bus->base, hcd,sizeof(device_t));468 bus_init(&bus->base, sizeof(device_t)); 470 469 bus->base.ops = &usb2_bus_ops; 471 470
Note:
See TracChangeset
for help on using the changeset viewer.