Changeset e4d7363 in mainline
- 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
- Location:
- uspace
- Files:
-
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ehci/hc.c
rcb89430 re4d7363 89 89 }; 90 90 91 static void hc_start(hc_t *instance);92 91 static int hc_init_memory(hc_t *instance); 93 92 … … 98 97 * @return Error code. 99 98 */ 100 int ehci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res)99 int ehci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res) 101 100 { 102 101 assert(code); 103 102 assert(hw_res); 103 104 hc_t *instance = hcd_get_driver_data(hcd); 104 105 105 106 if (hw_res->irqs.count != 1 || hw_res->mem_ranges.count != 1) … … 128 129 129 130 memcpy(code->cmds, ehci_irq_commands, sizeof(ehci_irq_commands)); 130 ehci_caps_regs_t *caps = NULL; 131 132 int ret = pio_enable_range(®s, (void**)&caps); 133 if (ret != EOK) { 134 free(code->ranges); 135 free(code->cmds); 136 return ret; 137 } 138 139 ehci_regs_t *registers = 140 (ehci_regs_t *)(RNGABSPTR(regs) + EHCI_RD8(caps->caplength)); 141 code->cmds[0].addr = (void *) ®isters->usbsts; 142 code->cmds[3].addr = (void *) ®isters->usbsts; 131 132 code->cmds[0].addr = (void *) &instance->registers->usbsts; 133 code->cmds[3].addr = (void *) &instance->registers->usbsts; 143 134 EHCI_WR(code->cmds[1].value, EHCI_USED_INTERRUPTS); 144 135 … … 156 147 * @return Error code 157 148 */ 158 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res , bool interrupts)149 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res) 159 150 { 160 151 assert(instance); … … 172 163 return ret; 173 164 } 165 174 166 usb_log_info("HC(%p): Device registers at %"PRIx64" (%zuB) accessible.", 175 167 instance, hw_res->mem_ranges.ranges[0].address.absolute, … … 195 187 ehci_rh_init( 196 188 &instance->rh, instance->caps, instance->registers, "ehci rh"); 197 usb_log_debug("HC(%p): Starting HW.", instance);198 hc_start(instance);199 189 200 190 return EOK; … … 368 358 * @param[in] instance EHCI hc driver structure. 369 359 */ 370 void hc_start(hc_t *instance) 371 { 372 assert(instance); 360 int hc_start(hc_t *instance, bool interrupts) 361 { 362 assert(instance); 363 usb_log_debug("HC(%p): Starting HW.", instance); 364 373 365 /* Turn off the HC if it's running, Reseting a running device is 374 366 * undefined */ … … 435 427 EHCI_WR(instance->registers->usbsts, EHCI_RD(instance->registers->usbsts)); 436 428 EHCI_WR(instance->registers->usbintr, EHCI_USED_INTERRUPTS); 429 430 return EOK; 437 431 } 438 432 -
uspace/drv/bus/usb/ehci/hc.h
rcb89430 re4d7363 82 82 } hc_t; 83 83 84 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts); 84 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res); 85 int hc_start(hc_t *instance, bool interrupts); 85 86 void hc_fini(hc_t *instance); 86 87 … … 88 89 void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep); 89 90 90 int ehci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res);91 int ehci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res); 91 92 92 93 void ehci_hc_interrupt(hcd_t *hcd, uint32_t status); -
uspace/drv/bus/usb/ehci/main.c
rcb89430 re4d7363 52 52 #define NAME "ehci" 53 53 54 static int ehci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool); 54 static int ehci_driver_init(hcd_t *, const hw_res_list_parsed_t *); 55 static int ehci_driver_claim(hcd_t *, ddf_dev_t *); 56 static int ehci_driver_start(hcd_t *, bool); 55 57 static void ehci_driver_fini(hcd_t *); 56 58 57 59 static const ddf_hc_driver_t ehci_hc_driver = { 58 .claim = disable_legacy,59 60 .hc_speed = USB_SPEED_HIGH, 61 .name = "EHCI-PCI", 62 .init = ehci_driver_init, 60 63 .irq_code_gen = ehci_hc_gen_irq_code, 61 .init = ehci_driver_init, 64 .claim = ehci_driver_claim, 65 .start = ehci_driver_start, 62 66 .fini = ehci_driver_fini, 63 .name = "EHCI-PCI",64 67 .ops = { 65 68 .schedule = ehci_hc_schedule, … … 72 75 73 76 74 static int ehci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, 75 bool irq) 77 static int ehci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res) 76 78 { 77 79 assert(hcd); … … 82 84 return ENOMEM; 83 85 84 const int ret = hc_init(instance, res , irq);86 const int ret = hc_init(instance, res); 85 87 if (ret == EOK) { 86 88 hcd_set_implementation(hcd, instance, &ehci_hc_driver.ops); … … 89 91 } 90 92 return ret; 93 } 94 95 static int ehci_driver_claim(hcd_t *hcd, ddf_dev_t *dev) 96 { 97 hc_t *instance = hcd_get_driver_data(hcd); 98 assert(instance); 99 100 return disable_legacy(instance, dev); 101 } 102 103 static int ehci_driver_start(hcd_t *hcd, bool irq) { 104 hc_t *instance = hcd_get_driver_data(hcd); 105 assert(instance); 106 107 return hc_start(instance, irq); 91 108 } 92 109 -
uspace/drv/bus/usb/ehci/res.c
rcb89430 re4d7363 172 172 } 173 173 174 int disable_legacy( ddf_dev_t *device)174 int disable_legacy(hc_t *hc, ddf_dev_t *device) 175 175 { 176 176 assert(device); … … 183 183 usb_log_debug("Disabling EHCI legacy support.\n"); 184 184 185 hw_res_list_parsed_t res; 186 hw_res_list_parsed_init(&res); 187 int ret = hw_res_get_list_parsed(parent_sess, &res, 0); 188 if (ret != EOK) { 189 usb_log_error("Failed to get resource list: %s\n", 190 str_error(ret)); 191 goto clean; 192 } 193 194 if (res.mem_ranges.count < 1) { 195 usb_log_error("Incorrect mem range count: %zu", 196 res.mem_ranges.count); 197 ret = EINVAL; 198 goto clean; 199 } 200 201 /* Map EHCI registers */ 202 void *regs = NULL; 203 ret = pio_enable_range(&res.mem_ranges.ranges[0], ®s); 204 if (ret != EOK) { 205 usb_log_error("Failed to map registers %p: %s.\n", 206 RNGABSPTR(res.mem_ranges.ranges[0]), str_error(ret)); 207 goto clean; 208 } 209 210 usb_log_debug("Registers mapped at: %p.\n", regs); 211 212 ehci_caps_regs_t *ehci_caps = regs; 213 214 const uint32_t hcc_params = EHCI_RD(ehci_caps->hccparams); 185 186 const uint32_t hcc_params = EHCI_RD(hc->caps->hccparams); 215 187 usb_log_debug2("Value of hcc params register: %x.\n", hcc_params); 216 188 … … 221 193 usb_log_debug2("Value of EECP: %x.\n", eecp); 222 194 223 ret = disable_extended_caps(parent_sess, eecp);195 int ret = disable_extended_caps(parent_sess, eecp); 224 196 if (ret != EOK) { 225 197 usb_log_error("Failed to disable extended capabilities: %s.\n", … … 228 200 } 229 201 clean: 230 //TODO unmap registers231 hw_res_list_parsed_clean(&res);232 202 async_hangup(parent_sess); 233 203 return ret; -
uspace/drv/bus/usb/ehci/res.h
rcb89430 re4d7363 39 39 #include <device/hw_res_parsed.h> 40 40 41 extern int disable_legacy(ddf_dev_t *); 41 #include "hc.h" 42 43 extern int disable_legacy(hc_t *, ddf_dev_t *); 42 44 43 45 #endif -
uspace/drv/bus/usb/ohci/hc.c
rcb89430 re4d7363 89 89 }; 90 90 91 static void hc_gain_control(hc_t *instance);92 static void hc_start(hc_t *instance);93 91 static int hc_init_transfer_lists(hc_t *instance); 94 92 static int hc_init_memory(hc_t *instance); … … 103 101 * @return Error code. 104 102 */ 105 int ohci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res)103 int ohci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res) 106 104 { 107 105 assert(code); … … 151 149 * @return Error code 152 150 */ 153 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res , bool interrupts)151 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res) 154 152 { 155 153 assert(instance); … … 172 170 list_initialize(&instance->pending_batches); 173 171 fibril_mutex_initialize(&instance->guard); 174 instance->hw_interrupts = interrupts;175 172 176 173 ret = hc_init_memory(instance); … … 181 178 return ret; 182 179 } 183 184 hc_gain_control(instance);185 186 ohci_rh_init(&instance->rh, instance->registers, "ohci rh");187 hc_start(instance);188 180 189 181 return EOK; … … 443 435 void hc_start(hc_t *instance) 444 436 { 437 ohci_rh_init(&instance->rh, instance->registers, "ohci rh"); 438 445 439 /* OHCI guide page 42 */ 446 440 assert(instance); -
uspace/drv/bus/usb/ohci/hc.h
rcb89430 re4d7363 80 80 } hc_t; 81 81 82 extern int hc_init(hc_t *, const hw_res_list_parsed_t *, bool); 82 extern int hc_init(hc_t *, const hw_res_list_parsed_t *); 83 extern void hc_gain_control(hc_t *instance); 84 extern void hc_start(hc_t *instance); 83 85 extern void hc_fini(hc_t *); 84 86 … … 86 88 extern void hc_dequeue_endpoint(hc_t *, const endpoint_t *); 87 89 88 int ohci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res);90 int ohci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res); 89 91 90 92 extern void ohci_hc_interrupt(hcd_t *, uint32_t); -
uspace/drv/bus/usb/ohci/main.c
rcb89430 re4d7363 47 47 48 48 #define NAME "ohci" 49 static int ohci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool); 49 static int ohci_driver_init(hcd_t *, const hw_res_list_parsed_t *); 50 static int ohci_driver_start(hcd_t *, bool); 51 static int ohci_driver_claim(hcd_t *, ddf_dev_t *); 50 52 static void ohci_driver_fini(hcd_t *); 51 53 … … 54 56 .irq_code_gen = ohci_hc_gen_irq_code, 55 57 .init = ohci_driver_init, 58 .claim = ohci_driver_claim, 59 .start = ohci_driver_start, 56 60 .fini = ohci_driver_fini, 57 61 .name = "OHCI", … … 66 70 67 71 68 static int ohci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res , bool irq)72 static int ohci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res) 69 73 { 70 74 assert(hcd); … … 75 79 return ENOMEM; 76 80 77 const int ret = hc_init(instance, res , irq);81 const int ret = hc_init(instance, res); 78 82 if (ret == EOK) { 79 83 hcd_set_implementation(hcd, instance, &ohci_hc_driver.ops); … … 82 86 } 83 87 return ret; 88 } 89 90 static int ohci_driver_claim(hcd_t *hcd, ddf_dev_t *dev) 91 { 92 hc_t *hc = hcd_get_driver_data(hcd); 93 assert(hc); 94 95 hc_gain_control(hc); 96 97 return EOK; 98 } 99 100 static int ohci_driver_start(hcd_t *hcd, bool interrupts) 101 { 102 hc_t *hc = hcd_get_driver_data(hcd); 103 assert(hc); 104 105 hc->hw_interrupts = interrupts; 106 hc_start(hc); 107 return EOK; 84 108 } 85 109 -
uspace/drv/bus/usb/uhci/hc.c
rcb89430 re4d7363 106 106 * @return Error code. 107 107 */ 108 int uhci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res)108 int uhci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res) 109 109 { 110 110 assert(code); … … 214 214 * interrupt fibrils. 215 215 */ 216 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res , bool interrupts)216 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res) 217 217 { 218 218 assert(instance); … … 222 222 return EINVAL; 223 223 224 instance->hw_interrupts = interrupts;225 224 instance->hw_failures = 0; 226 225 … … 246 245 } 247 246 247 return EOK; 248 } 249 250 void hc_start(hc_t *instance) 251 { 248 252 hc_init_hw(instance); 249 253 (void)hc_debug_checker; 250 254 251 255 uhci_rh_init(&instance->rh, instance->registers->ports, "uhci"); 252 253 return EOK;254 256 } 255 257 -
uspace/drv/bus/usb/uhci/hc.h
rcb89430 re4d7363 124 124 } hc_t; 125 125 126 extern int hc_init(hc_t *, const hw_res_list_parsed_t *, bool); 126 extern int hc_init(hc_t *, const hw_res_list_parsed_t *); 127 extern void hc_start(hc_t *); 127 128 extern void hc_fini(hc_t *); 128 129 129 extern int uhci_hc_gen_irq_code(irq_code_t *, const hw_res_list_parsed_t *);130 extern int uhci_hc_gen_irq_code(irq_code_t *, hcd_t *,const hw_res_list_parsed_t *); 130 131 131 132 extern void uhci_hc_interrupt(hcd_t *, uint32_t); -
uspace/drv/bus/usb/uhci/main.c
rcb89430 re4d7363 50 50 #define NAME "uhci" 51 51 52 static int uhci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool); 52 static int uhci_driver_init(hcd_t *, const hw_res_list_parsed_t *); 53 static int uhci_driver_start(hcd_t *, bool); 53 54 static void uhci_driver_fini(hcd_t *); 54 static int disable_legacy( ddf_dev_t *);55 static int disable_legacy(hcd_t *, ddf_dev_t *); 55 56 56 57 static const ddf_hc_driver_t uhci_hc_driver = { … … 59 60 .irq_code_gen = uhci_hc_gen_irq_code, 60 61 .init = uhci_driver_init, 62 .start = uhci_driver_start, 61 63 .fini = uhci_driver_fini, 62 64 .name = "UHCI", … … 68 70 }; 69 71 70 static int uhci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res , bool irq)72 static int uhci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res) 71 73 { 72 74 assert(hcd); … … 77 79 return ENOMEM; 78 80 79 const int ret = hc_init(instance, res , irq);81 const int ret = hc_init(instance, res); 80 82 if (ret == EOK) { 81 83 hcd_set_implementation(hcd, instance, &uhci_hc_driver.ops); … … 84 86 } 85 87 return ret; 88 } 89 90 static int uhci_driver_start(hcd_t *hcd, bool interrupts) 91 { 92 assert(hcd); 93 hc_t *hc = hcd_get_driver_data(hcd); 94 95 hc->hw_interrupts = interrupts; 96 hc_start(hc); 97 return EOK; 86 98 } 87 99 … … 102 114 * @return Error code. 103 115 */ 104 static int disable_legacy( ddf_dev_t *device)116 static int disable_legacy(hcd_t *hcd, ddf_dev_t *device) 105 117 { 106 118 assert(device); -
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 -
uspace/drv/bus/usb/xhci/hc.h
rcb89430 re4d7363 34 34 */ 35 35 36 #include <usb/host/ ddf_helpers.h>36 #include <usb/host/usb_transfer_batch.h> 37 37 #include "hw_struct/regs.h" 38 38 #include "hw_struct/context.h" … … 44 44 xhci_rt_regs_t *rt_regs; 45 45 xhci_doorbell_t *db_arry; 46 47 addr_range_t mmio_range; 46 48 47 49 xhci_trb_ring_t command_ring; … … 55 57 } xhci_hc_t; 56 58 57 extern const ddf_hc_driver_t xhci_ddf_hc_driver; 58 59 int hc_init_mmio(xhci_hc_t *, const hw_res_list_parsed_t *); 60 int hc_init_memory(xhci_hc_t *); 61 int hc_claim(xhci_hc_t *, ddf_dev_t *); 62 int hc_irq_code_gen(irq_code_t *, xhci_hc_t *, const hw_res_list_parsed_t *); 63 int hc_start(xhci_hc_t *, bool); 64 int hc_schedule(xhci_hc_t *hc, usb_transfer_batch_t *batch); 65 int hc_status(xhci_hc_t *, uint32_t *); 66 void hc_interrupt(xhci_hc_t *, uint32_t); 67 void hc_fini(xhci_hc_t *); 59 68 60 69 /** -
uspace/drv/bus/usb/xhci/main.c
rcb89430 re4d7363 45 45 #define NAME "xhci" 46 46 47 static int hc_driver_init(hcd_t *, const hw_res_list_parsed_t *); 48 static int hcd_irq_code_gen(irq_code_t *, hcd_t *, const hw_res_list_parsed_t *); 49 static int hcd_claim(hcd_t *, ddf_dev_t *); 50 static int hcd_start(hcd_t *, bool); 51 static int hcd_status(hcd_t *, uint32_t *); 52 static void hcd_interrupt(hcd_t *, uint32_t); 53 static int hcd_schedule(hcd_t *, usb_transfer_batch_t *); 54 static void hc_driver_fini(hcd_t *); 55 56 static const ddf_hc_driver_t xhci_ddf_hc_driver = { 57 .hc_speed = USB_SPEED_SUPER, 58 .name = "XHCI-PCI", 59 .init = hc_driver_init, 60 .irq_code_gen = hcd_irq_code_gen, 61 .claim = hcd_claim, 62 .start = hcd_start, 63 .fini = hc_driver_fini, 64 .ops = { 65 .schedule = hcd_schedule, 66 .irq_hook = hcd_interrupt, 67 .status_hook = hcd_status, 68 } 69 }; 70 71 static int hc_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *hw_res) 72 { 73 int err; 74 75 xhci_hc_t *hc = malloc(sizeof(xhci_hc_t)); 76 if (!hc) 77 return ENOMEM; 78 79 if ((err = hc_init_mmio(hc, hw_res))) 80 goto err; 81 82 if ((err = hc_init_memory(hc))) 83 goto err; 84 85 hcd_set_implementation(hcd, hc, &xhci_ddf_hc_driver.ops); 86 87 return EOK; 88 err: 89 free(hc); 90 return err; 91 } 92 93 static int hcd_irq_code_gen(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res) 94 { 95 xhci_hc_t *hc = hcd_get_driver_data(hcd); 96 assert(hc); 97 98 return hc_irq_code_gen(code, hc, hw_res); 99 } 100 101 static int hcd_claim(hcd_t *hcd, ddf_dev_t *dev) 102 { 103 xhci_hc_t *hc = hcd_get_driver_data(hcd); 104 assert(hc); 105 106 return hc_claim(hc, dev); 107 } 108 109 static int hcd_start(hcd_t *hcd, bool irq) 110 { 111 xhci_hc_t *hc = hcd_get_driver_data(hcd); 112 assert(hc); 113 114 return hc_start(hc, irq); 115 } 116 117 static int hcd_schedule(hcd_t *hcd, usb_transfer_batch_t *batch) 118 { 119 xhci_hc_t *hc = hcd_get_driver_data(hcd); 120 assert(hc); 121 122 return hc_schedule(hc, batch); 123 } 124 125 static int hcd_status(hcd_t *hcd, uint32_t *status) 126 { 127 xhci_hc_t *hc = hcd_get_driver_data(hcd); 128 assert(hc); 129 assert(status); 130 131 return hc_status(hc, status); 132 } 133 134 static void hcd_interrupt(hcd_t *hcd, uint32_t status) 135 { 136 xhci_hc_t *hc = hcd_get_driver_data(hcd); 137 assert(hc); 138 139 hc_interrupt(hc, status); 140 } 141 142 static void hc_driver_fini(hcd_t *hcd) 143 { 144 xhci_hc_t *hc = hcd_get_driver_data(hcd); 145 assert(hc); 146 147 hc_fini(hc); 148 free(hc); 149 } 150 47 151 /** Initializes a new ddf driver instance of XHCI hcd. 48 152 * -
uspace/lib/usbhost/include/usb/host/ddf_helpers.h
rcb89430 re4d7363 45 45 #include <device/hw_res_parsed.h> 46 46 47 typedef int (*driver_init_t)(hcd_t *, const hw_res_list_parsed_t *, bool); 47 typedef int (*driver_init_t)(hcd_t *, const hw_res_list_parsed_t *); 48 typedef int (*irq_code_gen_t)(irq_code_t *, hcd_t *, const hw_res_list_parsed_t *); 49 typedef int (*claim_t)(hcd_t *, ddf_dev_t *); 50 typedef int (*driver_start_t)(hcd_t *, bool irq); 51 52 typedef void (*driver_stop_t)(hcd_t *); 48 53 typedef void (*driver_fini_t)(hcd_t *); 49 typedef int (*claim_t)(ddf_dev_t *);50 typedef int (*irq_code_gen_t)(irq_code_t *, const hw_res_list_parsed_t *);51 54 55 /** 56 * All callbacks are optional. 57 */ 52 58 typedef struct { 53 59 hcd_ops_t ops; 54 claim_t claim;55 60 usb_speed_t hc_speed; 56 driver_init_t init;57 driver_fini_t fini;58 interrupt_handler_t *irq_handler;59 irq_code_gen_t irq_code_gen;60 61 const char *name; 62 63 interrupt_handler_t *irq_handler; /**< Handler of IRQ. Do have generic implementation. */ 64 65 /* Initialization sequence: */ 66 driver_init_t init; /**< Initialize internal structures, memory */ 67 claim_t claim; /**< Claim device from BIOS */ 68 irq_code_gen_t irq_code_gen; /**< Generate IRQ handling code */ 69 driver_start_t start; /**< Start the HC */ 70 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) */ 61 74 } ddf_hc_driver_t; 62 75 … … 75 88 const hw_res_list_parsed_t *hw_res, 76 89 interrupt_handler_t handler, 77 i nt (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *));90 irq_code_gen_t gen_irq_code); 78 91 void ddf_hcd_gen_irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev); 79 92 -
uspace/lib/usbhost/src/ddf_helpers.c
rcb89430 re4d7363 753 753 const hw_res_list_parsed_t *hw_res, 754 754 interrupt_handler_t handler, 755 int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *hw_res)) 756 { 757 755 irq_code_gen_t gen_irq_code) 756 { 758 757 assert(device); 758 759 hcd_t *hcd = dev_to_hcd(device); 760 759 761 if (!handler || !gen_irq_code) 760 762 return ENOTSUP; … … 762 764 irq_code_t irq_code = {0}; 763 765 764 const int irq = gen_irq_code(&irq_code, h w_res);766 const int irq = gen_irq_code(&irq_code, hcd, hw_res); 765 767 if (irq < 0) { 766 768 usb_log_error("Failed to generate IRQ code: %s.\n", … … 878 880 if (ret != EOK) { 879 881 usb_log_error("Failed to setup generic HCD.\n"); 880 hw_res_list_parsed_clean(&hw_res); 881 return ret; 882 } 883 882 goto err_hw_res; 883 } 884 885 hcd_t *hcd = dev_to_hcd(device); 886 887 if (driver->init) 888 ret = driver->init(hcd, &hw_res); 889 if (ret != EOK) { 890 usb_log_error("Failed to init HCD.\n"); 891 goto err_hcd; 892 } 893 894 /* Setup interrupts */ 884 895 interrupt_handler_t *irq_handler = 885 896 driver->irq_handler ? driver->irq_handler : ddf_hcd_gen_irq_handler; 886 const int irq = hcd_ddf_setup_interrupts(device, &hw_res, irq_handler, 887 driver->irq_code_gen); 897 const int irq = hcd_ddf_setup_interrupts(device, &hw_res, irq_handler, driver->irq_code_gen); 888 898 if (!(irq < 0)) { 889 899 usb_log_debug("Hw interrupts enabled.\n"); 890 900 } 891 901 902 /* Claim the device from BIOS */ 892 903 if (driver->claim) 893 ret = driver->claim(device); 894 if (ret != EOK) { 895 usb_log_error("Failed to claim `%s' for driver `%s'", 896 ddf_dev_get_name(device), driver->name); 897 return ret; 898 } 899 900 901 /* Init hw driver */ 902 hcd_t *hcd = dev_to_hcd(device); 903 ret = driver->init(hcd, &hw_res, !(irq < 0)); 904 hw_res_list_parsed_clean(&hw_res); 905 if (ret != EOK) { 906 usb_log_error("Failed to init HCD: %s.\n", str_error(ret)); 907 goto irq_unregister; 904 ret = driver->claim(hcd, device); 905 if (ret != EOK) { 906 usb_log_error("Failed to claim `%s' for driver `%s': %s", 907 ddf_dev_get_name(device), driver->name, str_error(ret)); 908 goto err_irq; 909 } 910 911 /* Start hw driver */ 912 if (driver->start) 913 ret = driver->start(hcd, !(irq < 0)); 914 if (ret != EOK) { 915 usb_log_error("Failed to start HCD: %s.\n", str_error(ret)); 916 goto err_irq; 908 917 } 909 918 … … 914 923 usb_log_error("Failed to create polling fibril\n"); 915 924 ret = ENOMEM; 916 goto irq_unregister;925 goto err_started; 917 926 } 918 927 fibril_add_ready(hcd->polling_fibril); … … 929 938 usb_log_error("Failed to setup HC root hub: %s.\n", 930 939 str_error(ret)); 931 driver->fini(dev_to_hcd(device)); 932 irq_unregister: 933 /* Unregistering non-existent should be ok */ 934 unregister_interrupt_handler(device, irq); 935 hcd_ddf_clean_hc(device); 936 return ret; 940 goto err_polling; 937 941 } 938 942 … … 940 944 driver->name, ddf_dev_get_name(device)); 941 945 return EOK; 946 947 err_polling: 948 // TODO: Stop the polling fibril (refactor the interrupt_polling func) 949 // 950 err_started: 951 if (driver->stop) 952 driver->stop(hcd); 953 err_irq: 954 unregister_interrupt_handler(device, irq); 955 if (driver->fini) 956 driver->fini(hcd); 957 err_hcd: 958 hcd_ddf_clean_hc(device); 959 err_hw_res: 960 hw_res_list_parsed_clean(&hw_res); 961 return ret; 942 962 } 943 963 /**
Note:
See TracChangeset
for help on using the changeset viewer.