Changes in uspace/drv/bus/usb/ohci/hc.c [f5bfd98:7de1988c] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/hc.c
rf5bfd98 r7de1988c 34 34 */ 35 35 36 #include <assert.h>37 #include <async.h>38 36 #include <errno.h> 39 #include <macros.h> 40 #include <mem.h> 41 #include <stdlib.h> 37 #include <stdbool.h> 42 38 #include <str_error.h> 43 #include <sys/types.h> 39 #include <adt/list.h> 40 #include <libarch/ddi.h> 44 41 45 42 #include <usb/debug.h> 46 43 #include <usb/usb.h> 47 44 #include <usb/ddfiface.h> 45 46 #include "hc.h" 48 47 #include "ohci_endpoint.h" 49 #include "ohci_batch.h"50 #include "utils/malloc32.h"51 52 #include "hc.h"53 48 54 49 #define OHCI_USED_INTERRUPTS \ … … 89 84 }; 90 85 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 91 96 static void hc_gain_control(hc_t *instance); 92 97 static void hc_start(hc_t *instance); … … 94 99 static int hc_init_memory(hc_t *instance); 95 100 static int interrupt_emulator(hc_t *instance); 101 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch); 96 102 97 103 /** Generate IRQ code. … … 104 110 * @return Error code. 105 111 */ 106 int hc_gen_irq_code(irq_code_t *code, addr_range_t *regs) 107 { 108 assert(code); 109 if (RNGSZ(*regs) < sizeof(ohci_regs_t)) 112 int 113 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) 115 { 116 if ((ranges_size < sizeof(ohci_pio_ranges)) || 117 (cmds_size < sizeof(ohci_irq_commands)) || 118 (RNGSZ(*regs) < sizeof(ohci_regs_t))) 110 119 return EOVERFLOW; 111 120 112 code->ranges = malloc(sizeof(ohci_pio_ranges)); 113 if (code->ranges == NULL) 114 return ENOMEM; 115 116 code->cmds = malloc(sizeof(ohci_irq_commands)); 117 if (code->cmds == NULL) { 118 free(code->ranges); 119 return ENOMEM; 120 } 121 122 code->rangecount = ARRAY_SIZE(ohci_pio_ranges); 123 code->cmdcount = ARRAY_SIZE(ohci_irq_commands); 124 125 memcpy(code->ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges)); 126 code->ranges[0].base = RNGABS(*regs); 127 128 memcpy(code->cmds, ohci_irq_commands, sizeof(ohci_irq_commands)); 121 memcpy(ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges)); 122 ranges[0].base = RNGABS(*regs); 123 124 memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands)); 129 125 ohci_regs_t *registers = (ohci_regs_t *) RNGABSPTR(*regs); 130 code->cmds[0].addr = (void *) ®isters->interrupt_status; 131 code->cmds[3].addr = (void *) ®isters->interrupt_status; 132 OHCI_WR(code->cmds[1].value, OHCI_USED_INTERRUPTS); 133 134 return EOK; 126 cmds[0].addr = (void *) ®isters->interrupt_status; 127 cmds[3].addr = (void *) ®isters->interrupt_status; 128 OHCI_WR(cmds[1].value, OHCI_USED_INTERRUPTS); 129 130 return EOK; 131 } 132 133 /** Register interrupt handler. 134 * 135 * @param[in] device Host controller DDF device 136 * @param[in] regs Register range 137 * @param[in] irq Interrupt number 138 * @paran[in] handler Interrupt handler 139 * 140 * @return EOK on success or negative error code 141 */ 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_cmds 155 }; 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 DDF 177 * 178 * @param[in] instance OHCI driver intance 179 * @param[in] hub_fun DDF fuction representing OHCI root hub 180 * @return Error code 181 */ 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; 135 254 } 136 255 … … 146 265 assert(instance); 147 266 148 int r et= pio_enable_range(regs, (void **) &instance->registers);149 if (r et!= EOK) {267 int rc = pio_enable_range(regs, (void **) &instance->registers); 268 if (rc != EOK) { 150 269 usb_log_error("Failed to gain access to device registers: %s.\n", 151 str_error(r et));152 return r et;270 str_error(rc)); 271 return rc; 153 272 } 154 273 155 274 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) { 285 usb_log_error("Failed to create OHCI memory structures: %s.\n", 286 str_error(rc)); 287 return rc; 288 } 289 156 290 fibril_mutex_initialize(&instance->guard); 157 158 ret = hc_init_memory(instance);159 if (ret != EOK) {160 usb_log_error("Failed to create OHCI memory structures: %s.\n",161 str_error(ret));162 return ret;163 }164 291 165 292 hc_gain_control(instance); … … 171 298 } 172 299 173 ohci_rh_init(&instance->rh, instance->registers, "ohci rh");300 rh_init(&instance->rh, instance->registers); 174 301 hc_start(instance); 175 302 … … 254 381 { 255 382 assert(hcd); 256 hc_t *instance = hcd-> driver.data;383 hc_t *instance = hcd->private_data; 257 384 assert(instance); 258 385 259 386 /* Check for root hub communication */ 260 if (batch->ep->address == ohci_rh_get_address(&instance->rh)) {387 if (batch->ep->address == instance->rh.address) { 261 388 usb_log_debug("OHCI root hub request.\n"); 262 return ohci_rh_schedule(&instance->rh, batch); 389 rh_request(&instance->rh, batch); 390 return EOK; 263 391 } 264 392 ohci_transfer_batch_t *ohci_batch = ohci_transfer_batch_get(batch); … … 299 427 usb_log_debug2("OHCI(%p) interrupt: %x.\n", instance, status); 300 428 if (status & I_RHSC) 301 ohci_rh_interrupt(&instance->rh);429 rh_interrupt(&instance->rh); 302 430 303 431 if (status & I_WDH) { … … 384 512 OHCI_SET(instance->registers->command_status, CS_OCR); 385 513 /* Hope that SMM actually knows its stuff or we can hang here */ 386 while (OHCI_RD(instance->registers->control ) & C_IR) {514 while (OHCI_RD(instance->registers->control & C_IR)) { 387 515 async_usleep(1000); 388 516 } … … 497 625 do { \ 498 626 const char *name = usb_str_transfer_type(type); \ 499 constint ret = endpoint_list_init(&instance->lists[type], name); \627 int ret = endpoint_list_init(&instance->lists[type], name); \ 500 628 if (ret != EOK) { \ 501 629 usb_log_error("Failed to setup %s endpoint list: %s.\n", \
Note:
See TracChangeset
for help on using the changeset viewer.