Changeset e4d7363 in mainline for uspace/drv/bus/usb/xhci/hc.c
- Timestamp:
- 2017-06-22T21:34:39Z (8 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 91ca111
- Parents:
- cb89430
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/xhci/hc.c
rcb89430 re4d7363 37 37 #include <str_error.h> 38 38 #include <usb/debug.h> 39 #include <usb/host/ddf_helpers.h>40 39 #include <usb/host/utils/malloc32.h> 41 40 #include "debug.h" … … 70 69 }; 71 70 71 int hc_init_mmio(xhci_hc_t *hc, const hw_res_list_parsed_t *hw_res) 72 { 73 int err; 74 75 if (hw_res->mem_ranges.count != 1) { 76 usb_log_error("Unexpected MMIO area, bailing out."); 77 return EINVAL; 78 } 79 80 hc->mmio_range = hw_res->mem_ranges.ranges[0]; 81 82 usb_log_debug("MMIO area at %p (size %zu), IRQ %d.\n", 83 RNGABSPTR(hc->mmio_range), RNGSZ(hc->mmio_range), hw_res->irqs.irqs[0]); 84 85 if (RNGSZ(hc->mmio_range) < sizeof(xhci_cap_regs_t)) 86 return EOVERFLOW; 87 88 void *base; 89 if ((err = pio_enable_range(&hc->mmio_range, &base))) 90 return err; 91 92 hc->cap_regs = (xhci_cap_regs_t *) base; 93 hc->op_regs = (xhci_op_regs_t *) (base + XHCI_REG_RD(hc->cap_regs, XHCI_CAP_LENGTH)); 94 hc->rt_regs = (xhci_rt_regs_t *) (base + XHCI_REG_RD(hc->cap_regs, XHCI_CAP_RTSOFF)); 95 hc->db_arry = (xhci_doorbell_t *) (base + XHCI_REG_RD(hc->cap_regs, XHCI_CAP_DBOFF)); 96 97 usb_log_debug2("Initialized MMIO reg areas:"); 98 usb_log_debug2("\tCapability regs: %p", hc->cap_regs); 99 usb_log_debug2("\tOperational regs: %p", hc->op_regs); 100 usb_log_debug2("\tRuntime regs: %p", hc->rt_regs); 101 usb_log_debug2("\tDoorbell array base: %p", hc->db_arry); 102 103 xhci_dump_cap_regs(hc->cap_regs); 104 105 hc->ac64 = XHCI_REG_RD(hc->cap_regs, XHCI_CAP_AC64); 106 hc->max_slots = XHCI_REG_RD(hc->cap_regs, XHCI_CAP_MAX_SLOTS); 107 108 return EOK; 109 } 110 111 int hc_init_memory(xhci_hc_t *hc) 112 { 113 int err; 114 115 hc->dcbaa = malloc32((1 + hc->max_slots) * sizeof(xhci_device_ctx_t)); 116 if (!hc->dcbaa) 117 return ENOMEM; 118 119 if ((err = xhci_trb_ring_init(&hc->command_ring, hc))) 120 goto err_dcbaa; 121 122 if ((err = xhci_event_ring_init(&hc->event_ring, hc))) 123 goto err_cmd_ring; 124 125 // TODO: Allocate scratchpad buffers 126 127 return EOK; 128 129 xhci_event_ring_fini(&hc->event_ring); 130 err_cmd_ring: 131 xhci_trb_ring_fini(&hc->command_ring); 132 err_dcbaa: 133 free32(hc->dcbaa); 134 return err; 135 } 136 137 72 138 /** 73 139 * Generates code to accept interrupts. The xHCI is designed primarily for … … 75 141 * (except 0) are disabled. 76 142 */ 77 static int hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res) 78 { 79 int err; 80 143 int hc_irq_code_gen(irq_code_t *code, xhci_hc_t *hc, const hw_res_list_parsed_t *hw_res) 144 { 81 145 assert(code); 82 146 assert(hw_res); 83 147 84 if (hw_res->irqs.count != 1 || hw_res->mem_ranges.count != 1) {148 if (hw_res->irqs.count != 1) { 85 149 usb_log_info("Unexpected HW resources to enable interrupts."); 86 150 return EINVAL; … … 88 152 89 153 addr_range_t mmio_range = hw_res->mem_ranges.ranges[0]; 90 91 if (RNGSZ(mmio_range) < sizeof(xhci_cap_regs_t))92 return EOVERFLOW;93 94 95 xhci_cap_regs_t *cap_regs = NULL;96 if ((err = pio_enable_range(&mmio_range, (void **)&cap_regs)))97 return EIO;98 154 99 155 code->ranges = malloc(sizeof(irq_pio_range_t)); … … 116 172 memcpy(code->cmds, irq_commands, sizeof(irq_commands)); 117 173 118 void *intr0_iman = RNGABSPTR(mmio_range) + XHCI_REG_RD( cap_regs, XHCI_CAP_RTSOFF) + offsetof(xhci_rt_regs_t, ir[0]);174 void *intr0_iman = RNGABSPTR(mmio_range) + XHCI_REG_RD(hc->cap_regs, XHCI_CAP_RTSOFF) + offsetof(xhci_rt_regs_t, ir[0]); 119 175 code->cmds[0].addr = intr0_iman; 120 176 code->cmds[3].addr = intr0_iman; … … 124 180 } 125 181 126 static int hc_claim(ddf_dev_t *dev)127 { 128 // TODO: impl ement handoff: section 4.22.1182 int hc_claim(xhci_hc_t *hc, ddf_dev_t *dev) 183 { 184 // TODO: impl 129 185 return EOK; 130 186 } … … 152 208 * Initialize the HC: section 4.2 153 209 */ 154 staticint hc_start(xhci_hc_t *hc, bool irq)210 int hc_start(xhci_hc_t *hc, bool irq) 155 211 { 156 212 int err; … … 191 247 } 192 248 193 static int hc_init(hcd_t *hcd, const hw_res_list_parsed_t *hw_res, bool irq) 194 { 195 int err; 196 197 assert(hcd); 198 assert(hw_res); 199 assert(hcd_get_driver_data(hcd) == NULL); 200 201 /* Initialize the MMIO ranges */ 202 if (hw_res->mem_ranges.count != 1) { 203 usb_log_error("Unexpected MMIO area, bailing out."); 204 return EINVAL; 205 } 206 207 addr_range_t mmio_range = hw_res->mem_ranges.ranges[0]; 208 209 usb_log_debug("MMIO area at %p (size %zu), IRQ %d.\n", 210 RNGABSPTR(mmio_range), RNGSZ(mmio_range), hw_res->irqs.irqs[0]); 211 212 if (RNGSZ(mmio_range) < sizeof(xhci_cap_regs_t)) 213 return EOVERFLOW; 214 215 void *base; 216 if ((err = pio_enable_range(&mmio_range, &base))) 217 return err; 218 219 xhci_hc_t *hc = malloc(sizeof(xhci_hc_t)); 220 if (!hc) 221 return ENOMEM; 222 223 hc->cap_regs = (xhci_cap_regs_t *) base; 224 hc->op_regs = (xhci_op_regs_t *) (base + XHCI_REG_RD(hc->cap_regs, XHCI_CAP_LENGTH)); 225 hc->rt_regs = (xhci_rt_regs_t *) (base + XHCI_REG_RD(hc->cap_regs, XHCI_CAP_RTSOFF)); 226 hc->db_arry = (xhci_doorbell_t *) (base + XHCI_REG_RD(hc->cap_regs, XHCI_CAP_DBOFF)); 227 228 usb_log_debug2("Initialized MMIO reg areas:"); 229 usb_log_debug2("\tCapability regs: %p", hc->cap_regs); 230 usb_log_debug2("\tOperational regs: %p", hc->op_regs); 231 usb_log_debug2("\tRuntime regs: %p", hc->rt_regs); 232 usb_log_debug2("\tDoorbell array base: %p", hc->db_arry); 233 234 xhci_dump_cap_regs(hc->cap_regs); 235 236 hc->ac64 = XHCI_REG_RD(hc->cap_regs, XHCI_CAP_AC64); 237 hc->max_slots = XHCI_REG_RD(hc->cap_regs, XHCI_CAP_MAX_SLOTS); 238 239 hc->dcbaa = malloc32((1 + hc->max_slots) * sizeof(xhci_device_ctx_t)); 240 if (!hc->dcbaa) 241 goto err_hc; 242 243 if ((err = xhci_trb_ring_init(&hc->command_ring, hc))) 244 goto err_dcbaa; 245 246 if ((err = xhci_event_ring_init(&hc->event_ring, hc))) 247 goto err_cmd_ring; 248 249 // TODO: Allocate scratchpad buffers 250 251 hcd_set_implementation(hcd, hc, &xhci_ddf_hc_driver.ops); 252 253 if ((err = hc_start(hc, irq))) 254 goto err_event_ring; 255 256 return EOK; 257 258 err_event_ring: 259 xhci_event_ring_fini(&hc->event_ring); 260 err_cmd_ring: 261 xhci_trb_ring_fini(&hc->command_ring); 262 err_dcbaa: 263 free32(hc->dcbaa); 264 err_hc: 265 free(hc); 266 hcd_set_implementation(hcd, NULL, NULL); 267 return err; 268 } 269 270 static int hc_status(hcd_t *hcd, uint32_t *status) 271 { 272 xhci_hc_t *hc = hcd_get_driver_data(hcd); 273 assert(hc); 274 assert(status); 275 276 *status = 0; 277 if (hc->op_regs) { 278 *status = XHCI_REG_RD(hc->op_regs, XHCI_OP_STATUS); 279 XHCI_REG_WR(hc->op_regs, XHCI_OP_STATUS, *status & XHCI_STATUS_ACK_MASK); 280 } 249 int hc_status(xhci_hc_t *hc, uint32_t *status) 250 { 251 *status = XHCI_REG_RD(hc->op_regs, XHCI_OP_STATUS); 252 XHCI_REG_WR(hc->op_regs, XHCI_OP_STATUS, *status & XHCI_STATUS_ACK_MASK); 253 281 254 usb_log_debug2("HC(%p): Read status: %x", hc, *status); 282 255 return EOK; … … 305 278 } 306 279 307 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch) 308 { 309 xhci_hc_t *hc = hcd_get_driver_data(hcd); 310 assert(hc); 311 280 int hc_schedule(xhci_hc_t *hc, usb_transfer_batch_t *batch) 281 { 312 282 xhci_dump_state(hc); 313 283 send_no_op_command(hc); … … 346 316 } 347 317 348 static void hc_interrupt(hcd_t *hcd, uint32_t status) 349 { 350 xhci_hc_t *hc = hcd_get_driver_data(hcd); 351 assert(hc); 352 318 void hc_interrupt(xhci_hc_t *hc, uint32_t status) 319 { 353 320 if (status & XHCI_REG_MASK(XHCI_OP_HSE)) { 354 321 usb_log_error("Host controller error occured. Bad things gonna happen..."); … … 375 342 } 376 343 377 static void hc_fini(hcd_t *hcd) 378 { 379 xhci_hc_t *hc = hcd_get_driver_data(hcd); 380 assert(hc); 381 382 usb_log_info("Finishing"); 383 344 void hc_fini(xhci_hc_t *hc) 345 { 384 346 xhci_trb_ring_fini(&hc->command_ring); 385 347 xhci_event_ring_fini(&hc->event_ring); 386 387 free(hc); 388 hcd_set_implementation(hcd, NULL, NULL); 389 } 390 391 const ddf_hc_driver_t xhci_ddf_hc_driver = { 392 .hc_speed = USB_SPEED_SUPER, 393 .irq_code_gen = hc_gen_irq_code, 394 .claim = hc_claim, 395 .init = hc_init, 396 .fini = hc_fini, 397 .name = "XHCI-PCI", 398 .ops = { 399 .schedule = hc_schedule, 400 .irq_hook = hc_interrupt, 401 .status_hook = hc_status, 402 } 403 }; 348 usb_log_info("HC(%p): Finalized.", hc); 349 } 404 350 405 351
Note:
See TracChangeset
for help on using the changeset viewer.