Changeset f1d6866 in mainline for uspace/drv
- Timestamp:
- 2011-09-18T21:22:59Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- dcc44ca1
- Parents:
- 85ff862 (diff), 45a9cf4 (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/drv
- Files:
-
- 3 added
- 7 deleted
- 32 edited
- 3 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/isa/isa.c
r85ff862 rf1d6866 405 405 static void fun_hw_res_alloc(isa_fun_t *fun) 406 406 { 407 fun->hw_resources.resources = 407 fun->hw_resources.resources = 408 408 (hw_resource_t *)malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES); 409 409 } -
uspace/drv/bus/usb/ehci/hc_iface.c
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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/pci.c
r85ff862 rf1d6866 70 70 if (!parent_sess) 71 71 return ENOMEM; 72 72 73 73 hw_resource_list_t hw_resources; 74 74 int rc = hw_res_get_resource_list(parent_sess, &hw_resources); 75 async_hangup(parent_sess); 75 76 if (rc != EOK) { 76 async_hangup(parent_sess);77 77 return rc; 78 78 } 79 79 80 80 uintptr_t mem_address = 0; 81 81 size_t mem_size = 0; 82 82 bool mem_found = false; 83 83 84 84 int irq = 0; 85 85 bool irq_found = false; 86 86 87 87 size_t i; 88 88 for (i = 0; i < hw_resources.count; i++) { … … 107 107 } 108 108 } 109 109 free(hw_resources.resources); 110 110 111 if (mem_found && irq_found) { 111 112 *mem_reg_address = mem_address; 112 113 *mem_reg_size = mem_size; 113 114 *irq_no = irq; 114 rc = EOK; 115 } else 116 rc = ENOENT; 117 118 async_hangup(parent_sess); 119 return rc; 115 return EOK; 116 } 117 return ENOENT; 120 118 } 121 119 -
uspace/drv/bus/usb/ohci/root_hub.c
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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 int rc = hw_res_get_resource_list(parent_sess, &hw_resources); 71 const int rc = hw_res_get_resource_list(parent_sess, &hw_resources); 72 async_hangup(parent_sess); 72 73 if (rc != EOK) { 73 async_hangup(parent_sess);74 74 return rc; 75 75 } 76 76 77 77 uintptr_t io_address = 0; 78 78 size_t io_size = 0; 79 79 bool io_found = false; 80 80 81 81 int irq = 0; 82 82 bool irq_found = false; 83 83 84 84 size_t i; 85 85 for (i = 0; i < hw_resources.count; i++) { … … 102 102 } 103 103 } 104 105 async_hangup(parent_sess); 106 104 free(hw_resources.resources); 105 107 106 if (!io_found || !irq_found) 108 107 return ENOENT; 109 108 110 109 *io_reg_address = io_address; 111 110 *io_reg_size = io_size; 112 111 *irq_no = irq; 113 112 114 113 return EOK; 115 114 } 116 115 /*----------------------------------------------------------------------------*/ 117 116 /** Call the PCI driver with a request to enable interrupts 118 117 * … … 127 126 if (!parent_sess) 128 127 return ENOMEM; 129 128 130 129 const bool enabled = hw_res_enable_interrupt(parent_sess); 131 130 async_hangup(parent_sess); 132 131 133 132 return enabled ? EOK : EIO; 134 133 } 135 134 /*----------------------------------------------------------------------------*/ 136 135 /** Call the PCI driver with a request to clear legacy support register 137 136 * … … 142 141 { 143 142 assert(device); 144 143 145 144 async_sess_t *parent_sess = 146 145 devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle, … … 148 147 if (!parent_sess) 149 148 return ENOMEM; 150 149 151 150 /* See UHCI design guide for these values p.45, 152 151 * write all WC bits in USB legacy register */ 153 152 const sysarg_t address = 0xc0; 154 153 const sysarg_t value = 0xaf00; 155 154 156 155 async_exch_t *exch = async_exchange_begin(parent_sess); 157 156 158 157 const int rc = async_req_3_0(exch, DEV_IFACE_ID(PCI_DEV_IFACE), 159 158 IPC_M_CONFIG_SPACE_WRITE_16, address, value); 160 159 161 160 async_exchange_end(exch); 162 161 async_hangup(parent_sess); 163 162 164 163 return rc; 165 164 } -
uspace/drv/bus/usb/uhci/root_hub.c
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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
r85ff862 rf1d6866 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/drv/char/ns8250/ns8250.c
r85ff862 rf1d6866 59 59 60 60 #include <devman.h> 61 #include <ns.h> 61 62 #include <ipc/devman.h> 63 #include <ipc/services.h> 64 #include <ipc/irc.h> 62 65 #include <device/hw_res.h> 63 66 #include <ipc/serial_ctl.h> … … 409 412 static int ns8250_interrupt_enable(ns8250_t *ns) 410 413 { 414 /* 415 * Enable interrupt using IRC service. 416 * TODO: This is a temporary solution until the device framework 417 * takes care of this itself. 418 */ 419 async_sess_t *irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE, 420 SERVICE_IRC, 0, 0); 421 if (!irc_sess) { 422 return EIO; 423 } 424 425 async_exch_t *exch = async_exchange_begin(irc_sess); 426 if (!exch) { 427 return EIO; 428 } 429 async_msg_1(exch, IRC_ENABLE_INTERRUPT, ns->irq); 430 async_exchange_end(exch); 431 411 432 /* Enable interrupt on the serial port. */ 412 433 ns8250_port_interrupts_enable(ns->port);
Note:
See TracChangeset
for help on using the changeset viewer.