Changeset 8c877b2 in mainline for uspace/drv/uhci-hcd
- Timestamp:
- 2011-03-04T13:05:35Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/fix-logger-deadlock, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- d49728c
- Parents:
- dff940f8 (diff), 9a422574 (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/uhci-hcd
- Files:
-
- 2 added
- 15 edited
-
Makefile (modified) (1 diff)
-
batch.c (modified) (21 diffs)
-
batch.h (modified) (2 diffs)
-
iface.c (modified) (9 diffs)
-
main.c (modified) (4 diffs)
-
pci.c (modified) (4 diffs)
-
pci.h (modified) (1 diff)
-
root_hub.c (modified) (6 diffs)
-
transfer_list.c (modified) (6 diffs)
-
transfer_list.h (modified) (1 diff)
-
uhci-hcd.ma (modified) (1 diff)
-
uhci.c (modified) (16 diffs)
-
uhci.h (modified) (2 diffs)
-
uhci_struct/transfer_descriptor.c (modified) (4 diffs)
-
uhci_struct/transfer_descriptor.h (modified) (1 diff)
-
utils/device_keeper.c (added)
-
utils/device_keeper.h (added)
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/uhci-hcd/Makefile
rdff940f8 r8c877b2 39 39 uhci.c \ 40 40 uhci_struct/transfer_descriptor.c \ 41 utils/device_keeper.c \ 41 42 pci.c \ 42 43 batch.c -
uspace/drv/uhci-hcd/batch.c
rdff940f8 r8c877b2 33 33 */ 34 34 #include <errno.h> 35 35 #include <str_error.h> 36 37 #include <usb/usb.h> 36 38 #include <usb/debug.h> 37 39 … … 45 47 static int batch_schedule(batch_t *instance); 46 48 49 static void batch_control( 50 batch_t *instance, int data_stage, int status_stage); 47 51 static void batch_call_in(batch_t *instance); 48 52 static void batch_call_out(batch_t *instance); … … 53 57 batch_t * batch_get(ddf_fun_t *fun, usb_target_t target, 54 58 usb_transfer_type_t transfer_type, size_t max_packet_size, 55 dev_speed_t speed, char *buffer, size_t size,59 usb_speed_t speed, char *buffer, size_t size, 56 60 char* setup_buffer, size_t setup_size, 57 61 usbhc_iface_transfer_in_callback_t func_in, … … 92 96 instance->transport_buffer = 93 97 (size > 0) ? malloc32(transport_size) : NULL; 98 94 99 if ((size > 0) && (instance->transport_buffer == NULL)) { 95 100 usb_log_error("Failed to allocate device accessible buffer.\n"); … … 133 138 134 139 queue_head_element_td(instance->qh, addr_to_phys(instance->tds)); 140 usb_log_debug("Batch(%p) %d:%d memory structures ready.\n", 141 instance, target.address, target.endpoint); 135 142 return instance; 136 143 } … … 139 146 { 140 147 assert(instance); 141 usb_log_debug ("Checking(%p) %d packetfor completion.\n",148 usb_log_debug2("Batch(%p) checking %d packet(s) for completion.\n", 142 149 instance, instance->packets); 143 150 instance->transfered_size = 0; … … 151 158 if (i > 0) 152 159 instance->transfered_size -= instance->setup_size; 160 usb_log_debug("Batch(%p) found error TD(%d):%x.\n", 161 instance, i, instance->tds[i].status); 153 162 return true; 154 163 } … … 156 165 transfer_descriptor_actual_size(&instance->tds[i]); 157 166 } 158 /* This is just an ugly trick to support the old API */159 167 instance->transfered_size -= instance->setup_size; 160 168 return true; … … 164 172 { 165 173 assert(instance); 166 167 174 /* we are data out, we are supposed to provide data */ 168 175 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 169 170 int toggle = 0; 171 /* setup stage */ 172 transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT, 173 instance->setup_size, toggle, false, instance->target, 174 USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]); 175 176 /* data stage */ 177 size_t i = 1; 178 for (;i < instance->packets - 1; ++i) { 179 char *data = 180 instance->transport_buffer + ((i - 1) * instance->max_packet_size); 181 toggle = 1 - toggle; 182 183 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT, 184 instance->max_packet_size, toggle++, false, instance->target, 185 USB_PID_OUT, data, &instance->tds[i + 1]); 186 } 187 188 /* status stage */ 189 i = instance->packets - 1; 190 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT, 191 0, 1, false, instance->target, USB_PID_IN, NULL, NULL); 192 193 instance->tds[i].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG; 194 176 batch_control(instance, USB_PID_OUT, USB_PID_IN); 195 177 instance->next_step = batch_call_out_and_dispose; 178 usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance); 196 179 batch_schedule(instance); 197 180 } … … 200 183 { 201 184 assert(instance); 202 203 int toggle = 0; 204 /* setup stage */ 205 transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT, 206 instance->setup_size, toggle, false, instance->target, 207 USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]); 208 209 /* data stage */ 210 size_t i = 1; 211 for (;i < instance->packets - 1; ++i) { 212 char *data = 213 instance->transport_buffer + ((i - 1) * instance->max_packet_size); 214 toggle = 1 - toggle; 215 216 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT, 217 instance->max_packet_size, toggle, false, instance->target, 218 USB_PID_IN, data, &instance->tds[i + 1]); 219 } 220 221 /* status stage */ 222 i = instance->packets - 1; 223 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT, 224 0, 1, false, instance->target, USB_PID_OUT, NULL, NULL); 225 226 instance->tds[i].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG; 227 185 batch_control(instance, USB_PID_IN, USB_PID_OUT); 228 186 instance->next_step = batch_call_in_and_dispose; 187 usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance); 229 188 batch_schedule(instance); 230 189 } … … 234 193 assert(instance); 235 194 195 const bool low_speed = instance->speed == USB_SPEED_LOW; 236 196 int toggle = 1; 237 197 size_t i = 0; … … 244 204 245 205 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT, 246 instance->max_packet_size, toggle, false, instance->target,247 USB_PID_IN, data, next);206 instance->max_packet_size, toggle, false, low_speed, 207 instance->target, USB_PID_IN, data, next); 248 208 } 249 209 … … 251 211 252 212 instance->next_step = batch_call_in_and_dispose; 213 usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance); 253 214 batch_schedule(instance); 254 215 } … … 257 218 { 258 219 assert(instance); 259 260 220 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 261 221 222 const bool low_speed = instance->speed == USB_SPEED_LOW; 262 223 int toggle = 1; 263 224 size_t i = 0; … … 270 231 271 232 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT, 272 instance->max_packet_size, toggle++, false, instance->target,273 USB_PID_OUT, data, next);233 instance->max_packet_size, toggle++, false, low_speed, 234 instance->target, USB_PID_OUT, data, next); 274 235 } 275 236 … … 277 238 278 239 instance->next_step = batch_call_out_and_dispose; 240 usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance); 279 241 batch_schedule(instance); 280 242 } 281 243 /*----------------------------------------------------------------------------*/ 244 static void batch_control( 245 batch_t *instance, int data_stage, int status_stage) 246 { 247 assert(instance); 248 249 const bool low_speed = instance->speed == USB_SPEED_LOW; 250 int toggle = 0; 251 /* setup stage */ 252 transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT, 253 instance->setup_size, toggle, false, low_speed, instance->target, 254 USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]); 255 256 /* data stage */ 257 size_t packet = 1; 258 size_t remain_size = instance->buffer_size; 259 while (remain_size > 0) { 260 char *data = 261 instance->transport_buffer + instance->buffer_size 262 - remain_size; 263 264 toggle = 1 - toggle; 265 266 const size_t packet_size = 267 (instance->max_packet_size > remain_size) ? 268 remain_size : instance->max_packet_size; 269 270 transfer_descriptor_init(&instance->tds[packet], 271 DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed, 272 instance->target, data_stage, data, 273 &instance->tds[packet + 1]); 274 275 ++packet; 276 assert(packet < instance->packets); 277 assert(packet_size <= remain_size); 278 remain_size -= packet_size; 279 } 280 281 /* status stage */ 282 assert(packet == instance->packets - 1); 283 transfer_descriptor_init(&instance->tds[packet], DEFAULT_ERROR_COUNT, 284 0, 1, false, low_speed, instance->target, status_stage, NULL, NULL); 285 286 287 instance->tds[packet].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG; 288 usb_log_debug2("Control last TD status: %x.\n", 289 instance->tds[packet].status); 290 } 291 /*----------------------------------------------------------------------------*/ 282 292 void batch_call_in(batch_t *instance) 283 293 { … … 288 298 289 299 int err = instance->error; 290 usb_log_info("Callback IN(%d): %d, %zu.\n", instance->transfer_type, 291 err, instance->transfered_size); 300 usb_log_debug("Batch(%p) callback IN(type:%d): %s(%d), %zu.\n", 301 instance, instance->transfer_type, str_error(err), err, 302 instance->transfered_size); 292 303 293 304 instance->callback_in(instance->fun, … … 302 313 303 314 int err = instance->error; 304 usb_log_info("Callback OUT(%d): %d.\n", instance->transfer_type, err); 315 usb_log_debug("Batch(%p) callback OUT(type:%d): %s(%d).\n", 316 instance, instance->transfer_type, str_error(err), err); 305 317 instance->callback_out(instance->fun, 306 318 err, instance->arg); … … 311 323 assert(instance); 312 324 batch_call_in(instance); 313 usb_log_debug(" Disposing batch: %p.\n", instance);325 usb_log_debug("Batch(%p) disposing.\n", instance); 314 326 free32(instance->tds); 315 327 free32(instance->qh); … … 323 335 assert(instance); 324 336 batch_call_out(instance); 325 usb_log_debug(" Disposing batch: %p.\n", instance);337 usb_log_debug("Batch(%p) disposing.\n", instance); 326 338 free32(instance->tds); 327 339 free32(instance->qh); … … 338 350 return uhci_schedule(hc, instance); 339 351 } 340 /*----------------------------------------------------------------------------*/341 /* DEPRECATED FUNCTIONS NEEDED BY THE OLD API */342 void batch_control_setup_old(batch_t *instance)343 {344 assert(instance);345 instance->packets = 1;346 347 /* setup stage */348 transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,349 instance->setup_size, 0, false, instance->target,350 USB_PID_SETUP, instance->setup_buffer, NULL);351 352 instance->next_step = batch_call_out_and_dispose;353 batch_schedule(instance);354 }355 /*----------------------------------------------------------------------------*/356 void batch_control_write_data_old(batch_t *instance)357 {358 assert(instance);359 instance->packets -= 2;360 batch_interrupt_out(instance);361 }362 /*----------------------------------------------------------------------------*/363 void batch_control_read_data_old(batch_t *instance)364 {365 assert(instance);366 instance->packets -= 2;367 batch_interrupt_in(instance);368 }369 /*----------------------------------------------------------------------------*/370 void batch_control_write_status_old(batch_t *instance)371 {372 assert(instance);373 instance->packets = 1;374 transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,375 0, 1, false, instance->target, USB_PID_IN, NULL, NULL);376 instance->next_step = batch_call_in_and_dispose;377 batch_schedule(instance);378 }379 /*----------------------------------------------------------------------------*/380 void batch_control_read_status_old(batch_t *instance)381 {382 assert(instance);383 instance->packets = 1;384 transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,385 0, 1, false, instance->target, USB_PID_OUT, NULL, NULL);386 instance->next_step = batch_call_out_and_dispose;387 batch_schedule(instance);388 }389 352 /** 390 353 * @} -
uspace/drv/uhci-hcd/batch.h
rdff940f8 r8c877b2 43 43 #include "uhci_struct/queue_head.h" 44 44 45 typedef enum {46 LOW_SPEED,47 FULL_SPEED,48 } dev_speed_t;49 50 45 typedef struct batch 51 46 { 52 47 link_t link; 53 dev_speed_t speed;48 usb_speed_t speed; 54 49 usb_target_t target; 55 50 usb_transfer_type_t transfer_type; … … 76 71 batch_t * batch_get(ddf_fun_t *fun, usb_target_t target, 77 72 usb_transfer_type_t transfer_type, size_t max_packet_size, 78 dev_speed_t speed, char *buffer, size_t size,73 usb_speed_t speed, char *buffer, size_t size, 79 74 char *setup_buffer, size_t setup_size, 80 75 usbhc_iface_transfer_in_callback_t func_in, -
uspace/drv/uhci-hcd/iface.c
rdff940f8 r8c877b2 41 41 #include "iface.h" 42 42 #include "uhci.h" 43 #include "utils/device_keeper.h" 43 44 44 45 /*----------------------------------------------------------------------------*/ … … 48 49 uhci_t *hc = fun_to_uhci(fun); 49 50 assert(hc); 50 usb_address_keeping_reserve_default(&hc->address_manager); 51 usb_log_debug("Default address request with speed %d.\n", speed); 52 device_keeper_reserve_default(&hc->device_manager, speed); 51 53 return EOK; 52 54 } … … 57 59 uhci_t *hc = fun_to_uhci(fun); 58 60 assert(hc); 59 usb_address_keeping_release_default(&hc->address_manager); 61 usb_log_debug("Default address release.\n"); 62 device_keeper_release_default(&hc->device_manager); 60 63 return EOK; 61 64 } … … 67 70 uhci_t *hc = fun_to_uhci(fun); 68 71 assert(hc); 69 *address = usb_address_keeping_request(&hc->address_manager); 72 assert(address); 73 74 usb_log_debug("Address request with speed %d.\n", speed); 75 *address = device_keeper_request(&hc->device_manager, speed); 76 usb_log_debug("Address request with result: %d.\n", *address); 70 77 if (*address <= 0) 71 78 return *address; … … 79 86 uhci_t *hc = fun_to_uhci(fun); 80 87 assert(hc); 81 usb_address_keeping_devman_bind(&hc->address_manager, address, handle); 88 usb_log_debug("Address bind %d-%d.\n", address, handle); 89 device_keeper_bind(&hc->device_manager, address, handle); 82 90 return EOK; 83 91 } … … 88 96 uhci_t *hc = fun_to_uhci(fun); 89 97 assert(hc); 90 usb_address_keeping_release_default(&hc->address_manager); 98 usb_log_debug("Address release %d.\n", address); 99 device_keeper_release(&hc->device_manager, address); 91 100 return EOK; 92 101 } 93 102 /*----------------------------------------------------------------------------*/ 94 103 static int interrupt_out(ddf_fun_t *fun, usb_target_t target, 95 size_t max_packet_size, 96 void *data, size_t size, 104 size_t max_packet_size, void *data, size_t size, 97 105 usbhc_iface_transfer_out_callback_t callback, void *arg) 98 106 { 99 dev_speed_t speed = FULL_SPEED; 107 assert(fun); 108 uhci_t *hc = fun_to_uhci(fun); 109 assert(hc); 110 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 111 112 usb_log_debug("Interrupt OUT %d:%d %zu(%zu).\n", 113 target.address, target.endpoint, size, max_packet_size); 100 114 101 115 batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT, … … 108 122 /*----------------------------------------------------------------------------*/ 109 123 static int interrupt_in(ddf_fun_t *fun, usb_target_t target, 110 size_t max_packet_size, 111 void *data, size_t size, 124 size_t max_packet_size, void *data, size_t size, 112 125 usbhc_iface_transfer_in_callback_t callback, void *arg) 113 126 { 114 dev_speed_t speed = FULL_SPEED; 127 assert(fun); 128 uhci_t *hc = fun_to_uhci(fun); 129 assert(hc); 130 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 131 usb_log_debug("Interrupt IN %d:%d %zu(%zu).\n", 132 target.address, target.endpoint, size, max_packet_size); 115 133 116 134 batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT, … … 127 145 usbhc_iface_transfer_out_callback_t callback, void *arg) 128 146 { 129 dev_speed_t speed = FULL_SPEED; 147 assert(fun); 148 uhci_t *hc = fun_to_uhci(fun); 149 assert(hc); 150 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 151 usb_log_debug("Control WRITE %d:%d %zu(%zu).\n", 152 target.address, target.endpoint, size, max_packet_size); 130 153 131 154 batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL, … … 143 166 usbhc_iface_transfer_in_callback_t callback, void *arg) 144 167 { 145 dev_speed_t speed = FULL_SPEED; 146 168 assert(fun); 169 uhci_t *hc = fun_to_uhci(fun); 170 assert(hc); 171 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 172 173 usb_log_debug("Control READ %d:%d %zu(%zu).\n", 174 target.address, target.endpoint, size, max_packet_size); 147 175 batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL, 148 176 max_packet_size, speed, data, size, setup_data, setup_size, callback, -
uspace/drv/uhci-hcd/main.c
rdff940f8 r8c877b2 34 34 #include <ddf/driver.h> 35 35 #include <ddf/interrupt.h> 36 #include <device/hw_res.h> 37 #include <errno.h> 38 #include <str_error.h> 39 36 40 #include <usb_iface.h> 37 41 #include <usb/ddfiface.h> 38 #include <device/hw_res.h>39 40 #include <errno.h>41 42 42 #include <usb/debug.h> 43 43 … … 50 50 51 51 static int uhci_add_device(ddf_dev_t *device); 52 53 52 /*----------------------------------------------------------------------------*/ 54 53 static driver_ops_t uhci_driver_ops = { … … 70 69 } 71 70 /*----------------------------------------------------------------------------*/ 72 #define CHECK_RET_RETURN(ret, message...) \ 71 static int uhci_add_device(ddf_dev_t *device) 72 { 73 assert(device); 74 uhci_t *hcd = NULL; 75 #define CHECK_RET_FREE_HC_RETURN(ret, message...) \ 73 76 if (ret != EOK) { \ 74 77 usb_log_error(message); \ 78 if (hcd != NULL) \ 79 free(hcd); \ 75 80 return ret; \ 76 81 } 77 82 78 static int uhci_add_device(ddf_dev_t *device)79 {80 assert(device);81 82 83 usb_log_info("uhci_add_device() called\n"); 83 84 84 85 uintptr_t io_reg_base; 86 size_t io_reg_size; 87 int irq; 85 uintptr_t io_reg_base = 0; 86 size_t io_reg_size = 0; 87 int irq = 0; 88 88 89 89 int ret = 90 90 pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq); 91 92 CHECK_RET_RETURN(ret, 91 CHECK_RET_FREE_HC_RETURN(ret, 93 92 "Failed(%d) to get I/O addresses:.\n", ret, device->handle); 94 93 usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n", 95 94 io_reg_base, io_reg_size, irq); 96 95 96 ret = pci_disable_legacy(device); 97 CHECK_RET_FREE_HC_RETURN(ret, 98 "Failed(%d) disable legacy USB: %s.\n", ret, str_error(ret)); 99 100 #if 0 97 101 ret = pci_enable_interrupts(device); 98 CHECK_RET_RETURN(ret, "Failed(%d) to get enable interrupts:\n", ret); 102 if (ret != EOK) { 103 usb_log_warning( 104 "Failed(%d) to enable interrupts, fall back to polling.\n", 105 ret); 106 } 107 #endif 99 108 100 uhci_t *uhci_hc = malloc(sizeof(uhci_t)); 101 ret = (uhci_hc != NULL) ? EOK : ENOMEM; 102 CHECK_RET_RETURN(ret, "Failed to allocate memory for uhci hcd driver.\n"); 109 hcd = malloc(sizeof(uhci_t)); 110 ret = (hcd != NULL) ? EOK : ENOMEM; 111 CHECK_RET_FREE_HC_RETURN(ret, 112 "Failed(%d) to allocate memory for uhci hcd.\n", ret); 103 113 104 ret = uhci_init(uhci_hc, device, (void*)io_reg_base, io_reg_size); 105 if (ret != EOK) { 106 usb_log_error("Failed to init uhci-hcd.\n"); 107 free(uhci_hc); 108 return ret; 109 } 114 ret = uhci_init(hcd, device, (void*)io_reg_base, io_reg_size); 115 CHECK_RET_FREE_HC_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", 116 ret); 117 #undef CHECK_RET_FREE_HC_RETURN 110 118 111 119 /* 112 * We might free uhci_hc, but that does not matter since no one120 * We might free hcd, but that does not matter since no one 113 121 * else would access driver_data anyway. 114 122 */ 115 device->driver_data = uhci_hc;123 device->driver_data = hcd; 116 124 125 ddf_fun_t *rh = NULL; 126 #define CHECK_RET_FINI_FREE_RETURN(ret, message...) \ 127 if (ret != EOK) { \ 128 usb_log_error(message); \ 129 if (hcd != NULL) {\ 130 uhci_fini(hcd); \ 131 free(hcd); \ 132 } \ 133 if (rh != NULL) \ 134 free(rh); \ 135 return ret; \ 136 } 137 138 /* It does no harm if we register this on polling */ 117 139 ret = register_interrupt_handler(device, irq, irq_handler, 118 &uhci_hc->interrupt_code); 119 if (ret != EOK) { 120 usb_log_error("Failed to register interrupt handler.\n"); 121 uhci_fini(uhci_hc); 122 free(uhci_hc); 123 return ret; 124 } 140 &hcd->interrupt_code); 141 CHECK_RET_FINI_FREE_RETURN(ret, 142 "Failed(%d) to register interrupt handler.\n", ret); 125 143 126 ddf_fun_t *rh;127 144 ret = setup_root_hub(&rh, device); 128 if (ret != EOK) { 129 usb_log_error("Failed to setup uhci root hub.\n"); 130 uhci_fini(uhci_hc); 131 free(uhci_hc); 132 return ret; 133 } 134 rh->driver_data = uhci_hc->ddf_instance; 145 CHECK_RET_FINI_FREE_RETURN(ret, 146 "Failed(%d) to setup UHCI root hub.\n", ret); 147 rh->driver_data = hcd->ddf_instance; 135 148 136 149 ret = ddf_fun_bind(rh); 137 if (ret != EOK) { 138 usb_log_error("Failed to register root hub.\n"); 139 uhci_fini(uhci_hc); 140 free(uhci_hc); 141 free(rh); 142 return ret; 143 } 150 CHECK_RET_FINI_FREE_RETURN(ret, 151 "Failed(%d) to register UHCI root hub.\n", ret); 144 152 145 153 return EOK; 154 #undef CHECK_RET_FINI_FREE_RETURN 146 155 } 147 156 /*----------------------------------------------------------------------------*/ … … 149 158 { 150 159 sleep(3); 151 usb_log_enable(USB_LOG_LEVEL_ INFO, NAME);160 usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME); 152 161 153 162 return ddf_driver_main(&uhci_driver); -
uspace/drv/uhci-hcd/pci.c
rdff940f8 r8c877b2 38 38 #include <devman.h> 39 39 #include <device/hw_res.h> 40 41 #include <usb/debug.h> 42 #include <pci_dev_iface.h> 40 43 41 44 #include "pci.h" … … 83 86 irq = res->res.interrupt.irq; 84 87 irq_found = true; 88 usb_log_debug2("Found interrupt: %d.\n", irq); 85 89 break; 86 90 case IO_RANGE: 87 io_address = (uintptr_t) 88 res->res.io_range.address; 91 io_address = res->res.io_range.address; 89 92 io_size = res->res.io_range.size; 93 usb_log_debug2("Found io: %llx %zu.\n", 94 res->res.io_range.address, res->res.io_range.size); 90 95 io_found = true; 91 96 break; … … 105 110 } 106 111 107 if (io_reg_address != NULL) { 108 *io_reg_address = io_address; 109 } 110 if (io_reg_size != NULL) { 111 *io_reg_size = io_size; 112 } 113 if (irq_no != NULL) { 114 *irq_no = irq; 115 } 112 *io_reg_address = io_address; 113 *io_reg_size = io_size; 114 *irq_no = irq; 116 115 117 116 rc = EOK; … … 127 126 IPC_FLAG_BLOCKING); 128 127 bool enabled = hw_res_enable_interrupt(parent_phone); 128 async_hangup(parent_phone); 129 129 return enabled ? EOK : EIO; 130 130 } 131 /*----------------------------------------------------------------------------*/ 132 int pci_disable_legacy(ddf_dev_t *device) 133 { 134 assert(device); 135 int parent_phone = devman_parent_device_connect(device->handle, 136 IPC_FLAG_BLOCKING); 137 if (parent_phone < 0) { 138 return parent_phone; 139 } 140 141 /* See UHCI design guide for these values, 142 * write all WC bits in USB legacy register */ 143 sysarg_t address = 0xc0; 144 sysarg_t value = 0x8f00; 145 146 int rc = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), 147 IPC_M_CONFIG_SPACE_WRITE_16, address, value); 148 async_hangup(parent_phone); 149 150 return rc; 151 } 152 /*----------------------------------------------------------------------------*/ 131 153 /** 132 154 * @} -
uspace/drv/uhci-hcd/pci.h
rdff940f8 r8c877b2 40 40 int pci_get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *); 41 41 int pci_enable_interrupts(ddf_dev_t *); 42 int pci_disable_legacy(ddf_dev_t *); 42 43 43 44 #endif -
uspace/drv/uhci-hcd/root_hub.c
rdff940f8 r8c877b2 34 34 #include <assert.h> 35 35 #include <errno.h> 36 #include <str_error.h> 36 37 #include <stdio.h> 38 #include <ops/hw_res.h> 39 37 40 #include <usb_iface.h> 38 41 #include <usb/debug.h> … … 41 44 #include "uhci.h" 42 45 46 /*----------------------------------------------------------------------------*/ 43 47 static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun, 44 48 devman_handle_t *handle) … … 51 55 return EOK; 52 56 } 53 57 /*----------------------------------------------------------------------------*/ 54 58 static int usb_iface_get_address_rh_impl(ddf_fun_t *fun, devman_handle_t handle, 55 59 usb_address_t *address) … … 61 65 assert(hc); 62 66 63 usb_address_t addr = usb_address_keeping_find(&hc->address_manager,67 usb_address_t addr = device_keeper_find(&hc->device_manager, 64 68 handle); 65 69 if (addr < 0) { … … 73 77 return EOK; 74 78 } 75 79 /*----------------------------------------------------------------------------*/ 76 80 usb_iface_t usb_iface_root_hub_fun_impl = { 77 81 .get_hc_handle = usb_iface_get_hc_handle_rh_impl, 78 82 .get_address = usb_iface_get_address_rh_impl 79 83 }; 84 /*----------------------------------------------------------------------------*/ 85 static hw_resource_list_t *get_resource_list(ddf_fun_t *dev) 86 { 87 assert(dev); 88 ddf_fun_t *hc_ddf_instance = dev->driver_data; 89 assert(hc_ddf_instance); 90 uhci_t *hc = hc_ddf_instance->driver_data; 91 assert(hc); 80 92 93 //TODO: fix memory leak 94 hw_resource_list_t *resource_list = malloc(sizeof(hw_resource_list_t)); 95 assert(resource_list); 96 resource_list->count = 1; 97 resource_list->resources = malloc(sizeof(hw_resource_t)); 98 assert(resource_list->resources); 99 resource_list->resources[0].type = IO_RANGE; 100 resource_list->resources[0].res.io_range.address = 101 ((uintptr_t)hc->registers) + 0x10; // see UHCI design guide 102 resource_list->resources[0].res.io_range.size = 4; 103 resource_list->resources[0].res.io_range.endianness = LITTLE_ENDIAN; 104 105 return resource_list; 106 } 107 /*----------------------------------------------------------------------------*/ 108 static hw_res_ops_t hw_res_iface = { 109 .get_resource_list = get_resource_list, 110 .enable_interrupt = NULL 111 }; 112 /*----------------------------------------------------------------------------*/ 81 113 static ddf_dev_ops_t root_hub_ops = { 82 .interfaces[USB_DEV_IFACE] = &usb_iface_root_hub_fun_impl 114 .interfaces[USB_DEV_IFACE] = &usb_iface_root_hub_fun_impl, 115 .interfaces[HW_RES_DEV_IFACE] = &hw_res_iface 83 116 }; 84 85 117 /*----------------------------------------------------------------------------*/ 86 118 int setup_root_hub(ddf_fun_t **fun, ddf_dev_t *hc) 87 119 { 88 120 assert(fun); 121 assert(hc); 89 122 int ret; 90 123 … … 105 138 ret = ddf_fun_add_match_id(hub, match_str, 100); 106 139 if (ret != EOK) { 107 usb_log_error("Failed to add root hub match id.\n"); 140 usb_log_error("Failed(%d) to add root hub match id: %s\n", 141 ret, str_error(ret)); 108 142 ddf_fun_destroy(hub); 109 return ENOMEM;143 return ret; 110 144 } 111 145 -
uspace/drv/uhci-hcd/transfer_list.c
rdff940f8 r8c877b2 70 70 assert(instance); 71 71 assert(batch); 72 usb_log_debug2("Adding batch(%p) to queue %s.\n", batch, instance->name); 72 73 73 74 uint32_t pa = (uintptr_t)addr_to_phys(batch->qh); … … 83 84 list_append(&batch->link, &instance->batch_list); 84 85 instance->queue_head->element = pa; 85 usb_log_debug 2("Added batch(%p)to queue %s first.\n",86 usb_log_debug("Batch(%p) added to queue %s first.\n", 86 87 batch, instance->name); 87 88 fibril_mutex_unlock(&instance->guard); … … 96 97 queue_head_append_qh(last->qh, pa); 97 98 list_append(&batch->link, &instance->batch_list); 98 usb_log_debug 2("Added batch(%p)to queue %s last, first is %p.\n",99 usb_log_debug("Batch(%p) added to queue %s last, first is %p.\n", 99 100 batch, instance->name, first ); 100 101 fibril_mutex_unlock(&instance->guard); … … 108 109 assert(instance->queue_head); 109 110 assert(batch->qh); 111 usb_log_debug2("Removing batch(%p) from queue %s.\n", batch, instance->name); 110 112 111 113 /* I'm the first one here */ 112 114 if (batch->link.prev == &instance->batch_list) { 113 usb_log_debug(" Removing batch %p was first, next element %x.\n",114 batch, batch->qh->next_queue);115 usb_log_debug("Batch(%p) removed (FIRST) from queue %s, next element %x.\n", 116 batch, instance->name, batch->qh->next_queue); 115 117 instance->queue_head->element = batch->qh->next_queue; 116 118 } else { 117 usb_log_debug(" Removing batch %p was NOT first, next element %x.\n",118 batch, batch->qh->next_queue);119 usb_log_debug("Batch(%p) removed (NOT FIRST) from queue, next element %x.\n", 120 batch, instance->name, batch->qh->next_queue); 119 121 batch_t *prev = list_get_instance(batch->link.prev, batch_t, link); 120 122 prev->qh->next_queue = batch->qh->next_queue; … … 123 125 } 124 126 /*----------------------------------------------------------------------------*/ 125 void transfer_list_ check(transfer_list_t *instance)127 void transfer_list_remove_finished(transfer_list_t *instance) 126 128 { 127 129 assert(instance); 130 131 LIST_INITIALIZE(done); 132 128 133 fibril_mutex_lock(&instance->guard); 129 134 link_t *current = instance->batch_list.next; … … 134 139 if (batch_is_complete(batch)) { 135 140 transfer_list_remove_batch(instance, batch); 136 batch->next_step(batch);141 list_append(current, &done); 137 142 } 138 143 current = next; 139 144 } 140 145 fibril_mutex_unlock(&instance->guard); 146 147 while (!list_empty(&done)) { 148 link_t *item = done.next; 149 list_remove(item); 150 batch_t *batch = list_get_instance(item, batch_t, link); 151 batch->next_step(batch); 152 } 141 153 } 142 154 /** -
uspace/drv/uhci-hcd/transfer_list.h
rdff940f8 r8c877b2 60 60 queue_head_dispose(instance->queue_head); 61 61 } 62 void transfer_list_ check(transfer_list_t *instance);62 void transfer_list_remove_finished(transfer_list_t *instance); 63 63 64 64 void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch); -
uspace/drv/uhci-hcd/uhci-hcd.ma
rdff940f8 r8c877b2 1 1 10 pci/ven=8086&dev=7020 2 2 10 pci/ven=8086&dev=7112 3 4 10 pci/ven=8086&dev=27c8 5 10 pci/ven=8086&dev=27c9 6 10 pci/ven=8086&dev=27ca 7 10 pci/ven=8086&dev=27cb 8 9 10 10 pci/ven=8086&dev=2830 11 10 pci/ven=8086&dev=2831 12 10 pci/ven=8086&dev=2832 13 10 pci/ven=8086&dev=2834 14 10 pci/ven=8086&dev=2835 15 16 10 pci/ven=8086&dev=2934 17 10 pci/ven=8086&dev=2935 18 10 pci/ven=8086&dev=2936 19 10 pci/ven=8086&dev=2937 20 10 pci/ven=8086&dev=2938 21 10 pci/ven=8086&dev=2939 -
uspace/drv/uhci-hcd/uhci.c
rdff940f8 r8c877b2 48 48 { 49 49 .cmd = CMD_PIO_READ_16, 50 .addr = (void*)0xc022,50 .addr = NULL, /* patched for every instance */ 51 51 .dstarg = 1 52 52 }, 53 53 { 54 54 .cmd = CMD_PIO_WRITE_16, 55 .addr = (void*)0xc022,55 .addr = NULL, /* pathed for every instance */ 56 56 .value = 0x1f 57 57 }, … … 68 68 assert(hc); 69 69 70 usb_address_t addr = usb_address_keeping_find(&hc->address_manager,70 usb_address_t addr = device_keeper_find(&hc->device_manager, 71 71 handle); 72 72 if (addr < 0) { … … 80 80 return EOK; 81 81 } 82 83 82 /*----------------------------------------------------------------------------*/ 84 83 static usb_iface_t hc_usb_iface = { 85 84 .get_hc_handle = usb_iface_get_hc_handle_hc_impl, … … 89 88 static ddf_dev_ops_t uhci_ops = { 90 89 .interfaces[USB_DEV_IFACE] = &hc_usb_iface, 91 .interfaces[USBHC_DEV_IFACE] = &uhci_iface 90 .interfaces[USBHC_DEV_IFACE] = &uhci_iface, 92 91 }; 93 92 /*----------------------------------------------------------------------------*/ 94 93 static int uhci_init_transfer_lists(uhci_t *instance); 95 94 static int uhci_init_mem_structures(uhci_t *instance); … … 102 101 bool low_speed, usb_transfer_type_t, size_t size); 103 102 104 #define CHECK_RET_RETURN(ret, message...) \ 103 104 int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size) 105 { 106 assert(reg_size >= sizeof(regs_t)); 107 int ret; 108 109 #define CHECK_RET_DEST_FUN_RETURN(ret, message...) \ 105 110 if (ret != EOK) { \ 106 111 usb_log_error(message); \ 112 if (instance->ddf_instance) \ 113 ddf_fun_destroy(instance->ddf_instance); \ 107 114 return ret; \ 108 115 } else (void) 0 109 116 110 int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size) 111 { 112 assert(reg_size >= sizeof(regs_t)); 113 int ret; 114 115 /* 116 * Create UHCI function. 117 */ 117 /* Create UHCI function. */ 118 118 instance->ddf_instance = ddf_fun_create(dev, fun_exposed, "uhci"); 119 if (instance->ddf_instance == NULL) {120 usb_log_error("Failed to create UHCI device function.\n");121 return ENOMEM;122 } 119 ret = (instance->ddf_instance == NULL) ? ENOMEM : EOK; 120 CHECK_RET_DEST_FUN_RETURN(ret, 121 "Failed to create UHCI device function.\n"); 122 123 123 instance->ddf_instance->ops = &uhci_ops; 124 124 instance->ddf_instance->driver_data = instance; 125 125 126 126 ret = ddf_fun_bind(instance->ddf_instance); 127 CHECK_RET_RETURN(ret, "Failed to bind UHCI device function: %s.\n", 128 str_error(ret)); 127 CHECK_RET_DEST_FUN_RETURN(ret, 128 "Failed(%d) to bind UHCI device function: %s.\n", 129 ret, str_error(ret)); 129 130 130 131 /* allow access to hc control registers */ 131 132 regs_t *io; 132 133 ret = pio_enable(regs, reg_size, (void**)&io); 133 CHECK_RET_RETURN(ret, "Failed to gain access to registers at %p.\n", io); 134 CHECK_RET_DEST_FUN_RETURN(ret, 135 "Failed(%d) to gain access to registers at %p: %s.\n", 136 ret, str_error(ret), io); 134 137 instance->registers = io; 135 usb_log_debug("Device registers accessible.\n"); 138 usb_log_debug("Device registers at %p(%u) accessible.\n", 139 io, reg_size); 136 140 137 141 ret = uhci_init_mem_structures(instance); 138 CHECK_RET_RETURN(ret, "Failed to initialize memory structures.\n"); 142 CHECK_RET_DEST_FUN_RETURN(ret, 143 "Failed to initialize UHCI memory structures.\n"); 139 144 140 145 uhci_init_hw(instance); 141 142 instance->cleaner =fibril_create(uhci_interrupt_emulator, instance);143 //fibril_add_ready(instance->cleaner);146 instance->cleaner = 147 fibril_create(uhci_interrupt_emulator, instance); 148 fibril_add_ready(instance->cleaner); 144 149 145 150 instance->debug_checker = fibril_create(uhci_debug_checker, instance); 146 151 fibril_add_ready(instance->debug_checker); 147 152 148 return EOK; 153 usb_log_info("Started UHCI driver.\n"); 154 return EOK; 155 #undef CHECK_RET_DEST_FUN_RETURN 149 156 } 150 157 /*----------------------------------------------------------------------------*/ 151 158 void uhci_init_hw(uhci_t *instance) 152 159 { 160 assert(instance); 161 162 /* reset everything, who knows what touched it before us */ 163 pio_write_16(&instance->registers->usbcmd, UHCI_CMD_GLOBAL_RESET); 164 async_usleep(10000); /* 10ms according to USB spec */ 165 pio_write_16(&instance->registers->usbcmd, 0); 166 167 /* reset hc, all states and counters */ 168 pio_write_16(&instance->registers->usbcmd, UHCI_CMD_HCRESET); 169 while ((pio_read_16(&instance->registers->usbcmd) & UHCI_CMD_HCRESET) != 0) 170 { async_usleep(10); } 153 171 154 172 /* set framelist pointer */ … … 158 176 /* enable all interrupts, but resume interrupt */ 159 177 pio_write_16(&instance->registers->usbintr, 160 UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);178 UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET); 161 179 162 180 /* Start the hc with large(64B) packet FSBR */ 163 181 pio_write_16(&instance->registers->usbcmd, 164 182 UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE); 165 usb_log_debug("Started UHCI HC.\n");166 183 } 167 184 /*----------------------------------------------------------------------------*/ … … 169 186 { 170 187 assert(instance); 188 #define CHECK_RET_DEST_CMDS_RETURN(ret, message...) \ 189 if (ret != EOK) { \ 190 usb_log_error(message); \ 191 if (instance->interrupt_code.cmds != NULL) \ 192 free(instance->interrupt_code.cmds); \ 193 return ret; \ 194 } else (void) 0 171 195 172 196 /* init interrupt code */ 173 irq_cmd_t *interrupt_commands = malloc(sizeof(uhci_cmds)); 174 if (interrupt_commands == NULL) { 175 return ENOMEM; 176 } 177 memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds)); 178 interrupt_commands[0].addr = (void*)&instance->registers->usbsts; 179 interrupt_commands[1].addr = (void*)&instance->registers->usbsts; 180 instance->interrupt_code.cmds = interrupt_commands; 181 instance->interrupt_code.cmdcount = 182 sizeof(uhci_cmds) / sizeof(irq_cmd_t); 197 instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds)); 198 int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK; 199 CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to allocate interrupt cmds space.\n"); 200 201 { 202 irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds; 203 memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds)); 204 interrupt_commands[0].addr = (void*)&instance->registers->usbsts; 205 interrupt_commands[1].addr = (void*)&instance->registers->usbsts; 206 instance->interrupt_code.cmdcount = 207 sizeof(uhci_cmds) / sizeof(irq_cmd_t); 208 } 183 209 184 210 /* init transfer lists */ 185 intret = uhci_init_transfer_lists(instance);186 CHECK_RET_ RETURN(ret, "Failed to initialize transfer lists.\n");211 ret = uhci_init_transfer_lists(instance); 212 CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to initialize transfer lists.\n"); 187 213 usb_log_debug("Initialized transfer lists.\n"); 188 214 … … 190 216 instance->frame_list = get_page(); 191 217 ret = instance ? EOK : ENOMEM; 192 CHECK_RET_ RETURN(ret, "Failed to get frame list page.\n");218 CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to get frame list page.\n"); 193 219 usb_log_debug("Initialized frame list.\n"); 194 220 … … 197 223 instance->transfers_interrupt.queue_head_pa 198 224 | LINK_POINTER_QUEUE_HEAD_FLAG; 225 199 226 unsigned i = 0; 200 227 for(; i < UHCI_FRAME_LIST_COUNT; ++i) { … … 203 230 204 231 /* init address keeper(libusb) */ 205 usb_address_keeping_init(&instance->address_manager, USB11_ADDRESS_MAX); 206 usb_log_debug("Initialized address manager.\n"); 207 208 return EOK; 232 device_keeper_init(&instance->device_manager); 233 usb_log_debug("Initialized device manager.\n"); 234 235 return EOK; 236 #undef CHECK_RET_DEST_CMDS_RETURN 209 237 } 210 238 /*----------------------------------------------------------------------------*/ … … 212 240 { 213 241 assert(instance); 242 #define CHECK_RET_CLEAR_RETURN(ret, message...) \ 243 if (ret != EOK) { \ 244 usb_log_error(message); \ 245 transfer_list_fini(&instance->transfers_bulk_full); \ 246 transfer_list_fini(&instance->transfers_control_full); \ 247 transfer_list_fini(&instance->transfers_control_slow); \ 248 transfer_list_fini(&instance->transfers_interrupt); \ 249 return ret; \ 250 } else (void) 0 214 251 215 252 /* initialize TODO: check errors */ 216 253 int ret; 217 254 ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL"); 218 assert(ret == EOK); 255 CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list."); 256 219 257 ret = transfer_list_init(&instance->transfers_control_full, "CONTROL_FULL"); 220 assert(ret == EOK); 258 CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list."); 259 221 260 ret = transfer_list_init(&instance->transfers_control_slow, "CONTROL_SLOW"); 222 assert(ret == EOK); 261 CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list."); 262 223 263 ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT"); 224 assert(ret == EOK);264 CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list."); 225 265 226 266 transfer_list_set_next(&instance->transfers_control_full, … … 249 289 250 290 return EOK; 291 #undef CHECK_RET_CLEAR_RETURN 251 292 } 252 293 /*----------------------------------------------------------------------------*/ … … 255 296 assert(instance); 256 297 assert(batch); 257 const int low_speed = (batch->speed == LOW_SPEED);298 const int low_speed = (batch->speed == USB_SPEED_LOW); 258 299 if (!allowed_usb_packet( 259 300 low_speed, batch->transfer_type, batch->max_packet_size)) { 260 301 usb_log_warning("Invalid USB packet specified %s SPEED %d %zu.\n", 261 low_speed ? "LOW" : "FULL" , batch->transfer_type,302 low_speed ? "LOW" : "FULL" , batch->transfer_type, 262 303 batch->max_packet_size); 263 304 return ENOTSUP; … … 276 317 { 277 318 assert(instance); 278 if ((status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) == 0) 279 return; 280 usb_log_debug("UHCI interrupt: %X.\n", status); 281 transfer_list_check(&instance->transfers_interrupt); 282 transfer_list_check(&instance->transfers_control_slow); 283 transfer_list_check(&instance->transfers_control_full); 284 transfer_list_check(&instance->transfers_bulk_full); 319 transfer_list_remove_finished(&instance->transfers_interrupt); 320 transfer_list_remove_finished(&instance->transfers_control_slow); 321 transfer_list_remove_finished(&instance->transfers_control_full); 322 transfer_list_remove_finished(&instance->transfers_bulk_full); 285 323 } 286 324 /*----------------------------------------------------------------------------*/ … … 291 329 assert(instance); 292 330 293 while (1) {331 while (1) { 294 332 uint16_t status = pio_read_16(&instance->registers->usbsts); 333 if (status != 0) 334 usb_log_debug2("UHCI status: %x.\n", status); 335 status |= 1; 295 336 uhci_interrupt(instance, status); 296 async_usleep(UHCI_CLEANER_TIMEOUT); 337 pio_write_16(&instance->registers->usbsts, 0x1f); 338 async_usleep(UHCI_CLEANER_TIMEOUT * 5); 297 339 } 298 340 return EOK; … … 303 345 uhci_t *instance = (uhci_t*)arg; 304 346 assert(instance); 347 348 #define QH(queue) \ 349 instance->transfers_##queue.queue_head 350 305 351 while (1) { 306 352 const uint16_t cmd = pio_read_16(&instance->registers->usbcmd); 307 353 const uint16_t sts = pio_read_16(&instance->registers->usbsts); 308 const uint16_t intr = pio_read_16(&instance->registers->usbintr); 309 usb_log_debug("Command: %X Status: %X Interrupts: %x\n", 310 cmd, sts, intr); 311 312 uintptr_t frame_list = pio_read_32(&instance->registers->flbaseadd); 354 const uint16_t intr = 355 pio_read_16(&instance->registers->usbintr); 356 357 if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) { 358 usb_log_debug2("Command: %X Status: %X Intr: %x\n", 359 cmd, sts, intr); 360 } 361 362 uintptr_t frame_list = 363 pio_read_32(&instance->registers->flbaseadd) & ~0xfff; 313 364 if (frame_list != addr_to_phys(instance->frame_list)) { 314 365 usb_log_debug("Framelist address: %p vs. %p.\n", 315 frame_list, addr_to_phys(instance->frame_list)); 316 } 366 frame_list, addr_to_phys(instance->frame_list)); 367 } 368 317 369 int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff; 318 370 usb_log_debug2("Framelist item: %d \n", frnum ); 319 371 320 queue_head_t* qh = instance->transfers_interrupt.queue_head;321 322 if ( (instance->frame_list[frnum] & (~0xf)) != (uintptr_t)addr_to_phys(qh)) {372 uintptr_t expected_pa = instance->frame_list[frnum] & (~0xf); 373 uintptr_t real_pa = addr_to_phys(QH(interrupt)); 374 if (expected_pa != real_pa) { 323 375 usb_log_debug("Interrupt QH: %p vs. %p.\n", 324 instance->frame_list[frnum] & (~0xf), addr_to_phys(qh)); 325 } 326 327 if ((qh->next_queue & (~0xf)) 328 != (uintptr_t)addr_to_phys(instance->transfers_control_slow.queue_head)) { 329 usb_log_debug("Control Slow QH: %p vs. %p.\n", qh->next_queue & (~0xf), 330 addr_to_phys(instance->transfers_control_slow.queue_head)); 331 } 332 qh = instance->transfers_control_slow.queue_head; 333 334 if ((qh->next_queue & (~0xf)) 335 != (uintptr_t)addr_to_phys(instance->transfers_control_full.queue_head)) { 336 usb_log_debug("Control Full QH: %p vs. %p.\n", qh->next_queue & (~0xf), 337 addr_to_phys(instance->transfers_control_full.queue_head));\ 338 } 339 qh = instance->transfers_control_full.queue_head; 340 341 if ((qh->next_queue & (~0xf)) 342 != (uintptr_t)addr_to_phys(instance->transfers_bulk_full.queue_head)) { 343 usb_log_debug("Bulk QH: %p vs. %p.\n", qh->next_queue & (~0xf), 344 addr_to_phys(instance->transfers_bulk_full.queue_head)); 345 } 346 /* 347 uint16_t cmd = pio_read_16(&instance->registers->usbcmd); 348 cmd |= UHCI_CMD_RUN_STOP; 349 pio_write_16(&instance->registers->usbcmd, cmd); 350 */ 376 expected_pa, real_pa); 377 } 378 379 expected_pa = QH(interrupt)->next_queue & (~0xf); 380 real_pa = addr_to_phys(QH(control_slow)); 381 if (expected_pa != real_pa) { 382 usb_log_debug("Control Slow QH: %p vs. %p.\n", 383 expected_pa, real_pa); 384 } 385 386 expected_pa = QH(control_slow)->next_queue & (~0xf); 387 real_pa = addr_to_phys(QH(control_full)); 388 if (expected_pa != real_pa) { 389 usb_log_debug("Control Full QH: %p vs. %p.\n", 390 expected_pa, real_pa); 391 } 392 393 expected_pa = QH(control_full)->next_queue & (~0xf); 394 real_pa = addr_to_phys(QH(bulk_full)); 395 if (expected_pa != real_pa ) { 396 usb_log_debug("Bulk QH: %p vs. %p.\n", 397 expected_pa, real_pa); 398 } 351 399 async_usleep(UHCI_DEBUGER_TIMEOUT); 352 400 } 353 401 return 0; 402 #undef QH 354 403 } 355 404 /*----------------------------------------------------------------------------*/ 356 405 bool allowed_usb_packet( 357 bool low_speed, usb_transfer_type_t transfer, size_t size)406 bool low_speed, usb_transfer_type_t transfer, size_t size) 358 407 { 359 408 /* see USB specification chapter 5.5-5.8 for magic numbers used here */ 360 switch(transfer) { 361 case USB_TRANSFER_ISOCHRONOUS: 362 return (!low_speed && size < 1024); 363 case USB_TRANSFER_INTERRUPT: 364 return size <= (low_speed ? 8 : 64); 365 case USB_TRANSFER_CONTROL: /* device specifies its own max size */ 366 return (size <= (low_speed ? 8 : 64)); 367 case USB_TRANSFER_BULK: /* device specifies its own max size */ 368 return (!low_speed && size <= 64); 409 switch(transfer) 410 { 411 case USB_TRANSFER_ISOCHRONOUS: 412 return (!low_speed && size < 1024); 413 case USB_TRANSFER_INTERRUPT: 414 return size <= (low_speed ? 8 : 64); 415 case USB_TRANSFER_CONTROL: /* device specifies its own max size */ 416 return (size <= (low_speed ? 8 : 64)); 417 case USB_TRANSFER_BULK: /* device specifies its own max size */ 418 return (!low_speed && size <= 64); 369 419 } 370 420 return false; -
uspace/drv/uhci-hcd/uhci.h
rdff940f8 r8c877b2 41 41 #include <ddi.h> 42 42 43 #include <usb/addrkeep.h>44 43 #include <usbhc_iface.h> 45 44 45 #include "batch.h" 46 46 #include "transfer_list.h" 47 #include " batch.h"47 #include "utils/device_keeper.h" 48 48 49 49 typedef struct uhci_regs { … … 82 82 83 83 typedef struct uhci { 84 usb_address_keeping_t address_manager; 84 device_keeper_t device_manager; 85 85 86 volatile regs_t *registers; 86 87 -
uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c
rdff940f8 r8c877b2 39 39 40 40 void transfer_descriptor_init(transfer_descriptor_t *instance, 41 int error_count, size_t size, bool toggle, bool isochronous, 41 int error_count, size_t size, bool toggle, bool isochronous, bool low_speed, 42 42 usb_target_t target, int pid, void *buffer, transfer_descriptor_t *next) 43 43 { … … 50 50 instance->status = 0 51 51 | ((error_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS) 52 | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0) 52 53 | TD_STATUS_ERROR_ACTIVE; 53 54 … … 66 67 } 67 68 68 usb_log_ info("Created TD: %X:%X:%X:%X(%p).\n",69 usb_log_debug2("Created TD: %X:%X:%X:%X(%p).\n", 69 70 instance->next, instance->status, instance->device, 70 71 instance->buffer_ptr, buffer); 71 #if 072 if (size) {73 unsigned char * buff = buffer;74 uhci_print_verbose("TD Buffer dump(%p-%dB): ", buffer, size);75 unsigned i = 0;76 /* TODO: Verbose? */77 for (; i < size; ++i) {78 printf((i & 1) ? "%x " : "%x", buff[i]);79 }80 printf("\n");81 }82 #endif83 72 } 84 73 /*----------------------------------------------------------------------------*/ … … 88 77 89 78 if ((instance->status & TD_STATUS_ERROR_STALLED) != 0) 90 return E IO;79 return ESTALL; 91 80 92 81 if ((instance->status & TD_STATUS_ERROR_CRC) != 0) 93 return E AGAIN;82 return EBADCHECKSUM; 94 83 95 84 if ((instance->status & TD_STATUS_ERROR_BUFFER) != 0) -
uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h
rdff940f8 r8c877b2 92 92 93 93 void transfer_descriptor_init(transfer_descriptor_t *instance, 94 int error_count, size_t size, bool toggle, bool isochronous, 94 int error_count, size_t size, bool toggle, bool isochronous, bool low_speed, 95 95 usb_target_t target, int pid, void *buffer, transfer_descriptor_t * next); 96 96
Note:
See TracChangeset
for help on using the changeset viewer.
