Changeset fd07e526 in mainline
- Timestamp:
- 2011-09-16T14:50:20Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 432a269, d1e18573
- Parents:
- 47fecbb (diff), 82a31261 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- uspace
- Files:
-
- 6 added
- 8 deleted
- 42 edited
- 6 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ehci/hc_iface.c
r47fecbb rfd07e526 145 145 } 146 146 147 /** Schedule interrupt out transfer.148 *149 * The callback is supposed to be called once the transfer (on the wire) is150 * complete regardless of the outcome.151 * However, the callback could be called only when this function returns152 * with success status (i.e. returns EOK).153 *154 * @param[in] fun Device function the action was invoked on.155 * @param[in] target Target pipe (address and endpoint number) specification.156 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated157 * by the caller).158 * @param[in] size Size of the @p data buffer in bytes.159 * @param[in] callback Callback to be issued once the transfer is complete.160 * @param[in] arg Pass-through argument to the callback.161 * @return Error code.162 */163 static int interrupt_out(ddf_fun_t *fun, usb_target_t target,164 void *data, size_t size,165 usbhc_iface_transfer_out_callback_t callback, void *arg)166 {167 UNSUPPORTED("interrupt_out");168 169 return ENOTSUP;170 }171 172 /** Schedule interrupt in transfer.173 *174 * The callback is supposed to be called once the transfer (on the wire) is175 * complete regardless of the outcome.176 * However, the callback could be called only when this function returns177 * with success status (i.e. returns EOK).178 *179 * @param[in] fun Device function the action was invoked on.180 * @param[in] target Target pipe (address and endpoint number) specification.181 * @param[in] data Buffer where to store the data (in USB endianess,182 * allocated and deallocated by the caller).183 * @param[in] size Size of the @p data buffer in bytes.184 * @param[in] callback Callback to be issued once the transfer is complete.185 * @param[in] arg Pass-through argument to the callback.186 * @return Error code.187 */188 static int interrupt_in(ddf_fun_t *fun, usb_target_t target,189 void *data, size_t size,190 usbhc_iface_transfer_in_callback_t callback, void *arg)191 {192 UNSUPPORTED("interrupt_in");193 194 return ENOTSUP;195 }196 197 /** Schedule bulk out transfer.198 *199 * The callback is supposed to be called once the transfer (on the wire) is200 * complete regardless of the outcome.201 * However, the callback could be called only when this function returns202 * with success status (i.e. returns EOK).203 *204 * @param[in] fun Device function the action was invoked on.205 * @param[in] target Target pipe (address and endpoint number) specification.206 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated207 * by the caller).208 * @param[in] size Size of the @p data buffer in bytes.209 * @param[in] callback Callback to be issued once the transfer is complete.210 * @param[in] arg Pass-through argument to the callback.211 * @return Error code.212 */213 static int bulk_out(ddf_fun_t *fun, usb_target_t target,214 void *data, size_t size,215 usbhc_iface_transfer_out_callback_t callback, void *arg)216 {217 UNSUPPORTED("bulk_out");218 219 return ENOTSUP;220 }221 222 /** Schedule bulk in transfer.223 *224 * The callback is supposed to be called once the transfer (on the wire) is225 * complete regardless of the outcome.226 * However, the callback could be called only when this function returns227 * with success status (i.e. returns EOK).228 *229 * @param[in] fun Device function the action was invoked on.230 * @param[in] target Target pipe (address and endpoint number) specification.231 * @param[in] data Buffer where to store the data (in USB endianess,232 * allocated and deallocated by the caller).233 * @param[in] size Size of the @p data buffer in bytes.234 * @param[in] callback Callback to be issued once the transfer is complete.235 * @param[in] arg Pass-through argument to the callback.236 * @return Error code.237 */238 static int bulk_in(ddf_fun_t *fun, usb_target_t target,239 void *data, size_t size,240 usbhc_iface_transfer_in_callback_t callback, void *arg)241 {242 UNSUPPORTED("bulk_in");243 244 return ENOTSUP;245 }246 247 /** Schedule control write transfer.248 *249 * The callback is supposed to be called once the transfer (on the wire) is250 * complete regardless of the outcome.251 * However, the callback could be called only when this function returns252 * with success status (i.e. returns EOK).253 *254 * @param[in] fun Device function the action was invoked on.255 * @param[in] target Target pipe (address and endpoint number) specification.256 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated257 * and deallocated by the caller).258 * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.259 * @param[in] data_buffer Data buffer (in USB endianess, allocated and260 * deallocated by the caller).261 * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.262 * @param[in] callback Callback to be issued once the transfer is complete.263 * @param[in] arg Pass-through argument to the callback.264 * @return Error code.265 */266 static int control_write(ddf_fun_t *fun, usb_target_t target,267 void *setup_packet, size_t setup_packet_size,268 void *data_buffer, size_t data_buffer_size,269 usbhc_iface_transfer_out_callback_t callback, void *arg)270 {271 UNSUPPORTED("control_write");272 273 return ENOTSUP;274 }275 276 /** Schedule control read transfer.277 *278 * The callback is supposed to be called once the transfer (on the wire) is279 * complete regardless of the outcome.280 * However, the callback could be called only when this function returns281 * with success status (i.e. returns EOK).282 *283 * @param[in] fun Device function the action was invoked on.284 * @param[in] target Target pipe (address and endpoint number) specification.285 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated286 * and deallocated by the caller).287 * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.288 * @param[in] data_buffer Buffer where to store the data (in USB endianess,289 * allocated and deallocated by the caller).290 * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.291 * @param[in] callback Callback to be issued once the transfer is complete.292 * @param[in] arg Pass-through argument to the callback.293 * @return Error code.294 */295 static int control_read(ddf_fun_t *fun, usb_target_t target,296 void *setup_packet, size_t setup_packet_size,297 void *data_buffer, size_t data_buffer_size,298 usbhc_iface_transfer_in_callback_t callback, void *arg)299 {300 UNSUPPORTED("control_read");301 302 return ENOTSUP;303 }304 305 147 /** Host controller interface implementation for EHCI. */ 306 148 usbhc_iface_t ehci_hc_iface = { … … 312 154 .register_endpoint = register_endpoint, 313 155 .unregister_endpoint = unregister_endpoint, 314 315 .interrupt_out = interrupt_out,316 .interrupt_in = interrupt_in,317 318 .bulk_out = bulk_out,319 .bulk_in = bulk_in,320 321 .control_write = control_write,322 .control_read = control_read323 156 }; 324 157 -
uspace/drv/bus/usb/ohci/Makefile
r47fecbb rfd07e526 44 44 45 45 SOURCES = \ 46 batch.c \47 46 endpoint_list.c \ 48 47 hc.c \ 49 hcd_endpoint.c \50 iface.c \51 48 main.c \ 52 49 ohci.c \ 50 ohci_batch.c \ 51 ohci_endpoint.c \ 53 52 pci.c \ 54 53 root_hub.c \ -
uspace/drv/bus/usb/ohci/endpoint_list.c
r47fecbb rfd07e526 87 87 * The endpoint is added to the end of the list and queue. 88 88 */ 89 void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)89 void endpoint_list_add_ep(endpoint_list_t *instance, ohci_endpoint_t *ep) 90 90 { 91 91 assert(instance); 92 assert(hcd_ep); 93 usb_log_debug2("Queue %s: Adding endpoint(%p).\n", 94 instance->name, hcd_ep); 92 assert(ep); 93 usb_log_debug2("Queue %s: Adding endpoint(%p).\n", instance->name, ep); 95 94 96 95 fibril_mutex_lock(&instance->guard); … … 103 102 } else { 104 103 /* There are active EDs, get the last one */ 105 hcd_endpoint_t *last = list_get_instance(106 list_last(&instance->endpoint_list), hcd_endpoint_t, link);104 ohci_endpoint_t *last = list_get_instance( 105 list_last(&instance->endpoint_list), ohci_endpoint_t, link); 107 106 last_ed = last->ed; 108 107 } 109 108 /* Keep link */ 110 hcd_ep->ed->next = last_ed->next;109 ep->ed->next = last_ed->next; 111 110 /* Make sure ED is written to the memory */ 112 111 write_barrier(); 113 112 114 113 /* Add ed to the hw queue */ 115 ed_append_ed(last_ed, hcd_ep->ed);114 ed_append_ed(last_ed, ep->ed); 116 115 /* Make sure ED is updated */ 117 116 write_barrier(); 118 117 119 118 /* Add to the sw list */ 120 list_append(& hcd_ep->link, &instance->endpoint_list);119 list_append(&ep->link, &instance->endpoint_list); 121 120 122 hcd_endpoint_t *first = list_get_instance(123 list_first(&instance->endpoint_list), hcd_endpoint_t, link);121 ohci_endpoint_t *first = list_get_instance( 122 list_first(&instance->endpoint_list), ohci_endpoint_t, link); 124 123 usb_log_debug("HCD EP(%p) added to list %s, first is %p(%p).\n", 125 hcd_ep, instance->name, first, first->ed);124 ep, instance->name, first, first->ed); 126 125 if (last_ed == instance->list_head) { 127 126 usb_log_debug2("%s head ED(%p-0x%0" PRIx32 "): %x:%x:%x:%x.\n", … … 138 137 * @param[in] endpoint Endpoint to remove. 139 138 */ 140 void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)139 void endpoint_list_remove_ep(endpoint_list_t *instance, ohci_endpoint_t *ep) 141 140 { 142 141 assert(instance); 143 142 assert(instance->list_head); 144 assert( hcd_ep);145 assert( hcd_ep->ed);143 assert(ep); 144 assert(ep->ed); 146 145 147 146 fibril_mutex_lock(&instance->guard); 148 147 149 usb_log_debug2( 150 "Queue %s: removing endpoint(%p).\n", instance->name, hcd_ep); 148 usb_log_debug2("Queue %s: removing endpoint(%p).\n", instance->name, ep); 151 149 152 150 const char *qpos = NULL; 153 151 ed_t *prev_ed; 154 152 /* Remove from the hardware queue */ 155 if (list_first(&instance->endpoint_list) == & hcd_ep->link) {153 if (list_first(&instance->endpoint_list) == &ep->link) { 156 154 /* I'm the first one here */ 157 155 prev_ed = instance->list_head; 158 156 qpos = "FIRST"; 159 157 } else { 160 hcd_endpoint_t *prev =161 list_get_instance( hcd_ep->link.prev, hcd_endpoint_t, link);158 ohci_endpoint_t *prev = 159 list_get_instance(ep->link.prev, ohci_endpoint_t, link); 162 160 prev_ed = prev->ed; 163 161 qpos = "NOT FIRST"; 164 162 } 165 assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys( hcd_ep->ed));166 prev_ed->next = hcd_ep->ed->next;163 assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(ep->ed)); 164 prev_ed->next = ep->ed->next; 167 165 /* Make sure ED is updated */ 168 166 write_barrier(); 169 167 170 168 usb_log_debug("HCD EP(%p) removed (%s) from %s, next %x.\n", 171 hcd_ep, qpos, instance->name, hcd_ep->ed->next);169 ep, qpos, instance->name, ep->ed->next); 172 170 173 171 /* Remove from the endpoint list */ 174 list_remove(& hcd_ep->link);172 list_remove(&ep->link); 175 173 fibril_mutex_unlock(&instance->guard); 176 174 } -
uspace/drv/bus/usb/ohci/endpoint_list.h
r47fecbb rfd07e526 37 37 #include <fibril_synch.h> 38 38 39 #include " hcd_endpoint.h"39 #include "ohci_endpoint.h" 40 40 #include "hw_struct/endpoint_descriptor.h" 41 41 #include "utils/malloc32.h" … … 69 69 int endpoint_list_init(endpoint_list_t *instance, const char *name); 70 70 void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next); 71 void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);72 void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);71 void endpoint_list_add_ep(endpoint_list_t *instance, ohci_endpoint_t *ep); 72 void endpoint_list_remove_ep(endpoint_list_t *instance, ohci_endpoint_t *ep); 73 73 #endif 74 74 /** -
uspace/drv/bus/usb/ohci/hc.c
r47fecbb rfd07e526 42 42 43 43 #include "hc.h" 44 #include " hcd_endpoint.h"44 #include "ohci_endpoint.h" 45 45 46 46 #define OHCI_USED_INTERRUPTS \ … … 61 61 static int hc_init_memory(hc_t *instance); 62 62 static int interrupt_emulator(hc_t *instance); 63 63 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch); 64 64 /*----------------------------------------------------------------------------*/ 65 65 /** Get number of commands used in IRQ code. … … 128 128 129 129 const usb_address_t hub_address = 130 device_keeper_get_free_address(&instance->manager, USB_SPEED_FULL); 130 usb_device_manager_get_free_address( 131 &instance->generic.dev_manager, USB_SPEED_FULL); 131 132 if (hub_address <= 0) { 132 133 usb_log_error("Failed to get OHCI root hub address: %s\n", … … 135 136 } 136 137 instance->rh.address = hub_address; 137 usb_device_ keeper_bind(138 &instance-> manager, hub_address, hub_fun->handle);139 140 #define CHECK_RET_ RELEASE(ret, message...) \138 usb_device_manager_bind( 139 &instance->generic.dev_manager, hub_address, hub_fun->handle); 140 141 #define CHECK_RET_UNREG_RETURN(ret, message...) \ 141 142 if (ret != EOK) { \ 142 143 usb_log_error(message); \ 143 hc_remove_endpoint(instance, hub_address, 0, USB_DIRECTION_BOTH); \ 144 usb_device_keeper_release(&instance->manager, hub_address); \ 144 usb_endpoint_manager_unregister_ep( \ 145 &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH);\ 146 usb_device_manager_release( \ 147 &instance->generic.dev_manager, hub_address); \ 145 148 return ret; \ 146 149 } else (void)0 147 148 int ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL, 149 USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0); 150 CHECK_RET_RELEASE(ret, 151 "Failed to add OHCI root hub endpoint 0: %s.\n", str_error(ret)); 150 int ret = usb_endpoint_manager_add_ep( 151 &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH, 152 USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64, 0); 153 CHECK_RET_UNREG_RETURN(ret, 154 "Failed to register root hub control endpoint: %s.\n", 155 str_error(ret)); 152 156 153 157 ret = ddf_fun_add_match_id(hub_fun, "usb&class=hub", 100); 154 CHECK_RET_ RELEASE(ret,158 CHECK_RET_UNREG_RETURN(ret, 155 159 "Failed to add root hub match-id: %s.\n", str_error(ret)); 156 160 157 161 ret = ddf_fun_bind(hub_fun); 158 CHECK_RET_ RELEASE(ret,162 CHECK_RET_UNREG_RETURN(ret, 159 163 "Failed to bind root hub function: %s.\n", str_error(ret)); 160 164 … … 187 191 188 192 list_initialize(&instance->pending_batches); 189 usb_device_keeper_init(&instance->manager); 190 191 ret = usb_endpoint_manager_init(&instance->ep_manager, 192 BANDWIDTH_AVAILABLE_USB11); 193 CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n", 193 194 ret = hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11, 195 bandwidth_count_usb11); 196 CHECK_RET_RETURN(ret, "Failed to initialize generic driver: %s.\n", 194 197 str_error(ret)); 198 instance->generic.private_data = instance; 199 instance->generic.schedule = hc_schedule; 200 instance->generic.ep_add_hook = ohci_endpoint_init; 195 201 196 202 ret = hc_init_memory(instance); … … 215 221 } 216 222 /*----------------------------------------------------------------------------*/ 217 /** Create and register endpoint structures. 218 * 219 * @param[in] instance OHCI driver structure. 220 * @param[in] address USB address of the device. 221 * @param[in] endpoint USB endpoint number. 222 * @param[in] speed Communication speeed of the device. 223 * @param[in] type Endpoint's transfer type. 224 * @param[in] direction Endpoint's direction. 225 * @param[in] mps Maximum packet size the endpoint accepts. 226 * @param[in] size Maximum allowed buffer size. 227 * @param[in] interval Time between transfers(interrupt transfers only). 228 * @return Error code 229 */ 230 int hc_add_endpoint( 231 hc_t *instance, usb_address_t address, usb_endpoint_t endpoint, 232 usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction, 233 size_t mps, size_t size, unsigned interval) 234 { 235 endpoint_t *ep = 236 endpoint_get(address, endpoint, direction, type, speed, mps); 237 if (ep == NULL) 238 return ENOMEM; 239 240 hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep); 241 if (hcd_ep == NULL) { 242 endpoint_destroy(ep); 243 return ENOMEM; 244 } 245 246 int ret = 247 usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size); 248 if (ret != EOK) { 249 hcd_endpoint_clear(ep); 250 endpoint_destroy(ep); 251 return ret; 252 } 253 254 /* Enqueue hcd_ep */ 223 void hc_enqueue_endpoint(hc_t *instance, endpoint_t *ep) 224 { 225 endpoint_list_t *list = &instance->lists[ep->transfer_type]; 226 ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep); 227 /* Enqueue ep */ 255 228 switch (ep->transfer_type) { 256 229 case USB_TRANSFER_CONTROL: 257 230 instance->registers->control &= ~C_CLE; 258 endpoint_list_add_ep( 259 &instance->lists[ep->transfer_type], hcd_ep); 231 endpoint_list_add_ep(list, ohci_ep); 260 232 instance->registers->control_current = 0; 261 233 instance->registers->control |= C_CLE; … … 263 235 case USB_TRANSFER_BULK: 264 236 instance->registers->control &= ~C_BLE; 265 endpoint_list_add_ep( 266 &instance->lists[ep->transfer_type], hcd_ep); 237 endpoint_list_add_ep(list, ohci_ep); 267 238 instance->registers->control |= C_BLE; 268 239 break; … … 270 241 case USB_TRANSFER_INTERRUPT: 271 242 instance->registers->control &= (~C_PLE & ~C_IE); 272 endpoint_list_add_ep( 273 &instance->lists[ep->transfer_type], hcd_ep); 243 endpoint_list_add_ep(list, ohci_ep); 274 244 instance->registers->control |= C_PLE | C_IE; 275 245 break; 276 246 } 277 278 return EOK; 279 } 280 /*----------------------------------------------------------------------------*/ 281 /** Dequeue and delete endpoint structures 282 * 283 * @param[in] instance OHCI hc driver structure. 284 * @param[in] address USB address of the device. 285 * @param[in] endpoint USB endpoint number. 286 * @param[in] direction Direction of the endpoint. 287 * @return Error code 288 */ 289 int hc_remove_endpoint(hc_t *instance, usb_address_t address, 290 usb_endpoint_t endpoint, usb_direction_t direction) 291 { 292 assert(instance); 293 fibril_mutex_lock(&instance->guard); 294 endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager, 295 address, endpoint, direction, NULL); 296 if (ep == NULL) { 297 usb_log_error("Endpoint unregister failed: No such EP.\n"); 298 fibril_mutex_unlock(&instance->guard); 299 return ENOENT; 300 } 301 302 hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep); 303 if (hcd_ep) { 304 /* Dequeue hcd_ep */ 305 switch (ep->transfer_type) { 306 case USB_TRANSFER_CONTROL: 307 instance->registers->control &= ~C_CLE; 308 endpoint_list_remove_ep( 309 &instance->lists[ep->transfer_type], hcd_ep); 310 instance->registers->control_current = 0; 311 instance->registers->control |= C_CLE; 312 break; 313 case USB_TRANSFER_BULK: 314 instance->registers->control &= ~C_BLE; 315 endpoint_list_remove_ep( 316 &instance->lists[ep->transfer_type], hcd_ep); 317 instance->registers->control |= C_BLE; 318 break; 319 case USB_TRANSFER_ISOCHRONOUS: 320 case USB_TRANSFER_INTERRUPT: 321 instance->registers->control &= (~C_PLE & ~C_IE); 322 endpoint_list_remove_ep( 323 &instance->lists[ep->transfer_type], hcd_ep); 324 instance->registers->control |= C_PLE | C_IE; 325 break; 326 default: 327 break; 328 } 329 hcd_endpoint_clear(ep); 330 } else { 331 usb_log_warning("Endpoint without hcd equivalent structure.\n"); 332 } 333 int ret = usb_endpoint_manager_unregister_ep(&instance->ep_manager, 334 address, endpoint, direction); 335 fibril_mutex_unlock(&instance->guard); 336 return ret; 337 } 338 /*----------------------------------------------------------------------------*/ 339 /** Get access to endpoint structures 340 * 341 * @param[in] instance OHCI hc driver structure. 342 * @param[in] address USB address of the device. 343 * @param[in] endpoint USB endpoint number. 344 * @param[in] direction Direction of the endpoint. 345 * @param[out] bw Reserved bandwidth. 346 * @return Error code 347 */ 348 endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address, 349 usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw) 350 { 351 assert(instance); 352 fibril_mutex_lock(&instance->guard); 353 endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager, 354 address, endpoint, direction, bw); 355 fibril_mutex_unlock(&instance->guard); 356 return ep; 247 } 248 /*----------------------------------------------------------------------------*/ 249 void hc_dequeue_endpoint(hc_t *instance, endpoint_t *ep) 250 { 251 /* Dequeue ep */ 252 endpoint_list_t *list = &instance->lists[ep->transfer_type]; 253 ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep); 254 switch (ep->transfer_type) { 255 case USB_TRANSFER_CONTROL: 256 instance->registers->control &= ~C_CLE; 257 endpoint_list_remove_ep(list, ohci_ep); 258 instance->registers->control_current = 0; 259 instance->registers->control |= C_CLE; 260 break; 261 case USB_TRANSFER_BULK: 262 instance->registers->control &= ~C_BLE; 263 endpoint_list_remove_ep(list, ohci_ep); 264 instance->registers->control |= C_BLE; 265 break; 266 case USB_TRANSFER_ISOCHRONOUS: 267 case USB_TRANSFER_INTERRUPT: 268 instance->registers->control &= (~C_PLE & ~C_IE); 269 endpoint_list_remove_ep(list, ohci_ep); 270 instance->registers->control |= C_PLE | C_IE; 271 break; 272 default: 273 break; 274 } 357 275 } 358 276 /*----------------------------------------------------------------------------*/ … … 363 281 * @return Error code. 364 282 */ 365 int hc_schedule(hc _t *instance, usb_transfer_batch_t *batch)366 { 367 assert( instance);368 assert(batch);369 assert( batch->ep);283 int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch) 284 { 285 assert(hcd); 286 hc_t *instance = hcd->private_data; 287 assert(instance); 370 288 371 289 /* Check for root hub communication */ … … 374 292 return EOK; 375 293 } 294 ohci_transfer_batch_t *ohci_batch = ohci_transfer_batch_get(batch); 295 if (!ohci_batch) 296 return ENOMEM; 376 297 377 298 fibril_mutex_lock(&instance->guard); 378 list_append(& batch->link, &instance->pending_batches);379 batch_commit(batch);299 list_append(&ohci_batch->link, &instance->pending_batches); 300 ohci_transfer_batch_commit(ohci_batch); 380 301 381 302 /* Control and bulk schedules need a kick to start working */ … … 417 338 instance->registers->periodic_current); 418 339 419 link_t *current = instance->pending_batches.head.next;420 while (current != &instance->pending_batches.head) {340 link_t *current = list_first(&instance->pending_batches); 341 while (current && current != &instance->pending_batches.head) { 421 342 link_t *next = current->next; 422 usb_transfer_batch_t *batch =423 usb_transfer_batch_from_link(current);424 425 if ( batch_is_complete(batch)) {343 ohci_transfer_batch_t *batch = 344 ohci_transfer_batch_from_link(current); 345 346 if (ohci_transfer_batch_is_complete(batch)) { 426 347 list_remove(current); 427 usb_transfer_batch_finish(batch);348 ohci_transfer_batch_finish_dispose(batch); 428 349 } 429 350 … … 434 355 435 356 if (status & I_UE) { 357 usb_log_fatal("Error like no other!\n"); 436 358 hc_start(instance); 437 359 } -
uspace/drv/bus/usb/ohci/hc.h
r47fecbb rfd07e526 41 41 42 42 #include <usb/usb.h> 43 #include <usb/host/device_keeper.h> 44 #include <usb/host/usb_endpoint_manager.h> 45 #include <usbhc_iface.h> 43 #include <usb/host/hcd.h> 46 44 47 #include " batch.h"45 #include "ohci_batch.h" 48 46 #include "ohci_regs.h" 49 47 #include "root_hub.h" … … 53 51 /** Main OHCI driver structure */ 54 52 typedef struct hc { 55 /** USB bus driver, devices and addresses */ 56 usb_device_keeper_t manager; 57 /** USB bus driver, endpoints */ 58 usb_endpoint_manager_t ep_manager; 53 /** Generic USB hc driver */ 54 hcd_t generic; 59 55 60 56 /** Memory mapped I/O registers area */ … … 81 77 int hc_get_irq_commands( 82 78 irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size); 79 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun); 83 80 int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts); 84 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun);85 81 86 82 /** Safely dispose host controller internal structures … … 88 84 * @param[in] instance Host controller structure to use. 89 85 */ 90 static inline void hc_fini(hc_t *instance) 91 { /* TODO: implement*/ }; 86 static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ }; 92 87 93 int hc_add_endpoint(hc_t *instance, usb_address_t address, usb_endpoint_t ep, 94 usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction, 95 size_t max_packet_size, size_t size, unsigned interval); 96 int hc_remove_endpoint(hc_t *instance, usb_address_t address, 97 usb_endpoint_t endpoint, usb_direction_t direction); 98 endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address, 99 usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw); 88 void hc_enqueue_endpoint(hc_t *instance, endpoint_t *ep); 89 void hc_dequeue_endpoint(hc_t *instance, endpoint_t *ep); 100 90 101 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);102 91 void hc_interrupt(hc_t *instance, uint32_t status); 103 104 /** Get and cast pointer to the driver data105 *106 * @param[in] fun DDF function pointer107 * @return cast pointer to driver_data108 */109 static inline hc_t * fun_to_hc(ddf_fun_t *fun)110 { return fun->driver_data; }111 92 #endif 112 93 /** -
uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c
r47fecbb rfd07e526 39 39 static unsigned togg[2] = { TD_STATUS_T_0, TD_STATUS_T_1 }; 40 40 41 void td_init( 42 td_t *instance, usb_direction_t dir,void *buffer, size_t size, int toggle)41 void td_init(td_t *instance, 42 usb_direction_t dir, const void *buffer, size_t size, int toggle) 43 43 { 44 44 assert(instance); -
uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h
r47fecbb rfd07e526 75 75 } __attribute__((packed)) td_t; 76 76 77 void td_init( 78 td_t *instance, usb_direction_t dir,void *buffer, size_t size, int toggle);77 void td_init(td_t *instance, 78 usb_direction_t dir, const void *buffer, size_t size, int toggle); 79 79 80 80 inline static void td_set_next(td_t *instance, td_t *next) -
uspace/drv/bus/usb/ohci/ohci.c
r47fecbb rfd07e526 42 42 43 43 #include "ohci.h" 44 #include "iface.h"45 44 #include "pci.h" 46 45 #include "hc.h" 47 #include "root_hub.h"48 46 49 47 typedef struct ohci { … … 52 50 53 51 hc_t hc; 54 rh_t rh;55 52 } ohci_t; 56 53 … … 89 86 { 90 87 assert(fun); 91 usb_device_keeper_t *manager = &dev_to_ohci(fun->dev)->hc.manager; 92 93 usb_address_t addr = usb_device_keeper_find(manager, handle); 88 usb_device_manager_t *manager = 89 &dev_to_ohci(fun->dev)->hc.generic.dev_manager; 90 91 const usb_address_t addr = usb_device_manager_find(manager, handle); 94 92 if (addr < 0) { 95 93 return addr; … … 129 127 /** Standard USB HC options (HC interface) */ 130 128 static ddf_dev_ops_t hc_ops = { 131 .interfaces[USBHC_DEV_IFACE] = &hc _iface, /* see iface.h/c */129 .interfaces[USBHC_DEV_IFACE] = &hcd_iface, 132 130 }; 133 131 /*----------------------------------------------------------------------------*/ … … 150 148 int device_setup_ohci(ddf_dev_t *device) 151 149 { 150 assert(device); 151 152 152 ohci_t *instance = malloc(sizeof(ohci_t)); 153 153 if (instance == NULL) { … … 155 155 return ENOMEM; 156 156 } 157 instance->rh_fun = NULL; 158 instance->hc_fun = NULL; 157 159 158 160 #define CHECK_RET_DEST_FREE_RETURN(ret, message...) \ 159 161 if (ret != EOK) { \ 160 162 if (instance->hc_fun) { \ 161 instance->hc_fun->ops = NULL; \162 instance->hc_fun->driver_data = NULL; \163 163 ddf_fun_destroy(instance->hc_fun); \ 164 164 } \ 165 165 if (instance->rh_fun) { \ 166 instance->rh_fun->ops = NULL; \167 instance->rh_fun->driver_data = NULL; \168 166 ddf_fun_destroy(instance->rh_fun); \ 169 167 } \ 170 168 free(instance); \ 171 device->driver_data = NULL; \172 169 usb_log_error(message); \ 173 170 return ret; \ 174 171 } else (void)0 175 172 176 instance->rh_fun = NULL;177 173 instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci_hc"); 178 174 int ret = instance->hc_fun ? EOK : ENOMEM; … … 194 190 ret = pci_get_my_registers(device, ®_base, ®_size, &irq); 195 191 CHECK_RET_DEST_FREE_RETURN(ret, 196 "Failed to get memory addresses for %" PRIun ": %s.\n",192 "Failed to get register memory addresses for %" PRIun ": %s.\n", 197 193 device->handle, str_error(ret)); 198 194 usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n", … … 201 197 const size_t cmd_count = hc_irq_cmd_count(); 202 198 irq_cmd_t irq_cmds[cmd_count]; 199 irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds }; 200 203 201 ret = 204 202 hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size); … … 206 204 "Failed to generate IRQ commands: %s.\n", str_error(ret)); 207 205 208 irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };209 206 210 207 /* Register handler to avoid interrupt lockup */ … … 234 231 #define CHECK_RET_FINI_RETURN(ret, message...) \ 235 232 if (ret != EOK) { \ 233 hc_fini(&instance->hc); \ 236 234 unregister_interrupt_handler(device, irq); \ 237 hc_fini(&instance->hc); \238 235 CHECK_RET_DEST_FREE_RETURN(ret, message); \ 239 236 } else (void)0 … … 248 245 "Failed to add OHCI to HC class: %s.\n", str_error(ret)); 249 246 250 hc_register_hub(&instance->hc, instance->rh_fun); 251 return EOK; 252 253 #undef CHECK_RET_DEST_FUN_RETURN 247 ret = hc_register_hub(&instance->hc, instance->rh_fun); 248 CHECK_RET_FINI_RETURN(ret, 249 "Failed to register OHCI root hub: %s.\n", str_error(ret)); 250 return ret; 251 254 252 #undef CHECK_RET_FINI_RETURN 255 253 } -
uspace/drv/bus/usb/ohci/ohci_batch.h
r47fecbb rfd07e526 35 35 #define DRV_OHCI_BATCH_H 36 36 37 #include <adt/list.h> 37 38 #include <usbhc_iface.h> 38 39 #include <usb/usb.h> 39 #include <usb/host/device_keeper.h> 40 #include <usb/host/endpoint.h> 41 #include <usb/host/batch.h> 40 #include <usb/host/usb_transfer_batch.h> 42 41 43 usb_transfer_batch_t * batch_get( 44 ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size, 45 const char *setup_buffer, size_t setup_size, 46 usbhc_iface_transfer_in_callback_t func_in, 47 usbhc_iface_transfer_out_callback_t func_out, 48 void *arg); 42 #include "hw_struct/transfer_descriptor.h" 43 #include "hw_struct/endpoint_descriptor.h" 49 44 50 bool batch_is_complete(usb_transfer_batch_t *instance); 45 /** OHCI specific data required for USB transfer */ 46 typedef struct ohci_transfer_batch { 47 /** Link */ 48 link_t link; 49 /** Endpoint descriptor of the target endpoint. */ 50 ed_t *ed; 51 /** List of TDs needed for the transfer */ 52 td_t **tds; 53 /** Number of TDs used by the transfer */ 54 size_t td_count; 55 /** Dummy TD to be left at the ED and used by the next transfer */ 56 size_t leave_td; 57 /** Data buffer, must be accessible by the OHCI hw. */ 58 char *device_buffer; 59 /** Generic USB transfer structure */ 60 usb_transfer_batch_t *usb_batch; 61 } ohci_transfer_batch_t; 51 62 52 void batch_commit(usb_transfer_batch_t *instance); 53 54 void batch_control_write(usb_transfer_batch_t *instance); 55 56 void batch_control_read(usb_transfer_batch_t *instance); 57 58 void batch_interrupt_in(usb_transfer_batch_t *instance); 59 60 void batch_interrupt_out(usb_transfer_batch_t *instance); 61 62 void batch_bulk_in(usb_transfer_batch_t *instance); 63 64 void batch_bulk_out(usb_transfer_batch_t *instance); 63 ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *batch); 64 bool ohci_transfer_batch_is_complete(ohci_transfer_batch_t *batch); 65 void ohci_transfer_batch_commit(ohci_transfer_batch_t *batch); 66 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *batch); 67 /*----------------------------------------------------------------------------*/ 68 static inline ohci_transfer_batch_t *ohci_transfer_batch_from_link(link_t *l) 69 { 70 assert(l); 71 return list_get_instance(l, ohci_transfer_batch_t, link); 72 } 65 73 #endif 66 74 /** -
uspace/drv/bus/usb/ohci/ohci_endpoint.c
r47fecbb rfd07e526 33 33 */ 34 34 #include "utils/malloc32.h" 35 #include "hcd_endpoint.h" 35 #include "ohci_endpoint.h" 36 #include "hc.h" 36 37 37 38 /** Callback to set toggle on ED. … … 40 41 * @param[in] toggle new value of toggle bit 41 42 */ 42 static void hcd_ep_toggle_set(void *hcd_ep, int toggle)43 static void ohci_ep_toggle_set(void *ohci_ep, int toggle) 43 44 { 44 hcd_endpoint_t *instance = hcd_ep;45 ohci_endpoint_t *instance = ohci_ep; 45 46 assert(instance); 46 47 assert(instance->ed); … … 53 54 * @return Current value of toggle bit. 54 55 */ 55 static int hcd_ep_toggle_get(void *hcd_ep)56 static int ohci_ep_toggle_get(void *ohci_ep) 56 57 { 57 hcd_endpoint_t *instance = hcd_ep;58 ohci_endpoint_t *instance = ohci_ep; 58 59 assert(instance); 59 60 assert(instance->ed); 60 61 return ed_toggle_get(instance->ed); 62 } 63 /*----------------------------------------------------------------------------*/ 64 /** Disposes hcd endpoint structure 65 * 66 * @param[in] hcd_ep endpoint structure 67 */ 68 static void ohci_endpoint_fini(endpoint_t *ep) 69 { 70 ohci_endpoint_t *instance = ep->hc_data.data; 71 hc_dequeue_endpoint(instance->hcd->private_data, ep); 72 if (instance) { 73 free32(instance->ed); 74 free32(instance->td); 75 free(instance); 76 } 61 77 } 62 78 /*----------------------------------------------------------------------------*/ … … 66 82 * @return pointer to a new hcd endpoint structure, NULL on failure. 67 83 */ 68 hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep)84 int ohci_endpoint_init(hcd_t *hcd, endpoint_t *ep) 69 85 { 70 86 assert(ep); 71 hcd_endpoint_t *hcd_ep = malloc(sizeof(hcd_endpoint_t));72 if ( hcd_ep == NULL)73 return NULL;87 ohci_endpoint_t *ohci_ep = malloc(sizeof(ohci_endpoint_t)); 88 if (ohci_ep == NULL) 89 return ENOMEM; 74 90 75 hcd_ep->ed = malloc32(sizeof(ed_t));76 if ( hcd_ep->ed == NULL) {77 free( hcd_ep);78 return NULL;91 ohci_ep->ed = malloc32(sizeof(ed_t)); 92 if (ohci_ep->ed == NULL) { 93 free(ohci_ep); 94 return ENOMEM; 79 95 } 80 96 81 hcd_ep->td = malloc32(sizeof(td_t));82 if ( hcd_ep->td == NULL) {83 free32( hcd_ep->ed);84 free( hcd_ep);85 return NULL;97 ohci_ep->td = malloc32(sizeof(td_t)); 98 if (ohci_ep->td == NULL) { 99 free32(ohci_ep->ed); 100 free(ohci_ep); 101 return ENOMEM; 86 102 } 87 103 88 ed_init(hcd_ep->ed, ep); 89 ed_set_td(hcd_ep->ed, hcd_ep->td); 90 endpoint_set_hc_data(ep, hcd_ep, hcd_ep_toggle_get, hcd_ep_toggle_set); 91 92 return hcd_ep; 93 } 94 /*----------------------------------------------------------------------------*/ 95 /** Disposes assigned hcd endpoint structure 96 * 97 * @param[in] ep USBD endpoint structure 98 */ 99 void hcd_endpoint_clear(endpoint_t *ep) 100 { 101 assert(ep); 102 hcd_endpoint_t *hcd_ep = ep->hc_data.data; 103 assert(hcd_ep); 104 free32(hcd_ep->ed); 105 free32(hcd_ep->td); 106 free(hcd_ep); 104 ed_init(ohci_ep->ed, ep); 105 ed_set_td(ohci_ep->ed, ohci_ep->td); 106 endpoint_set_hc_data( 107 ep, ohci_ep, ohci_endpoint_fini, ohci_ep_toggle_get, ohci_ep_toggle_set); 108 ohci_ep->hcd = hcd; 109 hc_enqueue_endpoint(hcd->private_data, ep); 110 return EOK; 107 111 } 108 112 /** -
uspace/drv/bus/usb/ohci/ohci_endpoint.h
r47fecbb rfd07e526 38 38 #include <adt/list.h> 39 39 #include <usb/host/endpoint.h> 40 #include <usb/host/hcd.h> 40 41 41 42 #include "hw_struct/endpoint_descriptor.h" … … 43 44 44 45 /** Connector structure linking ED to to prepared TD. */ 45 typedef struct hcd_endpoint {46 typedef struct ohci_endpoint { 46 47 /** OHCI endpoint descriptor */ 47 48 ed_t *ed; … … 50 51 /** Linked list used by driver software */ 51 52 link_t link; 52 } hcd_endpoint_t; 53 /** Device using this ep */ 54 hcd_t *hcd; 55 } ohci_endpoint_t; 53 56 54 hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep); 55 void hcd_endpoint_clear(endpoint_t *ep); 57 int ohci_endpoint_init(hcd_t *hcd, endpoint_t *ep); 56 58 57 /** Get and convert assigned hcd_endpoint_t structure59 /** Get and convert assigned ohci_endpoint_t structure 58 60 * @param[in] ep USBD endpoint structure. 59 61 * @return Pointer to assigned hcd endpoint structure 60 62 */ 61 static inline hcd_endpoint_t * hcd_endpoint_get(endpoint_t *ep)63 static inline ohci_endpoint_t * ohci_endpoint_get(endpoint_t *ep) 62 64 { 63 65 assert(ep); -
uspace/drv/bus/usb/ohci/root_hub.c
r47fecbb rfd07e526 121 121 assert(request); 122 122 123 memcpy(request->data_buffer, &mask, size);124 123 request->transfered_size = size; 125 usb_transfer_batch_finish_error(request, EOK);124 usb_transfer_batch_finish_error(request, &mask, size, EOK); 126 125 } 127 126 … … 206 205 usb_log_debug("Root hub got CONTROL packet\n"); 207 206 const int ret = control_request(instance, request); 208 usb_transfer_batch_finish_error(request, ret);207 usb_transfer_batch_finish_error(request, NULL, 0, ret); 209 208 break; 210 209 case USB_TRANSFER_INTERRUPT: … … 215 214 assert(instance->unfinished_interrupt_transfer == NULL); 216 215 instance->unfinished_interrupt_transfer = request; 217 break;216 return; 218 217 } 219 218 usb_log_debug("Processing changes...\n"); … … 223 222 default: 224 223 usb_log_error("Root hub got unsupported request.\n"); 225 usb_transfer_batch_finish_error(request, EINVAL); 226 } 224 usb_transfer_batch_finish_error(request, NULL, 0, EINVAL); 225 } 226 usb_transfer_batch_dispose(request); 227 227 } 228 228 /*----------------------------------------------------------------------------*/ … … 244 244 interrupt_request(instance->unfinished_interrupt_transfer, 245 245 mask, instance->interrupt_mask_size); 246 usb_transfer_batch_dispose(instance->unfinished_interrupt_transfer); 246 247 247 248 instance->unfinished_interrupt_transfer = NULL; … … 389 390 const uint32_t data = instance->registers->rh_status & 390 391 (RHS_LPS_FLAG | RHS_LPSC_FLAG | RHS_OCI_FLAG | RHS_OCIC_FLAG); 391 memcpy(request-> data_buffer, &data, 4);392 TRANSFER_OK( 4);392 memcpy(request->buffer, &data, sizeof(data)); 393 TRANSFER_OK(sizeof(data)); 393 394 } 394 395 … … 402 403 const uint32_t data = 403 404 instance->registers->rh_port_status[port - 1]; 404 memcpy(request-> data_buffer, &data, 4);405 TRANSFER_OK( 4);405 memcpy(request->buffer, &data, sizeof(data)); 406 TRANSFER_OK(sizeof(data)); 406 407 } 407 408 … … 483 484 } 484 485 485 memcpy(request-> data_buffer, descriptor, size);486 memcpy(request->buffer, descriptor, size); 486 487 TRANSFER_OK(size); 487 488 } … … 713 714 if (request->buffer_size != 1) 714 715 return EINVAL; 715 request-> data_buffer[0] = 1;716 request->buffer[0] = 1; 716 717 TRANSFER_OK(1); 717 718 -
uspace/drv/bus/usb/ohci/root_hub.h
r47fecbb rfd07e526 37 37 #include <usb/usb.h> 38 38 #include <usb/dev/driver.h> 39 #include <usb/host/usb_transfer_batch.h> 39 40 40 41 #include "ohci_regs.h" 41 #include "batch.h"42 42 43 43 #define HUB_DESCRIPTOR_MAX_SIZE (7 + 2 + 2) … … 66 66 /** size of hub descriptor */ 67 67 size_t hub_descriptor_size; 68 69 68 } rh_t; 70 69 -
uspace/drv/bus/usb/ohci/utils/malloc32.h
r47fecbb rfd07e526 46 46 * @return Physical address if exists, NULL otherwise. 47 47 */ 48 static inline uintptr_t addr_to_phys( void *addr)48 static inline uintptr_t addr_to_phys(const void *addr) 49 49 { 50 50 uintptr_t result; -
uspace/drv/bus/usb/uhci/Makefile
r47fecbb rfd07e526 42 42 43 43 SOURCES = \ 44 iface.c \44 hc.c \ 45 45 main.c \ 46 pci.c \ 47 root_hub.c \ 46 48 transfer_list.c \ 47 49 uhci.c \ 48 hc.c \ 49 root_hub.c \ 50 hw_struct/transfer_descriptor.c \ 51 pci.c \ 52 batch.c 50 uhci_batch.c \ 51 hw_struct/transfer_descriptor.c 53 52 54 53 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/bus/usb/uhci/hc.c
r47fecbb rfd07e526 41 41 42 42 #include "hc.h" 43 #include "uhci_batch.h" 43 44 44 45 #define UHCI_INTR_ALLOW_INTERRUPTS \ … … 46 47 #define UHCI_STATUS_USED_INTERRUPTS \ 47 48 (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT) 49 48 50 49 51 static const irq_cmd_t uhci_irq_commands[] = … … 57 59 }; 58 60 61 static void hc_init_hw(const hc_t *instance); 62 static int hc_init_mem_structures(hc_t *instance); 59 63 static int hc_init_transfer_lists(hc_t *instance); 60 static int hc_init_mem_structures(hc_t *instance); 61 static void hc_init_hw(hc_t *instance); 64 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch); 62 65 63 66 static int hc_interrupt_emulator(void *arg); … … 95 98 cmds[3].addr = (void*)®isters->usbsts; 96 99 return EOK; 100 } 101 /*----------------------------------------------------------------------------*/ 102 /** Take action based on the interrupt cause. 103 * 104 * @param[in] instance UHCI structure to use. 105 * @param[in] status Value of the status register at the time of interrupt. 106 * 107 * Interrupt might indicate: 108 * - transaction completed, either by triggering IOC, SPD, or an error 109 * - some kind of device error 110 * - resume from suspend state (not implemented) 111 */ 112 void hc_interrupt(hc_t *instance, uint16_t status) 113 { 114 assert(instance); 115 /* Lower 2 bits are transaction error and transaction complete */ 116 if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) { 117 LIST_INITIALIZE(done); 118 transfer_list_remove_finished( 119 &instance->transfers_interrupt, &done); 120 transfer_list_remove_finished( 121 &instance->transfers_control_slow, &done); 122 transfer_list_remove_finished( 123 &instance->transfers_control_full, &done); 124 transfer_list_remove_finished( 125 &instance->transfers_bulk_full, &done); 126 127 while (!list_empty(&done)) { 128 link_t *item = list_first(&done); 129 list_remove(item); 130 uhci_transfer_batch_t *batch = 131 uhci_transfer_batch_from_link(item); 132 uhci_transfer_batch_call_dispose(batch); 133 } 134 } 135 /* Resume interrupts are not supported */ 136 if (status & UHCI_STATUS_RESUME) { 137 usb_log_error("Resume interrupt!\n"); 138 } 139 140 /* Bits 4 and 5 indicate hc error */ 141 if (status & (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)) { 142 usb_log_error("UHCI hardware failure!.\n"); 143 ++instance->hw_failures; 144 transfer_list_abort_all(&instance->transfers_interrupt); 145 transfer_list_abort_all(&instance->transfers_control_slow); 146 transfer_list_abort_all(&instance->transfers_control_full); 147 transfer_list_abort_all(&instance->transfers_bulk_full); 148 149 if (instance->hw_failures < UHCI_ALLOWED_HW_FAIL) { 150 /* reinitialize hw, this triggers virtual disconnect*/ 151 hc_init_hw(instance); 152 } else { 153 usb_log_fatal("Too many UHCI hardware failures!.\n"); 154 hc_fini(instance); 155 } 156 } 97 157 } 98 158 /*----------------------------------------------------------------------------*/ … … 132 192 "Device registers at %p (%zuB) accessible.\n", io, reg_size); 133 193 194 ret = hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11, 195 bandwidth_count_usb11); 196 CHECK_RET_RETURN(ret, "Failed to initialize HCD generic driver: %s.\n", 197 str_error(ret)); 198 199 instance->generic.private_data = instance; 200 instance->generic.schedule = hc_schedule; 201 instance->generic.ep_add_hook = NULL; 202 203 #undef CHECK_RET_DEST_FUN_RETURN 204 134 205 ret = hc_init_mem_structures(instance); 135 CHECK_RET_RETURN(ret, 136 "Failed to initialize UHCI memory structures: %s.\n", 137 str_error(ret)); 206 if (ret != EOK) { 207 usb_log_error( 208 "Failed to initialize UHCI memory structures: %s.\n", 209 str_error(ret)); 210 hcd_destroy(&instance->generic); 211 return ret; 212 } 138 213 139 214 hc_init_hw(instance); … … 146 221 147 222 return EOK; 148 #undef CHECK_RET_DEST_FUN_RETURN149 223 } 150 224 /*----------------------------------------------------------------------------*/ … … 154 228 * For magic values see UHCI Design Guide 155 229 */ 156 void hc_init_hw( hc_t *instance)230 void hc_init_hw(const hc_t *instance) 157 231 { 158 232 assert(instance); … … 198 272 * 199 273 * Structures: 200 * - interrupt code (I/O addressses are customized per instance)201 274 * - transfer lists (queue heads need to be accessible by the hw) 202 275 * - frame list page (needs to be one UHCI hw accessible 4K page) … … 205 278 { 206 279 assert(instance); 207 #define CHECK_RET_RETURN(ret, message...) \ 208 if (ret != EOK) { \ 209 usb_log_error(message); \ 210 return ret; \ 211 } else (void) 0 280 281 /* Init USB frame list page */ 282 instance->frame_list = get_page(); 283 if (!instance->frame_list) { 284 return ENOMEM; 285 } 286 usb_log_debug("Initialized frame list at %p.\n", instance->frame_list); 212 287 213 288 /* Init transfer lists */ 214 289 int ret = hc_init_transfer_lists(instance); 215 CHECK_RET_RETURN(ret, "Failed to initialize transfer lists.\n"); 290 if (ret != EOK) { 291 usb_log_error("Failed to initialize transfer lists.\n"); 292 return_page(instance->frame_list); 293 return ENOMEM; 294 } 216 295 usb_log_debug("Initialized transfer lists.\n"); 217 296 218 /* Init device keeper */219 usb_device_keeper_init(&instance->manager);220 usb_log_debug("Initialized device keeper.\n");221 222 ret = usb_endpoint_manager_init(&instance->ep_manager,223 BANDWIDTH_AVAILABLE_USB11);224 CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n",225 str_error(ret));226 227 /* Init USB frame list page*/228 instance->frame_list = get_page();229 if (!instance->frame_list) {230 usb_log_error("Failed to get frame list page.\n");231 usb_endpoint_manager_destroy(&instance->ep_manager);232 return ENOMEM;233 }234 usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);235 297 236 298 /* Set all frames to point to the first queue head */ … … 243 305 244 306 return EOK; 245 #undef CHECK_RET_RETURN246 307 } 247 308 /*----------------------------------------------------------------------------*/ … … 316 377 * Checks for bandwidth availability and appends the batch to the proper queue. 317 378 */ 318 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch) 319 { 379 int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch) 380 { 381 assert(hcd); 382 hc_t *instance = hcd->private_data; 320 383 assert(instance); 321 384 assert(batch); 385 uhci_transfer_batch_t *uhci_batch = uhci_transfer_batch_get(batch); 386 if (!uhci_batch) { 387 usb_log_error("Failed to create UHCI transfer structures.\n"); 388 return ENOMEM; 389 } 322 390 323 391 transfer_list_t *list = 324 392 instance->transfers[batch->ep->speed][batch->ep->transfer_type]; 325 393 assert(list); 326 transfer_list_add_batch(list, batch); 327 328 return EOK; 329 } 330 /*----------------------------------------------------------------------------*/ 331 /** Take action based on the interrupt cause. 332 * 333 * @param[in] instance UHCI structure to use. 334 * @param[in] status Value of the status register at the time of interrupt. 335 * 336 * Interrupt might indicate: 337 * - transaction completed, either by triggering IOC, SPD, or an error 338 * - some kind of device error 339 * - resume from suspend state (not implemented) 340 */ 341 void hc_interrupt(hc_t *instance, uint16_t status) 342 { 343 assert(instance); 344 /* Lower 2 bits are transaction error and transaction complete */ 345 if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) { 346 LIST_INITIALIZE(done); 347 transfer_list_remove_finished( 348 &instance->transfers_interrupt, &done); 349 transfer_list_remove_finished( 350 &instance->transfers_control_slow, &done); 351 transfer_list_remove_finished( 352 &instance->transfers_control_full, &done); 353 transfer_list_remove_finished( 354 &instance->transfers_bulk_full, &done); 355 356 while (!list_empty(&done)) { 357 link_t *item = list_first(&done); 358 list_remove(item); 359 usb_transfer_batch_t *batch = 360 list_get_instance(item, usb_transfer_batch_t, link); 361 usb_transfer_batch_finish(batch); 362 } 363 } 364 /* Resume interrupts are not supported */ 365 if (status & UHCI_STATUS_RESUME) { 366 usb_log_error("Resume interrupt!\n"); 367 } 368 369 /* Bits 4 and 5 indicate hc error */ 370 if (status & (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)) { 371 usb_log_error("UHCI hardware failure!.\n"); 372 ++instance->hw_failures; 373 transfer_list_abort_all(&instance->transfers_interrupt); 374 transfer_list_abort_all(&instance->transfers_control_slow); 375 transfer_list_abort_all(&instance->transfers_control_full); 376 transfer_list_abort_all(&instance->transfers_bulk_full); 377 378 if (instance->hw_failures < UHCI_ALLOWED_HW_FAIL) { 379 /* reinitialize hw, this triggers virtual disconnect*/ 380 hc_init_hw(instance); 381 } else { 382 usb_log_fatal("Too many UHCI hardware failures!.\n"); 383 hc_fini(instance); 384 } 385 } 394 transfer_list_add_batch(list, uhci_batch); 395 396 return EOK; 386 397 } 387 398 /*----------------------------------------------------------------------------*/ … … 403 414 if (status != 0) 404 415 usb_log_debug2("UHCI status: %x.\n", status); 405 // Qemu fails to report stalled communication406 // see https://bugs.launchpad.net/qemu/+bug/757654407 // This is a simple workaround to force queue processing every time408 // status |= 1;409 416 hc_interrupt(instance, status); 410 417 async_usleep(UHCI_INT_EMULATOR_TIMEOUT); … … 412 419 return EOK; 413 420 } 414 /*--------------------------------------------------------------------------- */421 /*----------------------------------------------------------------------------*/ 415 422 /** Debug function, checks consistency of memory structures. 416 423 * -
uspace/drv/bus/usb/uhci/hc.h
r47fecbb rfd07e526 39 39 #include <ddi.h> 40 40 41 #include <usb/host/device_keeper.h> 42 #include <usb/host/usb_endpoint_manager.h> 43 #include <usb/host/batch.h> 41 #include <usb/host/hcd.h> 44 42 45 43 #include "transfer_list.h" … … 94 92 /** Main UHCI driver structure */ 95 93 typedef struct hc { 96 /** USB bus driver, devices and addresses */ 97 usb_device_keeper_t manager; 98 /** USB bus driver, endpoints */ 99 usb_endpoint_manager_t ep_manager; 94 /** Generic HCD driver structure */ 95 hcd_t generic; 100 96 101 97 /** Addresses of I/O registers */ … … 124 120 unsigned hw_failures; 125 121 } hc_t; 122 126 123 size_t hc_irq_cmd_count(void); 127 124 int hc_get_irq_commands( 128 125 irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size); 126 void hc_interrupt(hc_t *instance, uint16_t status); 129 127 int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts); 130 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);131 void hc_interrupt(hc_t *instance, uint16_t status);132 128 133 129 /** Safely dispose host controller internal structures … … 135 131 * @param[in] instance Host controller structure to use. 136 132 */ 137 static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ }; 138 139 /** Get and cast pointer to the driver data 140 * 141 * @param[in] fun DDF function pointer 142 * @return cast pointer to driver_data 143 */ 144 static inline hc_t * fun_to_hc(ddf_fun_t *fun) 145 { 146 assert(fun); 147 return fun->driver_data; 148 } 133 static inline void hc_fini(hc_t *instance) {} /* TODO: implement*/ 149 134 #endif 150 135 /** -
uspace/drv/bus/usb/uhci/hw_struct/link_pointer.h
r47fecbb rfd07e526 35 35 #define DRV_UHCI_HW_STRUCT_LINK_POINTER_H 36 36 37 /* UHCI link pointer, used by many data structures */37 /** UHCI link pointer, used by many data structures */ 38 38 typedef uint32_t link_pointer_t; 39 39 -
uspace/drv/bus/usb/uhci/hw_struct/queue_head.h
r47fecbb rfd07e526 58 58 assert(instance); 59 59 60 instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;61 instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;60 instance->element = LINK_POINTER_TERM; 61 instance->next = LINK_POINTER_TERM; 62 62 } 63 63 /*----------------------------------------------------------------------------*/ … … 71 71 static inline void qh_set_next_qh(qh_t *instance, qh_t *next) 72 72 { 73 uint32_t pa = addr_to_phys(next); 73 /* Physical address has to be below 4GB, 74 * it is an UHCI limitation and malloc32 75 * should guarantee this */ 76 const uint32_t pa = addr_to_phys(next); 74 77 if (pa) { 75 78 instance->next = LINK_POINTER_QH(pa); … … 88 91 static inline void qh_set_element_td(qh_t *instance, td_t *td) 89 92 { 90 uint32_t pa = addr_to_phys(td); 93 /* Physical address has to be below 4GB, 94 * it is an UHCI limitation and malloc32 95 * should guarantee this */ 96 const uint32_t pa = addr_to_phys(td); 91 97 if (pa) { 92 98 instance->element = LINK_POINTER_TD(pa); -
uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.c
r47fecbb rfd07e526 61 61 */ 62 62 void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso, 63 bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer,64 td_t *next)63 bool low_speed, usb_target_t target, usb_packet_id pid, const void *buffer, 64 const td_t *next) 65 65 { 66 66 assert(instance); … … 113 113 * @return Error code. 114 114 */ 115 int td_status( td_t *instance)115 int td_status(const td_t *instance) 116 116 { 117 117 assert(instance); … … 119 119 /* This is hc internal error it should never be reported. */ 120 120 if ((instance->status & TD_STATUS_ERROR_BIT_STUFF) != 0) 121 return E AGAIN;121 return EIO; 122 122 123 123 /* CRC or timeout error, like device not present or bad data, … … 150 150 * @param[in] instance TD structure to use. 151 151 */ 152 void td_print_status( td_t *instance)152 void td_print_status(const td_t *instance) 153 153 { 154 154 assert(instance); -
uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.h
r47fecbb rfd07e526 69 69 #define TD_STATUS_ACTLEN_MASK 0x7ff 70 70 71 /* double word with USB device specific info */71 /** Double word with USB device specific info */ 72 72 volatile uint32_t device; 73 73 #define TD_DEVICE_MAXLEN_POS 21 … … 87 87 /* According to UHCI design guide, there is 16 bytes of 88 88 * data available here. 89 * According to linux kernel the hardware does not care,90 * itjust needs to be aligned. We don't use it anyway.89 * According to Linux kernel the hardware does not care, 90 * memory just needs to be aligned. We don't use it anyway. 91 91 */ 92 92 } __attribute__((packed)) td_t; … … 95 95 void td_init(td_t *instance, int error_count, size_t size, bool toggle, 96 96 bool iso, bool low_speed, usb_target_t target, usb_packet_id pid, 97 void *buffer,td_t *next);97 const void *buffer, const td_t *next); 98 98 99 int td_status( td_t *instance);99 int td_status(const td_t *instance); 100 100 101 void td_print_status( td_t *instance);101 void td_print_status(const td_t *instance); 102 102 /*----------------------------------------------------------------------------*/ 103 103 /** Helper function for parsing actual size out of TD. … … 106 106 * @return Parsed actual size. 107 107 */ 108 static inline size_t td_act_size( td_t *instance)108 static inline size_t td_act_size(const td_t *instance) 109 109 { 110 110 assert(instance); 111 111 const uint32_t s = instance->status; 112 /* Actual size is encoded as n-1 (UHCI design guide p. 23) */ 112 113 return ((s >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK; 113 114 } … … 119 120 * false otherwise. 120 121 */ 121 static inline bool td_is_short( td_t *instance)122 static inline bool td_is_short(const td_t *instance) 122 123 { 123 124 const size_t act_size = td_act_size(instance); … … 134 135 * @return Toggle bit value. 135 136 */ 136 static inline int td_toggle( td_t *instance)137 static inline int td_toggle(const td_t *instance) 137 138 { 138 139 assert(instance); … … 145 146 * @return Active bit value. 146 147 */ 147 static inline bool td_is_active( td_t *instance)148 static inline bool td_is_active(const td_t *instance) 148 149 { 149 150 assert(instance); -
uspace/drv/bus/usb/uhci/main.c
r47fecbb rfd07e526 64 64 assert(device); 65 65 66 int ret = device_setup_uhci(device);66 const int ret = device_setup_uhci(device); 67 67 if (ret != EOK) { 68 68 usb_log_error("Failed to initialize UHCI driver: %s.\n", 69 69 str_error(ret)); 70 return ret; 70 } else { 71 usb_log_info("Controlling new UHCI device '%s'.\n", 72 device->name); 71 73 } 72 usb_log_info("Controlling new UHCI device '%s'.\n", device->name);73 74 74 return EOK;75 return ret; 75 76 } 76 77 /*----------------------------------------------------------------------------*/ -
uspace/drv/bus/usb/uhci/pci.c
r47fecbb rfd07e526 61 61 assert(io_reg_size); 62 62 assert(irq_no); 63 63 64 64 async_sess_t *parent_sess = 65 65 devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle, … … 67 67 if (!parent_sess) 68 68 return ENOMEM; 69 69 70 70 hw_resource_list_t hw_resources; 71 71 int rc = hw_res_get_resource_list(parent_sess, &hw_resources); … … 74 74 return rc; 75 75 } 76 76 77 77 uintptr_t io_address = 0; 78 78 size_t io_size = 0; … … 102 102 } 103 103 } 104 104 105 105 async_hangup(parent_sess); 106 106 107 107 if (!io_found || !irq_found) 108 108 return ENOENT; 109 109 110 110 *io_reg_address = io_address; 111 111 *io_reg_size = io_size; 112 112 *irq_no = irq; 113 113 114 114 return EOK; 115 115 } 116 116 /*----------------------------------------------------------------------------*/ 117 117 /** Call the PCI driver with a request to enable interrupts 118 118 * … … 127 127 if (!parent_sess) 128 128 return ENOMEM; 129 129 130 130 const bool enabled = hw_res_enable_interrupt(parent_sess); 131 131 async_hangup(parent_sess); 132 132 133 133 return enabled ? EOK : EIO; 134 134 } 135 135 /*----------------------------------------------------------------------------*/ 136 136 /** Call the PCI driver with a request to clear legacy support register 137 137 * … … 142 142 { 143 143 assert(device); 144 144 145 145 async_sess_t *parent_sess = 146 146 devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle, … … 148 148 if (!parent_sess) 149 149 return ENOMEM; 150 150 151 151 /* See UHCI design guide for these values p.45, 152 152 * write all WC bits in USB legacy register */ 153 153 const sysarg_t address = 0xc0; 154 154 const sysarg_t value = 0xaf00; 155 155 156 156 async_exch_t *exch = async_exchange_begin(parent_sess); 157 157 158 158 const int rc = async_req_3_0(exch, DEV_IFACE_ID(PCI_DEV_IFACE), 159 159 IPC_M_CONFIG_SPACE_WRITE_16, address, value); 160 160 161 161 async_exchange_end(exch); 162 162 async_hangup(parent_sess); 163 163 164 164 return rc; 165 165 } -
uspace/drv/bus/usb/uhci/root_hub.c
r47fecbb rfd07e526 50 50 int rh_init(rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size) 51 51 { 52 int ret; 53 52 assert(instance); 54 53 assert(fun); 55 56 ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100);57 if (ret != EOK) {58 usb_log_error("Failed to add root hub match id: %s\n",59 str_error(ret));60 return ret;61 }62 54 63 55 /* Initialize resource structure */ … … 70 62 instance->io_regs.res.io_range.endianness = LITTLE_ENDIAN; 71 63 72 return EOK; 64 const int ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100); 65 if (ret != EOK) { 66 usb_log_error("Failed to add root hub match id: %s\n", 67 str_error(ret)); 68 } 69 return ret; 73 70 } 74 71 /** -
uspace/drv/bus/usb/uhci/transfer_list.c
r47fecbb rfd07e526 37 37 #include <usb/debug.h> 38 38 #include <libarch/barrier.h> 39 39 40 #include "transfer_list.h" 40 #include "batch.h"41 41 42 42 static void transfer_list_remove_batch( 43 transfer_list_t *instance, u sb_transfer_batch_t *batch);43 transfer_list_t *instance, uhci_transfer_batch_t *uhci_batch); 44 44 /*----------------------------------------------------------------------------*/ 45 45 /** Initialize transfer list structures. … … 106 106 */ 107 107 void transfer_list_add_batch( 108 transfer_list_t *instance, usb_transfer_batch_t *batch) 109 { 110 assert(instance); 111 assert(batch); 112 usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch); 108 transfer_list_t *instance, uhci_transfer_batch_t *uhci_batch) 109 { 110 assert(instance); 111 assert(uhci_batch); 112 usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, 113 uhci_batch->usb_batch); 113 114 114 115 fibril_mutex_lock(&instance->guard); 115 116 116 qh_t *last_qh = NULL; 117 /* Assume there is nothing scheduled */ 118 qh_t *last_qh = instance->queue_head; 119 /* There is something scheduled */ 120 if (!list_empty(&instance->batch_list)) { 121 last_qh = uhci_transfer_batch_from_link( 122 list_last(&instance->batch_list))->qh; 123 } 117 124 /* Add to the hardware queue. */ 118 if (list_empty(&instance->batch_list)) { 119 /* There is nothing scheduled */ 120 last_qh = instance->queue_head; 121 } else { 122 /* There is something scheduled */ 123 usb_transfer_batch_t *last = usb_transfer_batch_from_link( 124 list_last(&instance->batch_list)); 125 last_qh = batch_qh(last); 126 } 127 const uint32_t pa = addr_to_phys(batch_qh(batch)); 125 const uint32_t pa = addr_to_phys(uhci_batch->qh); 128 126 assert((pa & LINK_POINTER_ADDRESS_MASK) == pa); 129 127 … … 132 130 133 131 /* keep link */ 134 batch_qh(batch)->next = last_qh->next;135 qh_set_next_qh(last_qh, batch_qh(batch));132 uhci_batch->qh->next = last_qh->next; 133 qh_set_next_qh(last_qh, uhci_batch->qh); 136 134 137 135 /* Make sure the pointer is updated */ … … 139 137 140 138 /* Add to the driver's list */ 141 list_append(& batch->link, &instance->batch_list);139 list_append(&uhci_batch->link, &instance->batch_list); 142 140 143 141 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " scheduled in queue %s.\n", 144 batch, USB_TRANSFER_BATCH_ARGS(*batch), instance->name); 142 uhci_batch, USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch), 143 instance->name); 145 144 fibril_mutex_unlock(&instance->guard); 146 145 } … … 157 156 158 157 fibril_mutex_lock(&instance->guard); 159 link_t *current = instance->batch_list.head.next;160 while (current != &instance->batch_list.head) {158 link_t *current = list_first(&instance->batch_list); 159 while (current && current != &instance->batch_list.head) { 161 160 link_t * const next = current->next; 162 u sb_transfer_batch_t *batch =163 u sb_transfer_batch_from_link(current);164 165 if ( batch_is_complete(batch)) {161 uhci_transfer_batch_t *batch = 162 uhci_transfer_batch_from_link(current); 163 164 if (uhci_transfer_batch_is_complete(batch)) { 166 165 /* Save for processing */ 167 166 transfer_list_remove_batch(instance, batch); … … 182 181 while (!list_empty(&instance->batch_list)) { 183 182 link_t * const current = list_first(&instance->batch_list); 184 u sb_transfer_batch_t *batch =185 u sb_transfer_batch_from_link(current);183 uhci_transfer_batch_t *batch = 184 uhci_transfer_batch_from_link(current); 186 185 transfer_list_remove_batch(instance, batch); 187 usb_transfer_batch_finish_error(batch, EINTR); 186 batch->usb_batch->error = EINTR; 187 uhci_transfer_batch_call_dispose(batch); 188 188 } 189 189 fibril_mutex_unlock(&instance->guard); … … 198 198 */ 199 199 void transfer_list_remove_batch( 200 transfer_list_t *instance, u sb_transfer_batch_t *batch)200 transfer_list_t *instance, uhci_transfer_batch_t *uhci_batch) 201 201 { 202 202 assert(instance); 203 203 assert(instance->queue_head); 204 assert( batch);205 assert( batch_qh(batch));204 assert(uhci_batch); 205 assert(uhci_batch->qh); 206 206 assert(fibril_mutex_is_locked(&instance->guard)); 207 207 208 usb_log_debug2( 209 "Queue %s: removing batch(%p).\n", instance->name, batch); 210 211 const char *qpos = NULL; 212 qh_t *prev_qh = NULL; 208 usb_log_debug2("Queue %s: removing batch(%p).\n", 209 instance->name, uhci_batch->usb_batch); 210 211 /* Assume I'm the first */ 212 const char *qpos = "FIRST"; 213 qh_t *prev_qh = instance->queue_head; 213 214 /* Remove from the hardware queue */ 214 if (list_first(&instance->batch_list) == &batch->link) { 215 /* I'm the first one here */ 216 prev_qh = instance->queue_head; 217 qpos = "FIRST"; 218 } else { 219 /* The thing before me is a batch too */ 220 usb_transfer_batch_t *prev = 221 usb_transfer_batch_from_link(batch->link.prev); 222 prev_qh = batch_qh(prev); 215 if (list_first(&instance->batch_list) != &uhci_batch->link) { 216 /* There is a batch in front of me */ 217 prev_qh = 218 uhci_transfer_batch_from_link(uhci_batch->link.prev)->qh; 223 219 qpos = "NOT FIRST"; 224 220 } 225 221 assert((prev_qh->next & LINK_POINTER_ADDRESS_MASK) 226 == addr_to_phys( batch_qh(batch)));227 prev_qh->next = batch_qh(batch)->next;222 == addr_to_phys(uhci_batch->qh)); 223 prev_qh->next = uhci_batch->qh->next; 228 224 229 225 /* Make sure the pointer is updated */ … … 231 227 232 228 /* Remove from the batch list */ 233 list_remove(& batch->link);229 list_remove(&uhci_batch->link); 234 230 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " removed (%s) " 235 231 "from %s, next: %x.\n", 236 batch, USB_TRANSFER_BATCH_ARGS(*batch),237 qpos, instance->name, batch_qh(batch)->next);232 uhci_batch, USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch), 233 qpos, instance->name, uhci_batch->qh->next); 238 234 } 239 235 /** -
uspace/drv/bus/usb/uhci/transfer_list.h
r47fecbb rfd07e526 36 36 37 37 #include <fibril_synch.h> 38 #include <usb/host/batch.h>39 38 40 39 #include "hw_struct/queue_head.h" 41 40 #include "uhci_batch.h" 42 41 /** Structure maintaining both hw queue and software list 43 42 * of currently executed transfers … … 46 45 /** Guard against multiple add/remove races */ 47 46 fibril_mutex_t guard; 48 /** UHCI hw structure represe ting this queue */47 /** UHCI hw structure representing this queue */ 49 48 qh_t *queue_head; 50 49 /** Assigned name, for nicer debug output */ … … 58 57 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next); 59 58 void transfer_list_add_batch( 60 transfer_list_t *instance, u sb_transfer_batch_t *batch);59 transfer_list_t *instance, uhci_transfer_batch_t *batch); 61 60 void transfer_list_remove_finished(transfer_list_t *instance, list_t *done); 62 61 void transfer_list_abort_all(transfer_list_t *instance); -
uspace/drv/bus/usb/uhci/uhci.c
r47fecbb rfd07e526 41 41 42 42 #include "uhci.h" 43 #include "iface.h"44 43 #include "pci.h" 45 44 … … 87 86 /** Operations supported by the HC driver */ 88 87 static ddf_dev_ops_t hc_ops = { 89 .interfaces[USBHC_DEV_IFACE] = &hc _iface, /* see iface.h/c */88 .interfaces[USBHC_DEV_IFACE] = &hcd_iface, /* see iface.h/c */ 90 89 }; 91 90 /*----------------------------------------------------------------------------*/ … … 100 99 { 101 100 assert(fun); 102 usb_device_keeper_t *manager = &dev_to_uhci(fun->dev)->hc.manager; 103 usb_address_t addr = usb_device_keeper_find(manager, handle); 101 usb_device_manager_t *manager = 102 &dev_to_uhci(fun->dev)->hc.generic.dev_manager; 103 const usb_address_t addr = usb_device_manager_find(manager, handle); 104 104 105 105 if (addr < 0) { … … 202 202 CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI HC function.\n"); 203 203 instance->hc_fun->ops = &hc_ops; 204 instance->hc_fun->driver_data = &instance->hc ;204 instance->hc_fun->driver_data = &instance->hc.generic; 205 205 206 206 instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci_rh"); -
uspace/drv/bus/usb/uhci/utils/malloc32.h
r47fecbb rfd07e526 50 50 * @return Physical address if exists, NULL otherwise. 51 51 */ 52 static inline uintptr_t addr_to_phys( void *addr)52 static inline uintptr_t addr_to_phys(const void *addr) 53 53 { 54 54 if (addr == NULL) … … 102 102 if (free_address == 0) 103 103 return NULL; 104 void * ret= as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE,104 void *address = as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE, 105 105 AS_AREA_READ | AS_AREA_WRITE); 106 if ( ret!= free_address)106 if (address != free_address) 107 107 return NULL; 108 return ret; 108 return address; 109 } 110 /*----------------------------------------------------------------------------*/ 111 static inline void return_page(void *page) 112 { 113 if (page) 114 as_area_destroy(page); 109 115 } 110 116 -
uspace/drv/bus/usb/vhc/connhost.c
r47fecbb rfd07e526 62 62 VHC_DATA(vhc, fun); 63 63 64 usb_address_t addr = device_keeper_get_free_address(&vhc->dev_keeper,65 USB_SPEED_HIGH);64 usb_address_t addr = usb_device_manager_get_free_address( 65 &vhc->dev_manager, USB_SPEED_HIGH); 66 66 if (addr < 0) { 67 67 return addr; … … 88 88 usb_log_debug("Binding handle %" PRIun " to address %d.\n", 89 89 handle, address); 90 usb_device_ keeper_bind(&vhc->dev_keeper, address, handle);90 usb_device_manager_bind(&vhc->dev_manager, address, handle); 91 91 92 92 return EOK; … … 105 105 VHC_DATA(vhc, fun); 106 106 bool found = 107 usb_device_ keeper_find_by_address(&vhc->dev_keeper, address, handle);107 usb_device_manager_find_by_address(&vhc->dev_manager, address, handle); 108 108 return found ? EOK : ENOENT; 109 109 } … … 119 119 VHC_DATA(vhc, fun); 120 120 usb_log_debug("Releasing address %d...\n", address); 121 usb_device_ keeper_release(&vhc->dev_keeper, address);121 usb_device_manager_release(&vhc->dev_manager, address); 122 122 123 123 return ENOTSUP; … … 172 172 VHC_DATA(vhc, fun); 173 173 174 endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager,175 address, endpoint, direction, NULL);176 if (ep == NULL) {177 return ENOENT;178 }179 180 174 int rc = usb_endpoint_manager_unregister_ep(&vhc->ep_manager, 181 175 address, endpoint, direction); … … 183 177 return rc; 184 178 } 185 179 #if 0 186 180 /** Schedule interrupt out transfer. 187 181 * … … 413 407 return EOK; 414 408 } 409 #endif 410 static int usb_read(ddf_fun_t *fun, usb_target_t target, uint64_t setup_buffer, 411 uint8_t *data_buffer, size_t data_buffer_size, 412 usbhc_iface_transfer_in_callback_t callback, void *arg) 413 { 414 VHC_DATA(vhc, fun); 415 416 endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager, 417 target.address, target.endpoint, USB_DIRECTION_IN, NULL); 418 if (ep == NULL) { 419 return ENOENT; 420 } 421 const usb_transfer_type_t transfer_type = ep->transfer_type; 422 423 424 vhc_transfer_t *transfer = vhc_transfer_create(target.address, 425 target.endpoint, USB_DIRECTION_IN, transfer_type, 426 fun, arg); 427 if (transfer == NULL) { 428 return ENOMEM; 429 } 430 if (transfer_type == USB_TRANSFER_CONTROL) { 431 transfer->setup_buffer = malloc(sizeof(uint64_t)); 432 assert(transfer->setup_buffer); 433 memcpy(transfer->setup_buffer, &setup_buffer, sizeof(uint64_t)); 434 transfer->setup_buffer_size = sizeof(uint64_t); 435 } 436 transfer->data_buffer = data_buffer; 437 transfer->data_buffer_size = data_buffer_size; 438 transfer->callback_in = callback; 439 440 int rc = vhc_virtdev_add_transfer(vhc, transfer); 441 if (rc != EOK) { 442 free(transfer->setup_buffer); 443 free(transfer); 444 return rc; 445 } 446 447 return EOK; 448 } 449 450 static int usb_write(ddf_fun_t *fun, usb_target_t target, uint64_t setup_buffer, 451 const uint8_t *data_buffer, size_t data_buffer_size, 452 usbhc_iface_transfer_out_callback_t callback, void *arg) 453 { 454 VHC_DATA(vhc, fun); 455 456 endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager, 457 target.address, target.endpoint, USB_DIRECTION_OUT, NULL); 458 if (ep == NULL) { 459 return ENOENT; 460 } 461 const usb_transfer_type_t transfer_type = ep->transfer_type; 462 463 464 vhc_transfer_t *transfer = vhc_transfer_create(target.address, 465 target.endpoint, USB_DIRECTION_OUT, transfer_type, 466 fun, arg); 467 if (transfer == NULL) { 468 return ENOMEM; 469 } 470 if (transfer_type == USB_TRANSFER_CONTROL) { 471 transfer->setup_buffer = malloc(sizeof(uint64_t)); 472 assert(transfer->setup_buffer); 473 memcpy(transfer->setup_buffer, &setup_buffer, sizeof(uint64_t)); 474 transfer->setup_buffer_size = sizeof(uint64_t); 475 } 476 transfer->data_buffer = (void*)data_buffer; 477 transfer->data_buffer_size = data_buffer_size; 478 transfer->callback_out = callback; 479 480 int rc = vhc_virtdev_add_transfer(vhc, transfer); 481 if (rc != EOK) { 482 free(transfer->setup_buffer); 483 free(transfer); 484 return rc; 485 } 486 487 return EOK; 488 } 415 489 416 490 static int tell_address(ddf_fun_t *fun, devman_handle_t handle, … … 442 516 443 517 usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle); 444 usb_address_t addr = usb_device_ keeper_find(&vhc->dev_keeper, handle);518 usb_address_t addr = usb_device_manager_find(&vhc->dev_manager, handle); 445 519 if (addr < 0) { 446 520 return addr; … … 460 534 .unregister_endpoint = unregister_endpoint, 461 535 462 .interrupt_out = interrupt_out, 463 .interrupt_in = interrupt_in, 464 465 .bulk_in = bulk_in, 466 .bulk_out = bulk_out, 467 468 .control_write = control_write, 469 .control_read = control_read 536 .write = usb_write, 537 .read = usb_read, 470 538 }; 471 539 -
uspace/drv/bus/usb/vhc/main.c
r47fecbb rfd07e526 73 73 } 74 74 data->magic = 0xDEADBEEF; 75 rc = usb_endpoint_manager_init(&data->ep_manager, (size_t) -1); 75 rc = usb_endpoint_manager_init(&data->ep_manager, (size_t) -1, 76 bandwidth_count_usb11); 76 77 if (rc != EOK) { 77 78 usb_log_fatal("Failed to initialize endpoint manager.\n"); … … 79 80 return rc; 80 81 } 81 usb_device_ keeper_init(&data->dev_keeper);82 usb_device_manager_init(&data->dev_manager); 82 83 83 84 ddf_fun_t *hc = ddf_fun_create(dev, fun_exposed, "hc"); -
uspace/drv/bus/usb/vhc/vhcd.h
r47fecbb rfd07e526 39 39 #include <usbvirt/device.h> 40 40 #include <usb/host/usb_endpoint_manager.h> 41 #include <usb/host/ device_keeper.h>41 #include <usb/host/usb_device_manager.h> 42 42 #include <usbhc_iface.h> 43 43 #include <async.h> … … 60 60 fibril_mutex_t guard; 61 61 usb_endpoint_manager_t ep_manager; 62 usb_device_ keeper_t dev_keeper;62 usb_device_manager_t dev_manager; 63 63 usbvirt_device_t *hub; 64 64 ddf_fun_t *hc_fun; -
uspace/lib/c/generic/as.c
r47fecbb rfd07e526 123 123 * @retval ENOENT Mapping not found. 124 124 */ 125 int as_get_physical_mapping( void *address, uintptr_t *frame)125 int as_get_physical_mapping(const void *address, uintptr_t *frame) 126 126 { 127 127 uintptr_t tmp_frame; -
uspace/lib/c/include/as.h
r47fecbb rfd07e526 60 60 extern void *set_maxheapsize(size_t); 61 61 extern void *as_get_mappable_page(size_t); 62 extern int as_get_physical_mapping( void *, uintptr_t *);62 extern int as_get_physical_mapping(const void *, uintptr_t *); 63 63 64 64 #endif -
uspace/lib/drv/generic/remote_usbhc.c
r47fecbb rfd07e526 41 41 42 42 #define USB_MAX_PAYLOAD_SIZE 1020 43 #define HACK_MAX_PACKET_SIZE 8 44 #define HACK_MAX_PACKET_SIZE_INTERRUPT_IN 4 45 46 static void remote_usbhc_interrupt_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 47 static void remote_usbhc_interrupt_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 48 static void remote_usbhc_bulk_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 49 static void remote_usbhc_bulk_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 50 static void remote_usbhc_control_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 51 static void remote_usbhc_control_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 43 52 44 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 53 45 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); … … 56 48 static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 57 49 static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 50 static void remote_usbhc_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 51 static void remote_usbhc_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 58 52 //static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 59 53 60 54 /** Remote USB host controller interface operations. */ 61 static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = { 62 remote_usbhc_request_address, 63 remote_usbhc_bind_address, 64 remote_usbhc_find_by_address, 65 remote_usbhc_release_address, 66 67 remote_usbhc_interrupt_out, 68 remote_usbhc_interrupt_in, 69 70 remote_usbhc_bulk_out, 71 remote_usbhc_bulk_in, 72 73 remote_usbhc_control_write, 74 remote_usbhc_control_read, 75 76 remote_usbhc_register_endpoint, 77 remote_usbhc_unregister_endpoint 55 static remote_iface_func_ptr_t remote_usbhc_iface_ops[] = { 56 [IPC_M_USBHC_REQUEST_ADDRESS] = remote_usbhc_request_address, 57 [IPC_M_USBHC_BIND_ADDRESS] = remote_usbhc_bind_address, 58 [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_find_by_address, 59 [IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address, 60 61 [IPC_M_USBHC_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint, 62 [IPC_M_USBHC_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint, 63 64 [IPC_M_USBHC_READ] = remote_usbhc_read, 65 [IPC_M_USBHC_WRITE] = remote_usbhc_write, 78 66 }; 79 67 … … 90 78 ipc_callid_t data_caller; 91 79 void *buffer; 92 void *setup_packet;93 80 size_t size; 94 81 } async_transaction_t; … … 98 85 if (trans == NULL) { 99 86 return; 100 }101 102 if (trans->setup_packet != NULL) {103 free(trans->setup_packet);104 87 } 105 88 if (trans->buffer != NULL) { … … 120 103 trans->data_caller = 0; 121 104 trans->buffer = NULL; 122 trans->setup_packet = NULL;123 105 trans->size = 0; 124 106 … … 135 117 return; 136 118 } 137 119 138 120 usb_speed_t speed = DEV_IPC_GET_ARG1(*call); 139 121 … … 239 221 async_transaction_destroy(trans); 240 222 } 241 242 /** Process an outgoing transfer (both OUT and SETUP).243 *244 * @param device Target device.245 * @param callid Initiating caller.246 * @param call Initiating call.247 * @param transfer_func Transfer function (might be NULL).248 */249 static void remote_usbhc_out_transfer(ddf_fun_t *fun,250 ipc_callid_t callid, ipc_call_t *call,251 usbhc_iface_transfer_out_t transfer_func)252 {253 if (!transfer_func) {254 async_answer_0(callid, ENOTSUP);255 return;256 }257 258 usb_target_t target = {259 .address = DEV_IPC_GET_ARG1(*call),260 .endpoint = DEV_IPC_GET_ARG2(*call)261 };262 263 size_t len = 0;264 void *buffer = NULL;265 266 int rc = async_data_write_accept(&buffer, false,267 1, USB_MAX_PAYLOAD_SIZE,268 0, &len);269 270 if (rc != EOK) {271 async_answer_0(callid, rc);272 return;273 }274 275 async_transaction_t *trans = async_transaction_create(callid);276 if (trans == NULL) {277 if (buffer != NULL) {278 free(buffer);279 }280 async_answer_0(callid, ENOMEM);281 return;282 }283 284 trans->buffer = buffer;285 trans->size = len;286 287 rc = transfer_func(fun, target,288 buffer, len,289 callback_out, trans);290 291 if (rc != EOK) {292 async_answer_0(callid, rc);293 async_transaction_destroy(trans);294 }295 }296 297 /** Process an incoming transfer.298 *299 * @param device Target device.300 * @param callid Initiating caller.301 * @param call Initiating call.302 * @param transfer_func Transfer function (might be NULL).303 */304 static void remote_usbhc_in_transfer(ddf_fun_t *fun,305 ipc_callid_t callid, ipc_call_t *call,306 usbhc_iface_transfer_in_t transfer_func)307 {308 if (!transfer_func) {309 async_answer_0(callid, ENOTSUP);310 return;311 }312 313 usb_target_t target = {314 .address = DEV_IPC_GET_ARG1(*call),315 .endpoint = DEV_IPC_GET_ARG2(*call)316 };317 318 size_t len;319 ipc_callid_t data_callid;320 if (!async_data_read_receive(&data_callid, &len)) {321 async_answer_0(callid, EPARTY);322 return;323 }324 325 async_transaction_t *trans = async_transaction_create(callid);326 if (trans == NULL) {327 async_answer_0(data_callid, ENOMEM);328 async_answer_0(callid, ENOMEM);329 return;330 }331 trans->data_caller = data_callid;332 trans->buffer = malloc(len);333 trans->size = len;334 335 int rc = transfer_func(fun, target,336 trans->buffer, len,337 callback_in, trans);338 339 if (rc != EOK) {340 async_answer_0(data_callid, rc);341 async_answer_0(callid, rc);342 async_transaction_destroy(trans);343 }344 }345 346 void remote_usbhc_interrupt_out(ddf_fun_t *fun, void *iface,347 ipc_callid_t callid, ipc_call_t *call)348 {349 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;350 assert(usb_iface != NULL);351 352 return remote_usbhc_out_transfer(fun, callid, call,353 usb_iface->interrupt_out);354 }355 356 void remote_usbhc_interrupt_in(ddf_fun_t *fun, void *iface,357 ipc_callid_t callid, ipc_call_t *call)358 {359 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;360 assert(usb_iface != NULL);361 362 return remote_usbhc_in_transfer(fun, callid, call,363 usb_iface->interrupt_in);364 }365 366 void remote_usbhc_bulk_out(ddf_fun_t *fun, void *iface,367 ipc_callid_t callid, ipc_call_t *call)368 {369 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;370 assert(usb_iface != NULL);371 372 return remote_usbhc_out_transfer(fun, callid, call,373 usb_iface->bulk_out);374 }375 376 void remote_usbhc_bulk_in(ddf_fun_t *fun, void *iface,377 ipc_callid_t callid, ipc_call_t *call)378 {379 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;380 assert(usb_iface != NULL);381 382 return remote_usbhc_in_transfer(fun, callid, call,383 usb_iface->bulk_in);384 }385 386 void remote_usbhc_control_write(ddf_fun_t *fun, void *iface,387 ipc_callid_t callid, ipc_call_t *call)388 {389 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;390 assert(usb_iface != NULL);391 392 if (!usb_iface->control_write) {393 async_answer_0(callid, ENOTSUP);394 return;395 }396 397 usb_target_t target = {398 .address = DEV_IPC_GET_ARG1(*call),399 .endpoint = DEV_IPC_GET_ARG2(*call)400 };401 size_t data_buffer_len = DEV_IPC_GET_ARG3(*call);402 403 int rc;404 405 void *setup_packet = NULL;406 void *data_buffer = NULL;407 size_t setup_packet_len = 0;408 409 rc = async_data_write_accept(&setup_packet, false,410 1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);411 if (rc != EOK) {412 async_answer_0(callid, rc);413 return;414 }415 416 if (data_buffer_len > 0) {417 rc = async_data_write_accept(&data_buffer, false,418 1, USB_MAX_PAYLOAD_SIZE, 0, &data_buffer_len);419 if (rc != EOK) {420 async_answer_0(callid, rc);421 free(setup_packet);422 return;423 }424 }425 426 async_transaction_t *trans = async_transaction_create(callid);427 if (trans == NULL) {428 async_answer_0(callid, ENOMEM);429 free(setup_packet);430 free(data_buffer);431 return;432 }433 trans->setup_packet = setup_packet;434 trans->buffer = data_buffer;435 trans->size = data_buffer_len;436 437 rc = usb_iface->control_write(fun, target,438 setup_packet, setup_packet_len,439 data_buffer, data_buffer_len,440 callback_out, trans);441 442 if (rc != EOK) {443 async_answer_0(callid, rc);444 async_transaction_destroy(trans);445 }446 }447 448 449 void remote_usbhc_control_read(ddf_fun_t *fun, void *iface,450 ipc_callid_t callid, ipc_call_t *call)451 {452 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;453 assert(usb_iface != NULL);454 455 if (!usb_iface->control_read) {456 async_answer_0(callid, ENOTSUP);457 return;458 }459 460 usb_target_t target = {461 .address = DEV_IPC_GET_ARG1(*call),462 .endpoint = DEV_IPC_GET_ARG2(*call)463 };464 465 int rc;466 467 void *setup_packet = NULL;468 size_t setup_packet_len = 0;469 size_t data_len = 0;470 471 rc = async_data_write_accept(&setup_packet, false,472 1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);473 if (rc != EOK) {474 async_answer_0(callid, rc);475 return;476 }477 478 ipc_callid_t data_callid;479 if (!async_data_read_receive(&data_callid, &data_len)) {480 async_answer_0(callid, EPARTY);481 free(setup_packet);482 return;483 }484 485 async_transaction_t *trans = async_transaction_create(callid);486 if (trans == NULL) {487 async_answer_0(data_callid, ENOMEM);488 async_answer_0(callid, ENOMEM);489 free(setup_packet);490 return;491 }492 trans->data_caller = data_callid;493 trans->setup_packet = setup_packet;494 trans->size = data_len;495 trans->buffer = malloc(data_len);496 if (trans->buffer == NULL) {497 async_answer_0(data_callid, ENOMEM);498 async_answer_0(callid, ENOMEM);499 async_transaction_destroy(trans);500 return;501 }502 503 rc = usb_iface->control_read(fun, target,504 setup_packet, setup_packet_len,505 trans->buffer, trans->size,506 callback_in, trans);507 508 if (rc != EOK) {509 async_answer_0(data_callid, rc);510 async_answer_0(callid, rc);511 async_transaction_destroy(trans);512 }513 }514 515 223 516 224 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface, … … 535 243 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 8) 536 244 537 _INIT_FROM_HIGH_DATA2(usb_address_t, address, 1); 538 _INIT_FROM_LOW_DATA2(usb_endpoint_t, endpoint, 1); 245 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 539 246 540 247 _INIT_FROM_HIGH_DATA3(usb_speed_t, speed, 2); … … 551 258 #undef _INIT_FROM_LOW_DATA3 552 259 553 int rc = usb_iface->register_endpoint(fun, address, speed, endpoint,554 t ransfer_type, direction, max_packet_size, interval);260 int rc = usb_iface->register_endpoint(fun, target.address, speed, 261 target.endpoint, transfer_type, direction, max_packet_size, interval); 555 262 556 263 async_answer_0(callid, rc); 557 264 } 558 559 265 560 266 void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface, … … 578 284 } 579 285 286 void remote_usbhc_read( 287 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 288 { 289 assert(fun); 290 assert(iface); 291 assert(call); 292 293 const usbhc_iface_t *hc_iface = iface; 294 295 if (!hc_iface->read) { 296 async_answer_0(callid, ENOTSUP); 297 return; 298 } 299 300 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 301 const uint64_t setup = 302 ((uint64_t)DEV_IPC_GET_ARG2(*call)) | 303 (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32); 304 305 async_transaction_t *trans = async_transaction_create(callid); 306 if (trans == NULL) { 307 async_answer_0(callid, ENOMEM); 308 return; 309 } 310 311 if (!async_data_read_receive(&trans->data_caller, &trans->size)) { 312 async_answer_0(callid, EPARTY); 313 return; 314 } 315 316 trans->buffer = malloc(trans->size); 317 if (trans->buffer == NULL) { 318 async_answer_0(trans->data_caller, ENOMEM); 319 async_answer_0(callid, ENOMEM); 320 async_transaction_destroy(trans); 321 } 322 323 const int rc = hc_iface->read( 324 fun, target, setup, trans->buffer, trans->size, callback_in, trans); 325 326 if (rc != EOK) { 327 async_answer_0(trans->data_caller, rc); 328 async_answer_0(callid, rc); 329 async_transaction_destroy(trans); 330 } 331 } 332 333 void remote_usbhc_write( 334 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 335 { 336 assert(fun); 337 assert(iface); 338 assert(call); 339 340 const usbhc_iface_t *hc_iface = iface; 341 342 if (!hc_iface->write) { 343 async_answer_0(callid, ENOTSUP); 344 return; 345 } 346 347 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 348 const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call); 349 const uint64_t setup = 350 ((uint64_t)DEV_IPC_GET_ARG3(*call)) | 351 (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32); 352 353 async_transaction_t *trans = async_transaction_create(callid); 354 if (trans == NULL) { 355 async_answer_0(callid, ENOMEM); 356 return; 357 } 358 359 if (data_buffer_len > 0) { 360 int rc = async_data_write_accept(&trans->buffer, false, 361 1, USB_MAX_PAYLOAD_SIZE, 362 0, &trans->size); 363 364 if (rc != EOK) { 365 async_answer_0(callid, rc); 366 async_transaction_destroy(trans); 367 return; 368 } 369 } 370 371 int rc = hc_iface->write( 372 fun, target, setup, trans->buffer, trans->size, callback_out, trans); 373 374 if (rc != EOK) { 375 async_answer_0(callid, rc); 376 async_transaction_destroy(trans); 377 } 378 } 379 580 380 581 381 /** -
uspace/lib/drv/include/usbhc_iface.h
r47fecbb rfd07e526 123 123 IPC_M_USBHC_RELEASE_ADDRESS, 124 124 125 126 /** Send interrupt data to device.127 * See explanation at usb_iface_funcs_t (OUT transaction).128 */129 IPC_M_USBHC_INTERRUPT_OUT,130 131 /** Get interrupt data from device.132 * See explanation at usb_iface_funcs_t (IN transaction).133 */134 IPC_M_USBHC_INTERRUPT_IN,135 136 /** Send bulk data to device.137 * See explanation at usb_iface_funcs_t (OUT transaction).138 */139 IPC_M_USBHC_BULK_OUT,140 141 /** Get bulk data from device.142 * See explanation at usb_iface_funcs_t (IN transaction).143 */144 IPC_M_USBHC_BULK_IN,145 146 /** Issue control WRITE transfer.147 * See explanation at usb_iface_funcs_t (OUT transaction) for148 * call parameters.149 * This call is immediately followed by two IPC data writes150 * from the caller (setup packet and actual data).151 */152 IPC_M_USBHC_CONTROL_WRITE,153 154 /** Issue control READ transfer.155 * See explanation at usb_iface_funcs_t (IN transaction) for156 * call parameters.157 * This call is immediately followed by IPC data write from the caller158 * (setup packet) and IPC data read (buffer that was read).159 */160 IPC_M_USBHC_CONTROL_READ,161 162 125 /** Register endpoint attributes at host controller. 163 126 * This is used to reserve portion of USB bandwidth. … … 185 148 * - ENOENT - unknown endpoint 186 149 */ 187 IPC_M_USBHC_UNREGISTER_ENDPOINT 150 IPC_M_USBHC_UNREGISTER_ENDPOINT, 151 152 /** Get data from device. 153 * See explanation at usb_iface_funcs_t (IN transaction). 154 */ 155 IPC_M_USBHC_READ, 156 157 /** Send data to device. 158 * See explanation at usb_iface_funcs_t (OUT transaction). 159 */ 160 IPC_M_USBHC_WRITE, 188 161 } usbhc_iface_funcs_t; 189 162 190 163 /** Callback for outgoing transfer. */ 191 typedef void (*usbhc_iface_transfer_out_callback_t)(ddf_fun_t *, 192 int, void *); 164 typedef void (*usbhc_iface_transfer_out_callback_t)(ddf_fun_t *, int, void *); 193 165 194 166 /** Callback for incoming transfer. */ 195 167 typedef void (*usbhc_iface_transfer_in_callback_t)(ddf_fun_t *, 196 168 int, size_t, void *); 197 198 199 /** Out transfer processing function prototype. */200 typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t,201 void *, size_t,202 usbhc_iface_transfer_out_callback_t, void *);203 204 /** Setup transfer processing function prototype. @deprecated */205 typedef usbhc_iface_transfer_out_t usbhc_iface_transfer_setup_t;206 207 /** In transfer processing function prototype. */208 typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t,209 void *, size_t,210 usbhc_iface_transfer_in_callback_t, void *);211 169 212 170 /** USB host controller communication interface. */ … … 223 181 usb_direction_t); 224 182 225 usbhc_iface_transfer_out_t interrupt_out;226 usbhc_iface_transfer_in_t interrupt_in;183 int (*read)(ddf_fun_t *, usb_target_t, uint64_t, uint8_t *, size_t, 184 usbhc_iface_transfer_in_callback_t, void *); 227 185 228 usbhc_iface_transfer_out_t bulk_out; 229 usbhc_iface_transfer_in_t bulk_in; 230 231 int (*control_write)(ddf_fun_t *, usb_target_t, 232 void *, size_t, void *, size_t, 233 usbhc_iface_transfer_out_callback_t, void *); 234 235 int (*control_read)(ddf_fun_t *, usb_target_t, 236 void *, size_t, void *, size_t, 237 usbhc_iface_transfer_in_callback_t, void *); 186 int (*write)(ddf_fun_t *, usb_target_t, uint64_t, const uint8_t *, 187 size_t, usbhc_iface_transfer_out_callback_t, void *); 238 188 } usbhc_iface_t; 239 189 -
uspace/lib/usb/include/usb/hc.h
r47fecbb rfd07e526 62 62 devman_handle_t *); 63 63 64 int usb_hc_get_address_by_handle(devman_handle_t);64 usb_address_t usb_hc_get_address_by_handle(devman_handle_t); 65 65 66 66 int usb_hc_find(devman_handle_t, devman_handle_t *); -
uspace/lib/usb/include/usb/usb.h
r47fecbb rfd07e526 36 36 #define LIBUSB_USB_H_ 37 37 38 #include <bool.h> 38 39 #include <sys/types.h> 39 40 #include <byteorder.h> … … 105 106 * Negative values could be used to indicate error. 106 107 */ 107 typedef int usb_address_t;108 typedef int16_t usb_address_t; 108 109 109 110 /** Default USB address. */ … … 115 116 * Negative values could be used to indicate error. 116 117 */ 117 typedef int usb_endpoint_t;118 typedef int16_t usb_endpoint_t; 118 119 119 120 /** Maximum endpoint number in USB 1.1. … … 125 126 * Pair address + endpoint is identification of transaction recipient. 126 127 */ 127 typedef struct { 128 usb_address_t address; 129 usb_endpoint_t endpoint; 128 typedef union { 129 struct { 130 usb_address_t address; 131 usb_endpoint_t endpoint; 132 } __attribute__((packed)); 133 uint32_t packed; 130 134 } usb_target_t; 135 136 /** Check USB target for allowed values (address and endpoint). 137 * 138 * @param target. 139 * @return True, if values are wihtin limits, false otherwise. 140 */ 141 static inline bool usb_target_is_valid(usb_target_t target) 142 { 143 return !(target.endpoint > 15 || target.endpoint < 0 144 || target.address >= USB11_ADDRESS_MAX || target.address < 0); 145 } 131 146 132 147 /** Compare USB targets (addresses and endpoints). -
uspace/lib/usbdev/src/pipesinit.c
r47fecbb rfd07e526 486 486 return EBADF; 487 487 488 const usb_target_t target = 489 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }}; 488 490 #define _PACK2(high, low) (((high) << 16) + (low)) 489 491 #define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low)) … … 491 493 async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess); 492 494 int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 493 IPC_M_USBHC_REGISTER_ENDPOINT, 494 _PACK2(pipe->wire->address, pipe->endpoint_no), 495 IPC_M_USBHC_REGISTER_ENDPOINT, target.packed, 495 496 _PACK3(speed, pipe->transfer_type, pipe->direction), 496 497 _PACK2(pipe->max_packet_size, interval)); -
uspace/lib/usbdev/src/pipesio.c
r47fecbb rfd07e526 65 65 void *buffer, size_t size, size_t *size_transfered) 66 66 { 67 /* 68 * Get corresponding IPC method. 69 * In future, replace with static array of mappings 70 * transfer type -> method. 71 */ 72 usbhc_iface_funcs_t ipc_method; 73 switch (pipe->transfer_type) { 74 case USB_TRANSFER_INTERRUPT: 75 ipc_method = IPC_M_USBHC_INTERRUPT_IN; 76 break; 77 case USB_TRANSFER_BULK: 78 ipc_method = IPC_M_USBHC_BULK_IN; 79 break; 80 default: 81 return ENOTSUP; 82 } 67 /* Only interrupt and bulk transfers are supported */ 68 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT && 69 pipe->transfer_type != USB_TRANSFER_BULK) 70 return ENOTSUP; 71 72 const usb_target_t target = 73 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }}; 83 74 84 75 /* Ensure serialization over the phone. */ … … 89 80 * Make call identifying target USB device and type of transfer. 90 81 */ 91 aid_t opening_request = async_send_ 3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),92 ipc_method, pipe->wire->address, pipe->endpoint_no, NULL);82 aid_t opening_request = async_send_2(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 83 IPC_M_USBHC_READ, target.packed, NULL); 93 84 94 85 if (opening_request == 0) { … … 213 204 void *buffer, size_t size) 214 205 { 215 /* 216 * Get corresponding IPC method. 217 * In future, replace with static array of mappings 218 * transfer type -> method. 219 */ 220 usbhc_iface_funcs_t ipc_method; 221 switch (pipe->transfer_type) { 222 case USB_TRANSFER_INTERRUPT: 223 ipc_method = IPC_M_USBHC_INTERRUPT_OUT; 224 break; 225 case USB_TRANSFER_BULK: 226 ipc_method = IPC_M_USBHC_BULK_OUT; 227 break; 228 default: 229 return ENOTSUP; 230 } 206 /* Only interrupt and bulk transfers are supported */ 207 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT && 208 pipe->transfer_type != USB_TRANSFER_BULK) 209 return ENOTSUP; 210 211 const usb_target_t target = 212 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }}; 231 213 232 214 /* Ensure serialization over the phone. */ … … 238 220 */ 239 221 aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 240 ipc_method, pipe->wire->address, pipe->endpoint_no, NULL);222 IPC_M_USBHC_WRITE, target.packed, size, NULL); 241 223 242 224 if (opening_request == 0) { … … 352 334 pipe_start_transaction(pipe); 353 335 336 const usb_target_t target = 337 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }}; 338 339 assert(setup_buffer_size == 8); 340 uint64_t setup_packet; 341 memcpy(&setup_packet, setup_buffer, 8); 354 342 /* 355 343 * Make call identifying target USB device and control transfer type. 356 344 */ 357 345 async_exch_t *exch = async_exchange_begin(pipe->hc_sess); 358 aid_t opening_request = async_send_ 3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),359 IPC_M_USBHC_ CONTROL_READ, pipe->wire->address, pipe->endpoint_no,360 NULL);361 346 aid_t opening_request = async_send_4(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 347 IPC_M_USBHC_READ, target.packed, 348 (setup_packet & UINT32_MAX), (setup_packet >> 32), NULL); 349 362 350 if (opening_request == 0) { 363 351 async_exchange_end(exch); 364 352 return ENOMEM; 365 353 } 366 367 /* 368 * Send the setup packet. 369 */ 370 int rc = async_data_write_start(exch, setup_buffer, setup_buffer_size); 371 if (rc != EOK) { 372 async_exchange_end(exch); 373 pipe_end_transaction(pipe); 374 async_wait_for(opening_request, NULL); 375 return rc; 376 } 377 354 378 355 /* 379 356 * Retrieve the data. … … 498 475 pipe_start_transaction(pipe); 499 476 477 const usb_target_t target = 478 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }}; 479 assert(setup_buffer_size == 8); 480 uint64_t setup_packet; 481 memcpy(&setup_packet, setup_buffer, 8); 482 500 483 /* 501 484 * Make call identifying target USB device and control transfer type. 502 485 */ 503 486 async_exch_t *exch = async_exchange_begin(pipe->hc_sess); 504 aid_t opening_request = async_send_ 4(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),505 IPC_M_USBHC_ CONTROL_WRITE, pipe->wire->address, pipe->endpoint_no,506 data_buffer_size, NULL);487 aid_t opening_request = async_send_5(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 488 IPC_M_USBHC_WRITE, target.packed, data_buffer_size, 489 (setup_packet & UINT32_MAX), (setup_packet >> 32), NULL); 507 490 508 491 if (opening_request == 0) { … … 511 494 return ENOMEM; 512 495 } 513 514 /* 515 * Send the setup packet. 516 */ 517 int rc = async_data_write_start(exch, setup_buffer, setup_buffer_size); 518 if (rc != EOK) { 519 async_exchange_end(exch); 520 pipe_end_transaction(pipe); 521 async_wait_for(opening_request, NULL); 522 return rc; 523 } 524 496 525 497 /* 526 498 * Send the data (if any). 527 499 */ 528 500 if (data_buffer_size > 0) { 529 rc = async_data_write_start(exch, data_buffer, data_buffer_size);501 int rc = async_data_write_start(exch, data_buffer, data_buffer_size); 530 502 531 503 /* All data sent, pipe can be released. */ -
uspace/lib/usbhost/Makefile
r47fecbb rfd07e526 32 32 -I$(LIBUSB_PREFIX)/include \ 33 33 -I$(LIBDRV_PREFIX)/include \ 34 -Iinclude 34 -Iinclude 35 35 36 36 SOURCES = \ 37 src/batch.c \38 src/device_keeper.c \39 37 src/endpoint.c \ 40 src/usb_endpoint_manager.c 38 src/iface.c \ 39 src/usb_device_manager.c \ 40 src/usb_endpoint_manager.c \ 41 src/usb_transfer_batch.c 41 42 42 43 include $(USPACE_PREFIX)/Makefile.common -
uspace/lib/usbhost/include/usb/host/endpoint.h
r47fecbb rfd07e526 54 54 fibril_condvar_t avail; 55 55 volatile bool active; 56 void (*destroy_hook)(struct endpoint *); 56 57 struct { 57 58 void *data; … … 68 69 69 70 void endpoint_set_hc_data(endpoint_t *instance, 70 void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int)); 71 void *data, void (*destroy_hook)(endpoint_t *), 72 int (*toggle_get)(void *), void (*toggle_set)(void *, int)); 71 73 72 74 void endpoint_clear_hc_data(endpoint_t *instance); -
uspace/lib/usbhost/include/usb/host/usb_device_manager.h
r47fecbb rfd07e526 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 29 28 /** @addtogroup libusbhost 30 29 * @{ 31 30 */ 32 31 /** @file 33 * Device keeper structure and functions.32 * Device manager structure and functions. 34 33 * 35 34 * Typical USB host controller needs to keep track of various settings for … … 38 37 * This structure shall simplify the management. 39 38 */ 40 #ifndef LIBUSBHOST_HOST_ DEVICE_KEEPER_H41 #define LIBUSBHOST_HOST_ DEVICE_KEEPER_H39 #ifndef LIBUSBHOST_HOST_USB_DEVICE_MANAGER_H 40 #define LIBUSBHOST_HOST_USB_DEVICE_MANAGER_H 42 41 43 42 #include <adt/list.h> … … 57 56 }; 58 57 59 /** Host controller device keeper.58 /** Host controller device manager. 60 59 * You shall not access members directly but only using functions below. 61 60 */ … … 64 63 fibril_mutex_t guard; 65 64 usb_address_t last_address; 66 } usb_device_ keeper_t;65 } usb_device_manager_t; 67 66 68 void usb_device_ keeper_init(usb_device_keeper_t *instance);67 void usb_device_manager_init(usb_device_manager_t *instance); 69 68 70 usb_address_t device_keeper_get_free_address(usb_device_keeper_t *instance,71 usb_ speed_t speed);69 usb_address_t usb_device_manager_get_free_address( 70 usb_device_manager_t *instance, usb_speed_t speed); 72 71 73 void usb_device_ keeper_bind(usb_device_keeper_t *instance,72 void usb_device_manager_bind(usb_device_manager_t *instance, 74 73 usb_address_t address, devman_handle_t handle); 75 74 76 void usb_device_ keeper_release(usb_device_keeper_t *instance,75 void usb_device_manager_release(usb_device_manager_t *instance, 77 76 usb_address_t address); 78 77 79 usb_address_t usb_device_ keeper_find(usb_device_keeper_t *instance,78 usb_address_t usb_device_manager_find(usb_device_manager_t *instance, 80 79 devman_handle_t handle); 81 80 82 bool usb_device_ keeper_find_by_address(usb_device_keeper_t *instance,81 bool usb_device_manager_find_by_address(usb_device_manager_t *instance, 83 82 usb_address_t address, devman_handle_t *handle); 84 83 85 usb_speed_t usb_device_ keeper_get_speed(usb_device_keeper_t *instance,84 usb_speed_t usb_device_manager_get_speed(usb_device_manager_t *instance, 86 85 usb_address_t address); 87 86 #endif -
uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h
r47fecbb rfd07e526 38 38 */ 39 39 #ifndef LIBUSBHOST_HOST_USB_ENDPOINT_MANAGER_H 40 #define LIBUSBHOST_HOST_ YSB_ENDPOINT_MANAGER_H40 #define LIBUSBHOST_HOST_USB_ENDPOINT_MANAGER_H 41 41 42 42 #include <stdlib.h> … … 52 52 hash_table_t ep_table; 53 53 fibril_mutex_t guard; 54 fibril_condvar_t change;55 54 size_t free_bw; 55 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t); 56 56 } usb_endpoint_manager_t; 57 57 … … 60 60 61 61 int usb_endpoint_manager_init(usb_endpoint_manager_t *instance, 62 size_t available_bandwidth); 62 size_t available_bandwidth, 63 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t)); 63 64 64 65 void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance); … … 77 78 usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data); 78 79 80 /** Wrapper combining allocation and insertion */ 79 81 static inline int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance, 80 82 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, -
uspace/lib/usbhost/src/endpoint.c
r47fecbb rfd07e526 53 53 instance->toggle = 0; 54 54 instance->active = false; 55 instance->destroy_hook = NULL; 56 instance->hc_data.data = NULL; 57 instance->hc_data.toggle_get = NULL; 58 instance->hc_data.toggle_set = NULL; 55 59 fibril_mutex_initialize(&instance->guard); 56 60 fibril_condvar_initialize(&instance->avail); … … 64 68 assert(instance); 65 69 assert(!instance->active); 70 if (instance->hc_data.data) { 71 assert(instance->destroy_hook); 72 instance->destroy_hook(instance); 73 } 66 74 free(instance); 67 75 } 68 76 /*----------------------------------------------------------------------------*/ 69 77 void endpoint_set_hc_data(endpoint_t *instance, 70 void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int)) 78 void *data, void (*destroy_hook)(endpoint_t *), 79 int (*toggle_get)(void *), void (*toggle_set)(void *, int)) 71 80 { 72 81 assert(instance); 82 instance->destroy_hook = destroy_hook; 73 83 instance->hc_data.data = data; 74 84 instance->hc_data.toggle_get = toggle_get; … … 79 89 { 80 90 assert(instance); 91 instance->destroy_hook = NULL; 81 92 instance->hc_data.data = NULL; 82 93 instance->hc_data.toggle_get = NULL; -
uspace/lib/usbhost/src/usb_device_manager.c
r47fecbb rfd07e526 31 31 */ 32 32 /** @file 33 * Device keeper structure and functions (implementation).33 * Device manager structure and functions (implementation). 34 34 */ 35 35 #include <assert.h> 36 36 #include <errno.h> 37 37 #include <usb/debug.h> 38 #include <usb/host/ device_keeper.h>39 40 /*----------------------------------------------------------------------------*/ 41 /** Initialize device keeper structure.38 #include <usb/host/usb_device_manager.h> 39 40 /*----------------------------------------------------------------------------*/ 41 /** Initialize device manager structure. 42 42 * 43 43 * @param[in] instance Memory place to initialize. … … 45 45 * Set all values to false/0. 46 46 */ 47 void usb_device_ keeper_init(usb_device_keeper_t *instance)47 void usb_device_manager_init(usb_device_manager_t *instance) 48 48 { 49 49 assert(instance); … … 63 63 /** Get a free USB address 64 64 * 65 * @param[in] instance Device keeper structure to use.65 * @param[in] instance Device manager structure to use. 66 66 * @param[in] speed Speed of the device requiring address. 67 67 * @return Free address, or error code. 68 68 */ 69 usb_address_t device_keeper_get_free_address(70 usb_device_ keeper_t *instance, usb_speed_t speed)69 usb_address_t usb_device_manager_get_free_address( 70 usb_device_manager_t *instance, usb_speed_t speed) 71 71 { 72 72 assert(instance); … … 97 97 /** Bind USB address to devman handle. 98 98 * 99 * @param[in] instance Device keeper structure to use.99 * @param[in] instance Device manager structure to use. 100 100 * @param[in] address Device address 101 101 * @param[in] handle Devman handle of the device. 102 102 */ 103 void usb_device_ keeper_bind(usb_device_keeper_t *instance,103 void usb_device_manager_bind(usb_device_manager_t *instance, 104 104 usb_address_t address, devman_handle_t handle) 105 105 { … … 117 117 /** Release used USB address. 118 118 * 119 * @param[in] instance Device keeper structure to use.119 * @param[in] instance Device manager structure to use. 120 120 * @param[in] address Device address 121 121 */ 122 void usb_device_ keeper_release(123 usb_device_ keeper_t *instance, usb_address_t address)122 void usb_device_manager_release( 123 usb_device_manager_t *instance, usb_address_t address) 124 124 { 125 125 assert(instance); … … 136 136 /** Find USB address associated with the device 137 137 * 138 * @param[in] instance Device keeper structure to use.138 * @param[in] instance Device manager structure to use. 139 139 * @param[in] handle Devman handle of the device seeking its address. 140 140 * @return USB Address, or error code. 141 141 */ 142 usb_address_t usb_device_ keeper_find(143 usb_device_ keeper_t *instance, devman_handle_t handle)142 usb_address_t usb_device_manager_find( 143 usb_device_manager_t *instance, devman_handle_t handle) 144 144 { 145 145 assert(instance); … … 161 161 * Intentionally refuse to find handle of default address. 162 162 * 163 * @param[in] instance Device keeper structure to use.163 * @param[in] instance Device manager structure to use. 164 164 * @param[in] address Address the caller wants to find. 165 165 * @param[out] handle Where to store found handle. 166 166 * @return Whether such address is currently occupied. 167 167 */ 168 bool usb_device_ keeper_find_by_address(usb_device_keeper_t *instance,168 bool usb_device_manager_find_by_address(usb_device_manager_t *instance, 169 169 usb_address_t address, devman_handle_t *handle) 170 170 { … … 191 191 /** Get speed associated with the address 192 192 * 193 * @param[in] instance Device keeper structure to use.193 * @param[in] instance Device manager structure to use. 194 194 * @param[in] address Address of the device. 195 195 * @return USB speed. 196 196 */ 197 usb_speed_t usb_device_ keeper_get_speed(198 usb_device_ keeper_t *instance, usb_address_t address)197 usb_speed_t usb_device_manager_get_speed( 198 usb_device_manager_t *instance, usb_address_t address) 199 199 { 200 200 assert(instance); -
uspace/lib/usbhost/src/usb_endpoint_manager.c
r47fecbb rfd07e526 45 45 static hash_index_t node_hash(unsigned long key[]) 46 46 { 47 hash_index_t hash = 0; 48 unsigned i = 0; 49 for (;i < MAX_KEYS; ++i) { 50 hash ^= key[i]; 51 } 52 hash %= BUCKET_COUNT; 53 return hash; 47 /* USB endpoints use 4 bits, thus ((key[0] << 4) | key[1]) 48 * produces unique value for every address.endpoint pair */ 49 return ((key[0] << 4) | key[1]) % BUCKET_COUNT; 54 50 } 55 51 /*----------------------------------------------------------------------------*/ … … 63 59 switch (keys) { 64 60 case 3: 65 match = match && (key[2] == node->ep->direction); 61 match = match && 62 ((key[2] == node->ep->direction) 63 || (node->ep->direction == USB_DIRECTION_BOTH)); 66 64 case 2: 67 65 match = match && (key[1] == (unsigned long)node->ep->endpoint); … … 140 138 /*----------------------------------------------------------------------------*/ 141 139 int usb_endpoint_manager_init(usb_endpoint_manager_t *instance, 142 size_t available_bandwidth) 140 size_t available_bandwidth, 141 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t)) 143 142 { 144 143 assert(instance); 145 144 fibril_mutex_initialize(&instance->guard); 146 fibril_condvar_initialize(&instance->change);147 145 instance->free_bw = available_bandwidth; 148 bool ht = 146 instance->bw_count = bw_count; 147 const bool ht = 149 148 hash_table_create(&instance->ep_table, BUCKET_COUNT, MAX_KEYS, &op); 150 149 return ht ? EOK : ENOMEM; … … 159 158 endpoint_t *ep, size_t data_size) 160 159 { 160 assert(instance); 161 assert(instance->bw_count); 161 162 assert(ep); 162 size_t bw = bandwidth_count_usb11(ep->speed, ep->transfer_type,163 const size_t bw = instance->bw_count(ep->speed, ep->transfer_type, 163 164 data_size, ep->max_packet_size); 164 assert(instance); 165 166 fibril_mutex_lock(&instance->guard); 167 168 if (bw > instance->free_bw) { 169 fibril_mutex_unlock(&instance->guard); 170 return ENOSPC; 171 } 165 172 166 173 unsigned long key[MAX_KEYS] = 167 174 {ep->address, ep->endpoint, ep->direction}; 168 fibril_mutex_lock(&instance->guard); 169 170 link_t *item = 175 176 const link_t *item = 171 177 hash_table_find(&instance->ep_table, key); 172 178 if (item != NULL) { 173 179 fibril_mutex_unlock(&instance->guard); 174 180 return EEXISTS; 175 }176 177 if (bw > instance->free_bw) {178 fibril_mutex_unlock(&instance->guard);179 return ENOSPC;180 181 } 181 182 … … 193 194 instance->free_bw -= bw; 194 195 fibril_mutex_unlock(&instance->guard); 195 fibril_condvar_broadcast(&instance->change);196 196 return EOK; 197 197 } … … 211 211 212 212 node_t *node = hash_table_get_instance(item, node_t, link); 213 if (node->ep->active) 213 if (node->ep->active) { 214 fibril_mutex_unlock(&instance->guard); 214 215 return EBUSY; 216 } 215 217 216 218 instance->free_bw += node->bw; … … 218 220 219 221 fibril_mutex_unlock(&instance->guard); 220 fibril_condvar_broadcast(&instance->change);221 222 return EOK; 222 223 } … … 230 231 231 232 fibril_mutex_lock(&instance->guard); 232 link_t *item = hash_table_find(&instance->ep_table, key);233 const link_t *item = hash_table_find(&instance->ep_table, key); 233 234 if (item == NULL) { 234 235 fibril_mutex_unlock(&instance->guard); 235 236 return NULL; 236 237 } 237 node_t *node = hash_table_get_instance(item, node_t, link);238 const node_t *node = hash_table_get_instance(item, node_t, link); 238 239 if (bw) 239 240 *bw = node->bw; … … 255 256 { 256 257 assert(instance); 257 if (target.endpoint > 15 || target.endpoint < 0 258 || target.address >= USB11_ADDRESS_MAX || target.address < 0) { 258 if (!usb_target_is_valid(target)) { 259 259 usb_log_error("Invalid data when checking for toggle reset.\n"); 260 260 return; 261 261 } 262 262 263 assert(data); 263 264 switch (data[1]) 264 265 { 265 case 0x01: /* clear feature*/266 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */266 case 0x01: /* Clear Feature -- resets only cleared ep */ 267 /* Recipient is endpoint, value is zero (ENDPOINT_STALL) */ 267 268 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) { 268 269 /* endpoint number is < 16, thus first byte is enough */ … … 276 277 break; 277 278 278 case 0x9: /* set configuration */279 case 0x11: /* set interface */280 /* target must be device */279 case 0x9: /* Set Configuration */ 280 case 0x11: /* Set Interface */ 281 /* Recipient must be device */ 281 282 if ((data[0] & 0xf) == 0) { 282 283 usb_target_t reset_target = -
uspace/lib/usbhost/src/usb_transfer_batch.c
r47fecbb rfd07e526 37 37 #include <usb/usb.h> 38 38 #include <usb/debug.h> 39 #include <usb/host/batch.h> 39 #include <usb/host/usb_transfer_batch.h> 40 #include <usb/host/hcd.h> 40 41 41 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance); 42 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance); 43 44 void usb_transfer_batch_init( 45 usb_transfer_batch_t *instance, 42 usb_transfer_batch_t * usb_transfer_batch_get( 46 43 endpoint_t *ep, 47 44 char *buffer, 48 char *data_buffer,49 45 size_t buffer_size, 50 char *setup_buffer, 51 size_t setup_size, 46 uint64_t setup_buffer, 52 47 usbhc_iface_transfer_in_callback_t func_in, 53 48 usbhc_iface_transfer_out_callback_t func_out, … … 55 50 ddf_fun_t *fun, 56 51 void *private_data, 57 void (*private_data_dtor)(void * p_data)52 void (*private_data_dtor)(void *) 58 53 ) 59 54 { 60 assert(instance); 61 link_initialize(&instance->link); 62 instance->ep = ep; 63 instance->callback_in = func_in; 64 instance->callback_out = func_out; 65 instance->arg = arg; 66 instance->buffer = buffer; 67 instance->data_buffer = data_buffer; 68 instance->buffer_size = buffer_size; 69 instance->setup_buffer = setup_buffer; 70 instance->setup_size = setup_size; 71 instance->fun = fun; 72 instance->private_data = private_data; 73 instance->private_data_dtor = private_data_dtor; 74 instance->transfered_size = 0; 75 instance->next_step = NULL; 76 instance->error = EOK; 77 endpoint_use(instance->ep); 55 usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t)); 56 if (instance) { 57 instance->ep = ep; 58 instance->callback_in = func_in; 59 instance->callback_out = func_out; 60 instance->arg = arg; 61 instance->buffer = buffer; 62 instance->buffer_size = buffer_size; 63 instance->setup_size = 0; 64 instance->fun = fun; 65 instance->private_data = private_data; 66 instance->private_data_dtor = private_data_dtor; 67 instance->transfered_size = 0; 68 instance->error = EOK; 69 if (ep && ep->transfer_type == USB_TRANSFER_CONTROL) { 70 memcpy(instance->setup_buffer, &setup_buffer, 71 USB_SETUP_PACKET_SIZE); 72 instance->setup_size = USB_SETUP_PACKET_SIZE; 73 } 74 if (instance->ep) 75 endpoint_use(instance->ep); 76 } 77 return instance; 78 78 } 79 79 /*----------------------------------------------------------------------------*/ 80 /** Helper function, calls callback and correctly destroys batch structure.80 /** Mark batch as finished and run callback. 81 81 * 82 82 * @param[in] instance Batch structure to use. 83 * @param[in] data Data to copy to the output buffer. 84 * @param[in] size Size of @p data. 83 85 */ 84 void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance) 85 { 86 assert(instance); 87 usb_transfer_batch_call_in(instance); 88 usb_transfer_batch_dispose(instance); 89 } 90 /*----------------------------------------------------------------------------*/ 91 /** Helper function calls callback and correctly destroys batch structure. 92 * 93 * @param[in] instance Batch structure to use. 94 */ 95 void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance) 96 { 97 assert(instance); 98 usb_transfer_batch_call_out(instance); 99 usb_transfer_batch_dispose(instance); 100 } 101 /*----------------------------------------------------------------------------*/ 102 /** Mark batch as finished and continue with next step. 103 * 104 * @param[in] instance Batch structure to use. 105 * 106 */ 107 void usb_transfer_batch_finish(usb_transfer_batch_t *instance) 86 void usb_transfer_batch_finish( 87 usb_transfer_batch_t *instance, const void *data, size_t size) 108 88 { 109 89 assert(instance); 110 90 assert(instance->ep); 111 assert(instance->next_step); 112 endpoint_release(instance->ep); 113 instance->next_step(instance); 91 /* we care about the data and there are some to copy */ 92 if (instance->ep->direction != USB_DIRECTION_OUT 93 && data) { 94 const size_t min_size = 95 size < instance->buffer_size ? size : instance->buffer_size; 96 memcpy(instance->buffer, data, min_size); 97 } 98 if (instance->callback_out) 99 usb_transfer_batch_call_out(instance); 100 if (instance->callback_in) 101 usb_transfer_batch_call_in(instance); 102 114 103 } 115 104 /*----------------------------------------------------------------------------*/ … … 124 113 assert(instance); 125 114 assert(instance->callback_in); 126 assert(instance->ep);127 128 /* We are data in, we need data */129 memcpy(instance->buffer, instance->data_buffer, instance->buffer_size);130 115 131 116 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed (%zuB): %s.\n", … … 150 135 str_error(instance->error)); 151 136 137 if (instance->ep->transfer_type == USB_TRANSFER_CONTROL 138 && instance->error == EOK) { 139 const usb_target_t target = 140 {{ instance->ep->address, instance->ep->endpoint }}; 141 reset_ep_if_need( 142 fun_to_hcd(instance->fun), target, instance->setup_buffer); 143 } 144 152 145 instance->callback_out(instance->fun, 153 146 instance->error, instance->arg); … … 160 153 void usb_transfer_batch_dispose(usb_transfer_batch_t *instance) 161 154 { 162 assert(instance); 155 if (!instance) 156 return; 163 157 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " disposing.\n", 164 158 instance, USB_TRANSFER_BATCH_ARGS(*instance)); 159 if (instance->ep) { 160 endpoint_release(instance->ep); 161 } 165 162 if (instance->private_data) { 166 163 assert(instance->private_data_dtor);
Note:
See TracChangeset
for help on using the changeset viewer.