Changes in uspace/drv/bus/usb/ohci/hc.c [7de1988c:6340a6ff] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/hc.c
r7de1988c r6340a6ff 35 35 36 36 #include <errno.h> 37 #include <stdbool.h>38 37 #include <str_error.h> 39 38 #include <adt/list.h> … … 42 41 #include <usb/debug.h> 43 42 #include <usb/usb.h> 44 #include <usb/ddfiface.h>45 43 46 44 #include "hc.h" … … 84 82 }; 85 83 86 enum {87 /** Number of PIO ranges used in IRQ code */88 hc_irq_pio_range_count =89 sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t),90 91 /** Number of commands used in IRQ code */92 hc_irq_cmd_count =93 sizeof(ohci_irq_commands) / sizeof(irq_cmd_t)94 };95 96 84 static void hc_gain_control(hc_t *instance); 97 85 static void hc_start(hc_t *instance); … … 99 87 static int hc_init_memory(hc_t *instance); 100 88 static int interrupt_emulator(hc_t *instance); 101 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch); 89 90 /** Get number of PIO ranges used in IRQ code. 91 * @return Number of ranges. 92 */ 93 size_t hc_irq_pio_range_count(void) 94 { 95 return sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t); 96 } 97 98 /** Get number of commands used in IRQ code. 99 * @return Number of commands. 100 */ 101 size_t hc_irq_cmd_count(void) 102 { 103 return sizeof(ohci_irq_commands) / sizeof(irq_cmd_t); 104 } 102 105 103 106 /** Generate IRQ code. … … 106 109 * @param[out] cmds Commands buffer. 107 110 * @param[in] cmds_size Size of the commands buffer (bytes). 108 * @param[in] regs Device's register range. 111 * @param[in] regs Physical address of device's registers. 112 * @param[in] reg_size Size of the register area (bytes). 109 113 * 110 114 * @return Error code. … … 112 116 int 113 117 hc_get_irq_code(irq_pio_range_t ranges[], size_t ranges_size, irq_cmd_t cmds[], 114 size_t cmds_size, addr_range_t *regs)118 size_t cmds_size, uintptr_t regs, size_t reg_size) 115 119 { 116 120 if ((ranges_size < sizeof(ohci_pio_ranges)) || 117 121 (cmds_size < sizeof(ohci_irq_commands)) || 118 ( RNGSZ(*regs)< sizeof(ohci_regs_t)))122 (reg_size < sizeof(ohci_regs_t))) 119 123 return EOVERFLOW; 120 124 121 125 memcpy(ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges)); 122 ranges[0].base = RNGABS(*regs);126 ranges[0].base = regs; 123 127 124 128 memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands)); 125 ohci_regs_t *registers = (ohci_regs_t *) RNGABSPTR(*regs);129 ohci_regs_t *registers = (ohci_regs_t *) regs; 126 130 cmds[0].addr = (void *) ®isters->interrupt_status; 127 131 cmds[3].addr = (void *) ®isters->interrupt_status; … … 131 135 } 132 136 133 /** Register interrupt handler.134 *135 * @param[in] device Host controller DDF device136 * @param[in] regs Register range137 * @param[in] irq Interrupt number138 * @paran[in] handler Interrupt handler139 *140 * @return EOK on success or negative error code141 */142 int hc_register_irq_handler(ddf_dev_t *device, addr_range_t *regs, int irq,143 interrupt_handler_t handler)144 {145 int rc;146 147 irq_pio_range_t irq_ranges[hc_irq_pio_range_count];148 irq_cmd_t irq_cmds[hc_irq_cmd_count];149 150 irq_code_t irq_code = {151 .rangecount = hc_irq_pio_range_count,152 .ranges = irq_ranges,153 .cmdcount = hc_irq_cmd_count,154 .cmds = irq_cmds155 };156 157 rc = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds,158 sizeof(irq_cmds), regs);159 if (rc != EOK) {160 usb_log_error("Failed to generate IRQ code: %s.\n",161 str_error(rc));162 return rc;163 }164 165 /* Register handler to avoid interrupt lockup */166 rc = register_interrupt_handler(device, irq, handler, &irq_code);167 if (rc != EOK) {168 usb_log_error("Failed to register interrupt handler: %s.\n",169 str_error(rc));170 return rc;171 }172 173 return EOK;174 }175 176 /** Announce OHCI root hub to the DDF177 *178 * @param[in] instance OHCI driver intance179 * @param[in] hub_fun DDF fuction representing OHCI root hub180 * @return Error code181 */182 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun)183 {184 bool addr_reqd = false;185 bool ep_added = false;186 bool fun_bound = false;187 int rc;188 189 assert(instance);190 assert(hub_fun);191 192 /* Try to get address 1 for root hub. */193 instance->rh.address = 1;194 rc = usb_device_manager_request_address(195 &instance->generic.dev_manager, &instance->rh.address, false,196 USB_SPEED_FULL);197 if (rc != EOK) {198 usb_log_error("Failed to get OHCI root hub address: %s\n",199 str_error(rc));200 goto error;201 }202 203 addr_reqd = true;204 205 rc = usb_endpoint_manager_add_ep(206 &instance->generic.ep_manager, instance->rh.address, 0,207 USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64,208 0, NULL, NULL);209 if (rc != EOK) {210 usb_log_error("Failed to register root hub control endpoint: %s.\n",211 str_error(rc));212 goto error;213 }214 215 ep_added = true;216 217 rc = ddf_fun_add_match_id(hub_fun, "usb&class=hub", 100);218 if (rc != EOK) {219 usb_log_error("Failed to add root hub match-id: %s.\n",220 str_error(rc));221 goto error;222 }223 224 rc = ddf_fun_bind(hub_fun);225 if (rc != EOK) {226 usb_log_error("Failed to bind root hub function: %s.\n",227 str_error(rc));228 goto error;229 }230 231 fun_bound = true;232 233 rc = usb_device_manager_bind_address(&instance->generic.dev_manager,234 instance->rh.address, ddf_fun_get_handle(hub_fun));235 if (rc != EOK) {236 usb_log_warning("Failed to bind root hub address: %s.\n",237 str_error(rc));238 }239 240 return EOK;241 error:242 if (fun_bound)243 ddf_fun_unbind(hub_fun);244 if (ep_added) {245 usb_endpoint_manager_remove_ep(246 &instance->generic.ep_manager, instance->rh.address, 0,247 USB_DIRECTION_BOTH, NULL, NULL);248 }249 if (addr_reqd) {250 usb_device_manager_release_address(251 &instance->generic.dev_manager, instance->rh.address);252 }253 return rc;254 }255 256 137 /** Initialize OHCI hc driver structure 257 138 * 258 139 * @param[in] instance Memory place for the structure. 259 * @param[in] regs Device's I/O registers range. 140 * @param[in] regs Address of the memory mapped I/O registers. 141 * @param[in] reg_size Size of the memory mapped area. 260 142 * @param[in] interrupts True if w interrupts should be used 261 143 * @return Error code 262 144 */ 263 int hc_init(hc_t *instance, addr_range_t *regs, bool interrupts) 264 { 265 assert(instance); 266 267 int rc = pio_enable_range(regs, (void **) &instance->registers); 268 if (rc != EOK) { 269 usb_log_error("Failed to gain access to device registers: %s.\n", 270 str_error(rc)); 271 return rc; 145 int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts) 146 { 147 assert(instance); 148 149 int ret = 150 pio_enable((void*)regs, reg_size, (void**)&instance->registers); 151 if (ret != EOK) { 152 usb_log_error("Failed to enable access to device regss: %s.\n", 153 str_error(ret)); 154 return ret; 272 155 } 273 156 274 157 list_initialize(&instance->pending_batches); 275 276 hcd_init(&instance->generic, USB_SPEED_FULL, 277 BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11); 278 instance->generic.private_data = instance; 279 instance->generic.schedule = hc_schedule; 280 instance->generic.ep_add_hook = ohci_endpoint_init; 281 instance->generic.ep_remove_hook = ohci_endpoint_fini; 282 283 rc = hc_init_memory(instance); 284 if (rc != EOK) { 158 fibril_mutex_initialize(&instance->guard); 159 160 ret = hc_init_memory(instance); 161 if (ret != EOK) { 285 162 usb_log_error("Failed to create OHCI memory structures: %s.\n", 286 str_error(rc)); 287 return rc; 288 } 289 290 fibril_mutex_initialize(&instance->guard); 163 str_error(ret)); 164 return ret; 165 } 291 166 292 167 hc_gain_control(instance); … … 298 173 } 299 174 300 rh_init(&instance->rh, instance->registers);175 ohci_rh_init(&instance->rh, instance->registers, "ohci rh"); 301 176 hc_start(instance); 302 177 … … 385 260 386 261 /* Check for root hub communication */ 387 if (batch->ep->address == instance->rh.address) {262 if (batch->ep->address == ohci_rh_get_address(&instance->rh)) { 388 263 usb_log_debug("OHCI root hub request.\n"); 389 rh_request(&instance->rh, batch); 390 return EOK; 264 return ohci_rh_schedule(&instance->rh, batch); 391 265 } 392 266 ohci_transfer_batch_t *ohci_batch = ohci_transfer_batch_get(batch); … … 427 301 usb_log_debug2("OHCI(%p) interrupt: %x.\n", instance, status); 428 302 if (status & I_RHSC) 429 rh_interrupt(&instance->rh);303 ohci_rh_interrupt(&instance->rh); 430 304 431 305 if (status & I_WDH) { … … 625 499 do { \ 626 500 const char *name = usb_str_transfer_type(type); \ 627 int ret = endpoint_list_init(&instance->lists[type], name); \501 const int ret = endpoint_list_init(&instance->lists[type], name); \ 628 502 if (ret != EOK) { \ 629 503 usb_log_error("Failed to setup %s endpoint list: %s.\n", \
Note:
See TracChangeset
for help on using the changeset viewer.