Changeset a720ff6 in mainline
- Timestamp:
- 2012-12-20T15:42:35Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 53332b5b
- Parents:
- d09791e6
- Location:
- uspace/drv/bus/usb/uhci
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/uhci/hc.c
rd09791e6 ra720ff6 85 85 static int hc_init_mem_structures(hc_t *instance); 86 86 static int hc_init_transfer_lists(hc_t *instance); 87 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);88 87 89 88 static int hc_interrupt_emulator(void *arg); … … 235 234 236 235 #undef CHECK_RET_RETURN 237 238 hcd_init(&instance->generic, USB_SPEED_FULL,239 BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);240 241 instance->generic.private_data = instance;242 instance->generic.schedule = hc_schedule;243 instance->generic.ep_add_hook = NULL;244 236 245 237 hc_init_hw(instance); -
uspace/drv/bus/usb/uhci/hc.h
rd09791e6 ra720ff6 90 90 /** Main UHCI driver structure */ 91 91 typedef struct hc { 92 /** Generic HCD driver structure */93 hcd_t generic;94 95 92 /** Addresses of I/O registers */ 96 93 uhci_regs_t *registers; … … 125 122 void hc_interrupt(hc_t *instance, uint16_t status); 126 123 int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts); 124 int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch); 127 125 128 126 /** Safely dispose host controller internal structures -
uspace/drv/bus/usb/uhci/root_hub.c
rd09791e6 ra720ff6 36 36 #include <str_error.h> 37 37 #include <stdio.h> 38 #include <ops/hw_res.h> 38 39 40 #include <usb_iface.h> 39 41 #include <usb/debug.h> 40 42 41 43 #include "root_hub.h" 44 /** DDF support structure for uhci_rhd driver, provides I/O resources */ 45 typedef struct { 46 /** List of resources available to the root hub. */ 47 hw_resource_list_t resource_list; 48 /** The only resource in the RH resource list */ 49 hw_resource_t io_regs; 42 50 51 devman_handle_t hc_handle; 52 } rh_t; 53 54 /** Gets handle of the respective hc. 55 * 56 * @param[in] fun DDF function of uhci device. 57 * @param[out] handle Host cotnroller handle. 58 * @return Error code. 59 */ 60 static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle) 61 { 62 assert(fun); 63 rh_t *rh = ddf_fun_data_get(fun); 64 65 if (handle != NULL) 66 *handle = rh->hc_handle; 67 return EOK; 68 } 69 70 /** USB interface implementation used by RH */ 71 static usb_iface_t usb_iface = { 72 .get_hc_handle = usb_iface_get_hc_handle, 73 }; 74 75 /** Get root hub hw resources (I/O registers). 76 * 77 * @param[in] fun Root hub function. 78 * @return Pointer to the resource list used by the root hub. 79 */ 80 static hw_resource_list_t *get_resource_list(ddf_fun_t *fun) 81 { 82 assert(fun); 83 rh_t *rh = ddf_fun_data_get(fun); 84 assert(rh); 85 return &rh->resource_list; 86 } 87 88 /** Interface to provide the root hub driver with hw info */ 89 static hw_res_ops_t hw_res_iface = { 90 .get_resource_list = get_resource_list, 91 .enable_interrupt = NULL, 92 }; 93 94 /** RH function support for uhci_rhd */ 95 static ddf_dev_ops_t rh_ops = { 96 .interfaces[USB_DEV_IFACE] = &usb_iface, 97 .interfaces[HW_RES_DEV_IFACE] = &hw_res_iface 98 }; 43 99 /** Root hub initialization 44 100 * @param[in] instance RH structure to initialize … … 48 104 * @return Error code. 49 105 */ 50 int rh_init(rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size) 106 int rh_init(ddf_dev_t *device, uintptr_t reg_addr, size_t reg_size, 107 devman_handle_t handle) 51 108 { 52 assert(instance); 53 assert(fun); 109 assert(device); 110 111 ddf_fun_t *fun = ddf_fun_create(device, fun_inner, "uhci_rh"); 112 if (!fun) { 113 usb_log_error("Failed to create UHCI RH function.\n"); 114 return ENOMEM; 115 } 116 ddf_fun_set_ops(fun, &rh_ops); 117 118 rh_t *instance = ddf_fun_data_alloc(fun, sizeof(rh_t)); 54 119 55 120 /* Initialize resource structure */ … … 62 127 instance->io_regs.res.io_range.endianness = LITTLE_ENDIAN; 63 128 64 const int ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100); 129 instance->hc_handle = handle; 130 131 int ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100); 65 132 if (ret != EOK) { 66 133 usb_log_error("Failed to add root hub match id: %s\n", 67 134 str_error(ret)); 135 ddf_fun_destroy(fun); 68 136 } 137 138 ret = ddf_fun_bind(fun); 139 if (ret != EOK) { 140 usb_log_error("Failed to bind root function: %s\n", 141 str_error(ret)); 142 ddf_fun_destroy(fun); 143 } 144 145 usb_log_fatal("RH ready, hc handle: %"PRIun"\n", handle); 69 146 return ret; 70 147 } -
uspace/drv/bus/usb/uhci/root_hub.h
rd09791e6 ra720ff6 37 37 38 38 #include <ddf/driver.h> 39 #include <ops/hw_res.h>40 39 41 /** DDF support structure for uhci_rhd driver, provides I/O resources */ 42 typedef struct rh { 43 /** List of resources available to the root hub. */ 44 hw_resource_list_t resource_list; 45 /** The only resource in the RH resource list */ 46 hw_resource_t io_regs; 47 } rh_t; 48 49 int rh_init( 50 rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size); 40 int rh_init(ddf_dev_t *device, uintptr_t reg_addr, size_t reg_size, 41 devman_handle_t handle); 51 42 52 43 #endif -
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.