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