Changes in uspace/drv/bus/usb/ohci/ohci.c [952bc66:7de1988c] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/ohci.c
r952bc66 r7de1988c 34 34 */ 35 35 36 #include <assert.h> 36 /* XXX Fix this */ 37 #define _DDF_DATA_IMPLANT 38 37 39 #include <errno.h> 40 #include <str_error.h> 38 41 #include <ddf/interrupt.h> 39 #include <device/hw_res_parsed.h> 40 #include <stdbool.h> 41 #include <str_error.h> 42 #include <sys/types.h> 43 42 #include <usb_iface.h> 44 43 #include <usb/usb.h> 44 #include <usb/ddfiface.h> 45 45 #include <usb/debug.h> 46 46 47 #include <usb/host/ddf_helpers.h>48 #include <usb/host/usb_bus.h>49 50 47 #include "ohci.h" 51 #include " ohci_endpoint.h"48 #include "res.h" 52 49 #include "hc.h" 53 50 54 51 typedef struct ohci { 52 ddf_fun_t *hc_fun; 53 ddf_fun_t *rh_fun; 54 55 hc_t hc; 56 } ohci_t; 57 58 static inline ohci_t *dev_to_ohci(ddf_dev_t *dev) 59 { 60 return ddf_dev_data_get(dev); 61 } 55 62 /** IRQ handling callback, identifies device 56 63 * … … 62 69 { 63 70 assert(dev); 64 hcd_t *hcd = dev_to_hcd(dev); 65 if (!hcd || !hcd->driver.data) { 71 72 ohci_t *ohci = dev_to_ohci(dev); 73 if (!ohci) { 66 74 usb_log_warning("Interrupt on device that is not ready.\n"); 67 75 return; 68 76 } 69 70 77 const uint16_t status = IPC_GET_ARG1(*call); 71 hc_interrupt(hcd->driver.data, status); 72 } 78 hc_interrupt(&ohci->hc, status); 79 } 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 }; 73 131 74 132 /** Initialize hc and rh ddf structures and their respective drivers. … … 85 143 int device_setup_ohci(ddf_dev_t *device) 86 144 { 87 hw_res_list_parsed_t hw_res; 88 int ret = hcd_ddf_get_registers(device, &hw_res); 89 if (ret != EOK || 90 hw_res.irqs.count != 1 || hw_res.mem_ranges.count != 1) { 145 bool ih_registered = false; 146 bool hc_inited = false; 147 int rc; 148 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; 180 int irq = 0; 181 182 rc = get_my_registers(device, ®s, &irq); 183 if (rc != EOK) { 91 184 usb_log_error("Failed to get register memory addresses " 92 185 "for %" PRIun ": %s.\n", ddf_dev_get_handle(device), 93 str_error(ret)); 94 return ret; 95 } 96 addr_range_t regs = hw_res.mem_ranges.ranges[0]; 97 const int irq = hw_res.irqs.irqs[0]; 98 hw_res_list_parsed_clean(&hw_res); 186 str_error(rc)); 187 goto error; 188 } 99 189 100 190 usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n", 101 191 RNGABSPTR(regs), RNGSZ(regs), irq); 102 192 103 /* Initialize generic HCD driver */ 104 ret = hcd_ddf_setup_hc(device, USB_SPEED_FULL, 105 BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11); 106 if (ret != EOK) { 107 usb_log_error("Failed to setup generic hcd structures: %s.", 108 str_error(ret)); 109 return ret; 110 } 111 112 hc_t *hc = malloc(sizeof(hc_t)); 113 if (!hc) { 114 usb_log_error("Failed to allocate driver structure.\n"); 115 ret = ENOMEM; 116 goto ddf_hc_clean; 117 } 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 } 199 200 ih_registered = true; 118 201 119 202 /* Try to enable interrupts */ 120 203 bool interrupts = false; 121 ret = hcd_ddf_setup_interrupts(device, ®s, irq, irq_handler, 122 hc_gen_irq_code); 123 if (ret != EOK) { 204 rc = enable_interrupts(device); 205 if (rc != EOK) { 124 206 usb_log_warning("Failed to enable interrupts: %s." 125 " Falling back to polling\n", str_error(ret)); 207 " Falling back to polling\n", str_error(rc)); 208 /* We don't need that handler */ 209 unregister_interrupt_handler(device, irq); 210 ih_registered = false; 126 211 } else { 127 212 usb_log_debug("Hw interrupts enabled.\n"); … … 129 214 } 130 215 131 /* Initialize OHCI HC */ 132 ret = hc_init(hc, ®s, interrupts); 133 if (ret != EOK) { 134 usb_log_error("Failed to init hc: %s.\n", str_error(ret)); 135 goto unregister_irq; 136 } 137 138 /* Connect OHCI to generic HCD */ 139 hcd_set_implementation(dev_to_hcd(device), hc, 140 hc_schedule, ohci_endpoint_init, ohci_endpoint_fini); 141 142 /* HC should be running OK. We can add root hub */ 143 ret = hcd_ddf_setup_root_hub(device); 144 if (ret != EOK) { 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; 220 } 221 222 hc_inited = true; 223 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 } 230 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 } 237 238 rc = hc_register_hub(&instance->hc, instance->rh_fun); 239 if (rc != EOK) { 145 240 usb_log_error("Failed to register OHCI root hub: %s.\n", 146 str_error(ret)); 147 hc_fini(hc); 148 unregister_irq: 241 str_error(rc)); 242 goto error; 243 } 244 245 return EOK; 246 247 error: 248 if (hc_inited) 249 hc_fini(&instance->hc); 250 if (ih_registered) 149 251 unregister_interrupt_handler(device, irq); 150 free(hc);151 ddf_hc_clean: 152 hcd_ddf_clean_hc(device);153 }154 return r et;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; 155 257 } 156 258 /**
Note:
See TracChangeset
for help on using the changeset viewer.