Changeset 32fb6bce in mainline for uspace/drv/bus/usb/ehci
- Timestamp:
- 2017-12-18T22:50:21Z (8 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/drv/bus/usb/ehci
- Files:
-
- 7 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
Note:
See TracChangeset
for help on using the changeset viewer.
