Changes in uspace/drv/bus/usb/ohci/ohci.c [7de1988c:e991937] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/ohci.c
r7de1988c re991937 34 34 */ 35 35 36 /* XXX Fix this */37 #define _DDF_DATA_IMPLANT38 39 36 #include <errno.h> 40 37 #include <str_error.h> 41 38 #include <ddf/interrupt.h> 42 #include <usb_iface.h>43 39 #include <usb/usb.h> 44 #include <usb/ddfiface.h>45 40 #include <usb/debug.h> 41 42 #include <usb/host/ddf_helpers.h> 46 43 47 44 #include "ohci.h" … … 49 46 #include "hc.h" 50 47 51 typedef struct ohci {52 ddf_fun_t *hc_fun;53 ddf_fun_t *rh_fun;54 48 55 hc_t hc;56 } ohci_t;57 49 58 static inline ohci_t *dev_to_ohci(ddf_dev_t *dev)59 {60 return ddf_dev_data_get(dev);61 }62 50 /** IRQ handling callback, identifies device 63 51 * … … 69 57 { 70 58 assert(dev); 71 72 ohci_t *ohci = dev_to_ohci(dev); 73 if (!ohci) { 59 hcd_t *hcd = dev_to_hcd(dev); 60 if (!hcd || !hcd->private_data) { 74 61 usb_log_warning("Interrupt on device that is not ready.\n"); 75 62 return; 76 63 } 64 77 65 const uint16_t status = IPC_GET_ARG1(*call); 78 hc_interrupt( &ohci->hc, status);66 hc_interrupt(hcd->private_data, status); 79 67 } 80 81 /** Get USB address assigned to root hub.82 *83 * @param[in] fun Root hub function.84 * @param[out] address Store the address here.85 * @return Error code.86 */87 static int rh_get_my_address(ddf_fun_t *fun, usb_address_t *address)88 {89 assert(fun);90 91 if (address != NULL) {92 *address = dev_to_ohci(ddf_fun_get_dev(fun))->hc.rh.address;93 }94 95 return EOK;96 }97 98 /** Gets handle of the respective hc (this device, hc function).99 *100 * @param[in] root_hub_fun Root hub function seeking hc handle.101 * @param[out] handle Place to write the handle.102 * @return Error code.103 */104 static int rh_get_hc_handle(105 ddf_fun_t *fun, devman_handle_t *handle)106 {107 assert(fun);108 ddf_fun_t *hc_fun = dev_to_ohci(ddf_fun_get_dev(fun))->hc_fun;109 assert(hc_fun);110 111 if (handle != NULL)112 *handle = ddf_fun_get_handle(hc_fun);113 return EOK;114 }115 116 /** Root hub USB interface */117 static usb_iface_t usb_iface = {118 .get_hc_handle = rh_get_hc_handle,119 .get_my_address = rh_get_my_address,120 };121 122 /** Standard USB HC options (HC interface) */123 static ddf_dev_ops_t hc_ops = {124 .interfaces[USBHC_DEV_IFACE] = &hcd_iface,125 };126 127 /** Standard USB RH options (RH interface) */128 static ddf_dev_ops_t rh_ops = {129 .interfaces[USB_DEV_IFACE] = &usb_iface,130 };131 68 132 69 /** Initialize hc and rh ddf structures and their respective drivers. … … 143 80 int device_setup_ohci(ddf_dev_t *device) 144 81 { 145 bool ih_registered = false; 146 bool hc_inited = false; 147 int rc; 82 #define CHECK_RET_RETURN(ret, message...) \ 83 if (ret != EOK) { \ 84 usb_log_error(message); \ 85 return ret; \ 86 } 148 87 149 if (device == NULL) 150 return EBADMEM; 151 152 ohci_t *instance = ddf_dev_data_alloc(device,sizeof(ohci_t)); 153 if (instance == NULL) { 154 usb_log_error("Failed to allocate OHCI driver.\n"); 155 return ENOMEM; 156 } 157 158 instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci_hc"); 159 if (instance->hc_fun == NULL) { 160 usb_log_error("Failed to create OHCI HC function: %s.\n", 161 str_error(ENOMEM)); 162 rc = ENOMEM; 163 goto error; 164 } 165 166 ddf_fun_set_ops(instance->hc_fun, &hc_ops); 167 ddf_fun_data_implant(instance->hc_fun, &instance->hc); 168 169 instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci_rh"); 170 if (instance->rh_fun == NULL) { 171 usb_log_error("Failed to create OHCI RH function: %s.\n", 172 str_error(ENOMEM)); 173 rc = ENOMEM; 174 goto error; 175 } 176 177 ddf_fun_set_ops(instance->rh_fun, &rh_ops); 178 179 addr_range_t regs; 88 uintptr_t reg_base = 0; 89 size_t reg_size = 0; 180 90 int irq = 0; 181 91 182 rc = get_my_registers(device, ®s, &irq); 183 if (rc != EOK) { 184 usb_log_error("Failed to get register memory addresses " 185 "for %" PRIun ": %s.\n", ddf_dev_get_handle(device), 186 str_error(rc)); 187 goto error; 188 } 92 int ret = get_my_registers(device, ®_base, ®_size, &irq); 93 CHECK_RET_RETURN(ret, "Failed to get register memory addresses for %" 94 PRIun ": %s.\n", ddf_dev_get_handle(device), str_error(ret)); 189 95 190 96 usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n", 191 RNGABSPTR(regs), RNGSZ(regs), irq);97 (void *) reg_base, reg_size, irq); 192 98 193 rc = hc_register_irq_handler(device, ®s, irq, irq_handler); 194 if (rc != EOK) { 195 usb_log_error("Failed to register interrupt handler: %s.\n", 196 str_error(rc)); 197 goto error; 198 } 99 const size_t ranges_count = hc_irq_pio_range_count(); 100 const size_t cmds_count = hc_irq_cmd_count(); 101 irq_pio_range_t irq_ranges[ranges_count]; 102 irq_cmd_t irq_cmds[cmds_count]; 103 irq_code_t irq_code = { 104 .rangecount = ranges_count, 105 .ranges = irq_ranges, 106 .cmdcount = cmds_count, 107 .cmds = irq_cmds 108 }; 199 109 200 ih_registered = true; 110 ret = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds, 111 sizeof(irq_cmds), reg_base, reg_size); 112 CHECK_RET_RETURN(ret, "Failed to gen IRQ code: %s.\n", str_error(ret)); 113 114 /* Register handler to avoid interrupt lockup */ 115 ret = register_interrupt_handler(device, irq, irq_handler, &irq_code); 116 CHECK_RET_RETURN(ret, 117 "Failed to register irq handler: %s.\n", str_error(ret)); 201 118 202 119 /* Try to enable interrupts */ 203 120 bool interrupts = false; 204 r c= enable_interrupts(device);205 if (r c!= EOK) {121 ret = enable_interrupts(device); 122 if (ret != EOK) { 206 123 usb_log_warning("Failed to enable interrupts: %s." 207 " Falling back to polling\n", str_error(r c));124 " Falling back to polling\n", str_error(ret)); 208 125 /* We don't need that handler */ 209 126 unregister_interrupt_handler(device, irq); 210 ih_registered = false;211 127 } else { 212 128 usb_log_debug("Hw interrupts enabled.\n"); … … 214 130 } 215 131 216 rc = hc_init(&instance->hc, ®s, interrupts); 217 if (rc != EOK) { 218 usb_log_error("Failed to init ohci_hcd: %s.\n", str_error(rc)); 219 goto error; 132 /* Initialize generic HCD driver */ 133 ret = hcd_ddf_setup_hc(device, USB_SPEED_FULL, 134 BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11); 135 if (ret != EOK) { 136 unregister_interrupt_handler(device, irq); 137 return ret; 220 138 } 221 139 222 hc_inited = true; 140 // TODO: Undo hcd_setup_device 141 #define CHECK_RET_CLEAN_RETURN(ret, message...) \ 142 if (ret != EOK) { \ 143 unregister_interrupt_handler(device, irq); \ 144 CHECK_RET_RETURN(ret, message); \ 145 } else (void)0 223 146 224 rc = ddf_fun_bind(instance->hc_fun); 225 if (rc != EOK) { 226 usb_log_error("Failed to bind OHCI device function: %s.\n", 227 str_error(rc)); 228 goto error; 229 } 147 hc_t *hc_impl = malloc(sizeof(hc_t)); 148 ret = hc_impl ? EOK : ENOMEM; 149 CHECK_RET_CLEAN_RETURN(ret, "Failed to allocate driver structure.\n"); 230 150 231 rc = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY); 232 if (rc != EOK) { 233 usb_log_error("Failed to add OHCI to HC category: %s.\n", 234 str_error(rc)); 235 goto error; 236 } 151 /* Initialize OHCI HC */ 152 ret = hc_init(hc_impl, reg_base, reg_size, interrupts); 153 CHECK_RET_CLEAN_RETURN(ret, "Failed to init hc: %s.\n", str_error(ret)); 237 154 238 rc = hc_register_hub(&instance->hc, instance->rh_fun); 239 if (rc != EOK) { 240 usb_log_error("Failed to register OHCI root hub: %s.\n", 241 str_error(rc)); 242 goto error; 243 } 155 /* Connect OHCI to generic HCD */ 156 hcd_set_implementation(dev_to_hcd(device), hc_impl, 157 hc_schedule, ohci_endpoint_init, ohci_endpoint_fini); 244 158 245 return EOK; 159 /* HC should be running OK. We can add root hub */ 160 ret = hcd_ddf_setup_root_hub(device); 161 CHECK_RET_CLEAN_RETURN(ret, 162 "Failed to register OHCI root hub: %s.\n", str_error(ret)); 246 163 247 error: 248 if (hc_inited) 249 hc_fini(&instance->hc); 250 if (ih_registered) 251 unregister_interrupt_handler(device, irq); 252 if (instance->hc_fun != NULL) 253 ddf_fun_destroy(instance->hc_fun); 254 if (instance->rh_fun != NULL) 255 ddf_fun_destroy(instance->rh_fun); 256 return rc; 164 return ret; 257 165 } 258 166 /**
Note:
See TracChangeset
for help on using the changeset viewer.