Changes in uspace/drv/bus/usb/ohci/ohci.c [7de1988c:952bc66] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/ohci.c
r7de1988c r952bc66 34 34 */ 35 35 36 /* XXX Fix this */ 37 #define _DDF_DATA_IMPLANT 36 #include <assert.h> 37 #include <errno.h> 38 #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> 38 43 39 #include <errno.h>40 #include <str_error.h>41 #include <ddf/interrupt.h>42 #include <usb_iface.h>43 44 #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 47 50 #include "ohci.h" 48 #include " res.h"51 #include "ohci_endpoint.h" 49 52 #include "hc.h" 50 53 51 typedef struct ohci {52 ddf_fun_t *hc_fun;53 ddf_fun_t *rh_fun;54 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 }62 55 /** IRQ handling callback, identifies device 63 56 * … … 69 62 { 70 63 assert(dev); 71 72 ohci_t *ohci = dev_to_ohci(dev); 73 if (!ohci) { 64 hcd_t *hcd = dev_to_hcd(dev); 65 if (!hcd || !hcd->driver.data) { 74 66 usb_log_warning("Interrupt on device that is not ready.\n"); 75 67 return; 76 68 } 69 77 70 const uint16_t status = IPC_GET_ARG1(*call); 78 hc_interrupt( &ohci->hc, status);71 hc_interrupt(hcd->driver.data, status); 79 72 } 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 73 132 74 /** Initialize hc and rh ddf structures and their respective drivers. … … 143 85 int device_setup_ohci(ddf_dev_t *device) 144 86 { 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) { 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) { 184 91 usb_log_error("Failed to get register memory addresses " 185 92 "for %" PRIun ": %s.\n", ddf_dev_get_handle(device), 186 str_error(r c));187 goto error;93 str_error(ret)); 94 return ret; 188 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); 189 99 190 100 usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n", 191 101 RNGABSPTR(regs), RNGSZ(regs), irq); 192 102 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; 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; 198 110 } 199 111 200 ih_registered = true; 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 } 201 118 202 119 /* Try to enable interrupts */ 203 120 bool interrupts = false; 204 rc = enable_interrupts(device); 205 if (rc != EOK) { 121 ret = hcd_ddf_setup_interrupts(device, ®s, irq, irq_handler, 122 hc_gen_irq_code); 123 if (ret != EOK) { 206 124 usb_log_warning("Failed to enable interrupts: %s." 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; 125 " Falling back to polling\n", str_error(ret)); 211 126 } else { 212 127 usb_log_debug("Hw interrupts enabled.\n"); … … 214 129 } 215 130 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; 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; 220 136 } 221 137 222 hc_inited = true; 138 /* Connect OHCI to generic HCD */ 139 hcd_set_implementation(dev_to_hcd(device), hc, 140 hc_schedule, ohci_endpoint_init, ohci_endpoint_fini); 223 141 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; 142 /* HC should be running OK. We can add root hub */ 143 ret = hcd_ddf_setup_root_hub(device); 144 if (ret != EOK) { 145 usb_log_error("Failed to register OHCI root hub: %s.\n", 146 str_error(ret)); 147 hc_fini(hc); 148 unregister_irq: 149 unregister_interrupt_handler(device, irq); 150 free(hc); 151 ddf_hc_clean: 152 hcd_ddf_clean_hc(device); 229 153 } 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; 154 return ret; 257 155 } 258 156 /**
Note:
See TracChangeset
for help on using the changeset viewer.