Changeset a720ff6 in mainline for uspace/drv/bus/usb/uhci/uhci.c
- Timestamp:
- 2012-12-20T15:42:35Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 53332b5b
- Parents:
- d09791e6
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/uhci/uhci.c
rd09791e6 ra720ff6 43 43 #include <usb/ddfiface.h> 44 44 #include <usb/debug.h> 45 #include <usb/host/hcd.h> 45 46 46 47 #include "uhci.h" … … 50 51 #include "root_hub.h" 51 52 52 /** Structure representing both functions of UHCI hc, USB host controller53 * and USB root hub */54 typedef struct uhci {55 /** Pointer to DDF representation of UHCI host controller */56 ddf_fun_t *hc_fun;57 /** Pointer to DDF representation of UHCI root hub */58 ddf_fun_t *rh_fun;59 60 /** Internal driver's representation of UHCI host controller */61 hc_t hc;62 /** Internal driver's representation of UHCI root hub */63 rh_t rh;64 } uhci_t;65 66 static inline uhci_t *dev_to_uhci(ddf_dev_t *dev)67 {68 return ddf_dev_data_get(dev);69 }70 53 71 54 /** IRQ handling callback, forward status from call to diver structure. … … 78 61 { 79 62 assert(dev); 80 uhci_t *uhci = dev_to_uhci(dev);81 if (! uhci) {63 hcd_t *hcd = dev_to_hcd(dev); 64 if (!hcd || !hcd->private_data) { 82 65 usb_log_error("Interrupt on not yet initialized device.\n"); 83 66 return; 84 67 } 85 68 const uint16_t status = IPC_GET_ARG1(*call); 86 hc_interrupt( &uhci->hc, status);69 hc_interrupt(hcd->private_data, status); 87 70 } 88 89 /** Operations supported by the HC driver */90 static ddf_dev_ops_t hc_ops = {91 .interfaces[USBHC_DEV_IFACE] = &hcd_iface, /* see iface.h/c */92 };93 94 /** Gets handle of the respective hc.95 *96 * @param[in] fun DDF function of uhci device.97 * @param[out] handle Host cotnroller handle.98 * @return Error code.99 */100 static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)101 {102 ddf_fun_t *hc_fun = dev_to_uhci(ddf_fun_get_dev(fun))->hc_fun;103 assert(hc_fun);104 105 if (handle != NULL)106 *handle = ddf_fun_get_handle(hc_fun);107 return EOK;108 }109 110 /** USB interface implementation used by RH */111 static usb_iface_t usb_iface = {112 .get_hc_handle = usb_iface_get_hc_handle,113 };114 115 /** Get root hub hw resources (I/O registers).116 *117 * @param[in] fun Root hub function.118 * @return Pointer to the resource list used by the root hub.119 */120 static hw_resource_list_t *get_resource_list(ddf_fun_t *fun)121 {122 rh_t *rh = ddf_fun_data_get(fun);123 assert(rh);124 return &rh->resource_list;125 }126 127 /** Interface to provide the root hub driver with hw info */128 static hw_res_ops_t hw_res_iface = {129 .get_resource_list = get_resource_list,130 .enable_interrupt = NULL,131 };132 133 /** RH function support for uhci_rhd */134 static ddf_dev_ops_t rh_ops = {135 .interfaces[USB_DEV_IFACE] = &usb_iface,136 .interfaces[HW_RES_DEV_IFACE] = &hw_res_iface137 };138 71 139 72 /** Initialize hc and rh DDF structures and their respective drivers. … … 152 85 return EBADMEM; 153 86 154 uhci_t *instance = ddf_dev_data_alloc(device, sizeof(uhci_t)); 155 if (instance == NULL) { 156 usb_log_error("Failed to allocate OHCI driver.\n"); 157 return ENOMEM; 158 } 159 160 #define CHECK_RET_DEST_FREE_RETURN(ret, message...) \ 87 #define CHECK_RET_RETURN(ret, message...) \ 161 88 if (ret != EOK) { \ 162 if (instance->hc_fun) \163 ddf_fun_destroy(instance->hc_fun); \164 if (instance->rh_fun) {\165 ddf_fun_destroy(instance->rh_fun); \166 } \167 89 usb_log_error(message); \ 168 90 return ret; \ 169 91 } else (void)0 170 171 instance->rh_fun = NULL;172 instance->hc_fun = ddf_fun_create(device, fun_exposed, "uhci_hc");173 int ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;174 CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI HC function.\n");175 ddf_fun_set_ops(instance->hc_fun, &hc_ops);176 ddf_fun_data_implant(instance->hc_fun, &instance->hc.generic);177 178 instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci_rh");179 ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;180 CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI RH function.\n");181 ddf_fun_set_ops(instance->rh_fun, &rh_ops);182 ddf_fun_data_implant(instance->rh_fun, &instance->rh);183 92 184 93 uintptr_t reg_base = 0; … … 186 95 int irq = 0; 187 96 188 ret = get_my_registers(device, ®_base, ®_size, &irq); 189 CHECK_RET_DEST_FREE_RETURN(ret, 190 "Failed to get I/O addresses for %" PRIun ": %s.\n", 97 int ret = get_my_registers(device, ®_base, ®_size, &irq); 98 CHECK_RET_RETURN(ret, "Failed to get I/O region for %" PRIun ": %s.\n", 191 99 ddf_dev_get_handle(device), str_error(ret)); 192 100 usb_log_debug("I/O regs at 0x%p (size %zu), IRQ %d.\n", 193 101 (void *) reg_base, reg_size, irq); 194 195 ret = disable_legacy(device);196 CHECK_RET_DEST_FREE_RETURN(ret,197 "Failed to disable legacy USB: %s.\n", str_error(ret));198 102 199 103 const size_t ranges_count = hc_irq_pio_range_count(); … … 203 107 ret = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds, 204 108 sizeof(irq_cmds), reg_base, reg_size); 205 CHECK_RET_ DEST_FREE_RETURN(ret,206 "Failed to generate IRQ commands: %s.\n",str_error(ret));109 CHECK_RET_RETURN(ret, "Failed to generate IRQ commands: %s.\n", 110 str_error(ret)); 207 111 208 112 irq_code_t irq_code = { … … 215 119 /* Register handler to avoid interrupt lockup */ 216 120 ret = register_interrupt_handler(device, irq, irq_handler, &irq_code); 217 CHECK_RET_DEST_FREE_RETURN(ret, 218 "Failed to register interrupt handler: %s.\n", str_error(ret)); 121 CHECK_RET_RETURN(ret, "Failed to register interrupt handler: %s.\n", 122 str_error(ret)); 123 124 ret = disable_legacy(device); 125 CHECK_RET_RETURN(ret, "Failed to disable legacy USB: %s.\n", 126 str_error(ret)); 219 127 220 128 bool interrupts = false; … … 228 136 } 229 137 230 ret = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts); 231 CHECK_RET_DEST_FREE_RETURN(ret, 138 ddf_fun_t *hc_fun = NULL; 139 ret = hcd_setup_device(device, &hc_fun); 140 CHECK_RET_RETURN(ret, "Failed to setup UHCI HCD.\n"); 141 142 hc_t *hc = malloc(sizeof(hc_t)); 143 ret = hc ? EOK : ENOMEM; 144 CHECK_RET_RETURN(ret, "Failed to allocate UHCI HC structure.\n"); 145 146 ret = hc_init(hc, (void*)reg_base, reg_size, interrupts); 147 CHECK_RET_RETURN(ret, 232 148 "Failed to init uhci_hcd: %s.\n", str_error(ret)); 233 149 150 hcd_set_implementation(dev_to_hcd(device), hc, hc_schedule, NULL, NULL); 151 152 // TODO: Undo hcd_setup_device 234 153 #define CHECK_RET_FINI_RETURN(ret, message...) \ 235 154 if (ret != EOK) { \ 236 hc_fini( &instance->hc); \237 CHECK_RET_ DEST_FREE_RETURN(ret, message); \155 hc_fini(hc); \ 156 CHECK_RET_RETURN(ret, message); \ 238 157 return ret; \ 239 158 } else (void)0 240 159 241 ret = ddf_fun_bind(instance->hc_fun); 242 CHECK_RET_FINI_RETURN(ret, "Failed to bind UHCI device function: %s.\n", 243 str_error(ret)); 244 245 ret = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY); 246 CHECK_RET_FINI_RETURN(ret, 247 "Failed to add UHCI to HC class: %s.\n", str_error(ret)); 248 249 ret = rh_init(&instance->rh, instance->rh_fun, 250 (uintptr_t)instance->hc.registers + 0x10, 4); 160 ret = rh_init(device, (uintptr_t)hc->registers + 0x10, 4, 161 ddf_fun_get_handle(hc_fun)); 251 162 CHECK_RET_FINI_RETURN(ret, 252 163 "Failed to setup UHCI root hub: %s.\n", str_error(ret)); 253 254 ret = ddf_fun_bind(instance->rh_fun);255 CHECK_RET_FINI_RETURN(ret,256 "Failed to register UHCI root hub: %s.\n", str_error(ret));257 164 258 165 return EOK;
Note:
See TracChangeset
for help on using the changeset viewer.