Changeset e1dbcbc in mainline for uspace/drv/ohci
- Timestamp:
- 2011-04-29T13:43:01Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/fix-logger-deadlock, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- a81a1d09
- Parents:
- 380e0364 (diff), f19f1b7 (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/ohci
- Files:
-
- 1 added
- 18 edited
- 3 moved
-
Makefile (modified) (2 diffs)
-
batch.c (modified) (13 diffs)
-
batch.h (modified) (1 diff)
-
endpoint_list.c (moved) (moved from uspace/drv/ohci/transfer_list.c ) (7 diffs)
-
endpoint_list.h (moved) (moved from uspace/drv/ohci/transfer_list.h ) (4 diffs)
-
hc.c (modified) (10 diffs)
-
hc.h (modified) (3 diffs)
-
hcd_endpoint.c (added)
-
hcd_endpoint.h (moved) (moved from uspace/drv/vhc/devices.h ) (2 diffs)
-
hw_struct/endpoint_descriptor.c (modified) (1 diff)
-
hw_struct/endpoint_descriptor.h (modified) (4 diffs)
-
hw_struct/hcca.h (modified) (1 diff)
-
hw_struct/transfer_descriptor.c (modified) (1 diff)
-
hw_struct/transfer_descriptor.h (modified) (4 diffs)
-
iface.c (modified) (13 diffs)
-
ohci.c (modified) (1 diff)
-
ohci.ma (modified) (1 diff)
-
ohci_regs.h (modified) (2 diffs)
-
pci.c (modified) (1 diff)
-
root_hub.c (modified) (17 diffs)
-
root_hub.h (modified) (1 diff)
-
utils/malloc32.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/ohci/Makefile
r380e0364 re1dbcbc 34 34 SOURCES = \ 35 35 batch.c \ 36 endpoint_list.c \ 36 37 hc.c \ 38 hcd_endpoint.c \ 37 39 iface.c \ 38 40 main.c \ … … 40 42 pci.c \ 41 43 root_hub.c \ 42 transfer_list.c \43 44 hw_struct/endpoint_descriptor.c \ 44 45 hw_struct/transfer_descriptor.c -
uspace/drv/ohci/batch.c
r380e0364 re1dbcbc 39 39 40 40 #include "batch.h" 41 #include "hcd_endpoint.h" 41 42 #include "utils/malloc32.h" 42 43 #include "hw_struct/endpoint_descriptor.h" 43 44 #include "hw_struct/transfer_descriptor.h" 44 45 45 typedef struct ohci_ batch {46 typedef struct ohci_transfer_batch { 46 47 ed_t *ed; 47 td_t * tds;48 td_t **tds; 48 49 size_t td_count; 49 } ohci_batch_t; 50 50 size_t leave_td; 51 char *device_buffer; 52 } ohci_transfer_batch_t; 53 54 static void ohci_transfer_batch_dispose(void *ohci_batch) 55 { 56 ohci_transfer_batch_t *instance = ohci_batch; 57 if (!instance) 58 return; 59 free32(instance->device_buffer); 60 unsigned i = 0; 61 if (instance->tds) { 62 for (; i< instance->td_count; ++i) { 63 if (i != instance->leave_td) 64 free32(instance->tds[i]); 65 } 66 free(instance->tds); 67 } 68 free(instance); 69 } 70 /*----------------------------------------------------------------------------*/ 51 71 static void batch_control(usb_transfer_batch_t *instance, 52 72 usb_direction_t data_dir, usb_direction_t status_dir); 53 static void batch_call_in_and_dispose(usb_transfer_batch_t *instance); 54 static void batch_call_out_and_dispose(usb_transfer_batch_t *instance); 55 56 #define DEFAULT_ERROR_COUNT 3 73 static void batch_data(usb_transfer_batch_t *instance); 74 /*----------------------------------------------------------------------------*/ 57 75 usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep, 58 76 char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size, … … 64 82 usb_log_error(message); \ 65 83 if (instance) { \ 66 batch_dispose(instance); \84 usb_transfer_batch_dispose(instance); \ 67 85 } \ 68 86 return NULL; \ … … 72 90 CHECK_NULL_DISPOSE_RETURN(instance, 73 91 "Failed to allocate batch instance.\n"); 74 usb_target_t target = 75 { .address = ep->address, .endpoint = ep->endpoint }; 76 usb_transfer_batch_init(instance, target, ep->transfer_type, ep->speed, 77 ep->max_packet_size, buffer, NULL, buffer_size, NULL, setup_size, 78 func_in, func_out, arg, fun, ep, NULL); 79 80 ohci_batch_t *data = malloc(sizeof(ohci_batch_t)); 92 usb_transfer_batch_init(instance, ep, buffer, NULL, buffer_size, 93 NULL, setup_size, func_in, func_out, arg, fun, NULL, 94 ohci_transfer_batch_dispose); 95 96 hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep); 97 assert(hcd_ep); 98 99 ohci_transfer_batch_t *data = calloc(sizeof(ohci_transfer_batch_t), 1); 81 100 CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n"); 82 bzero(data, sizeof(ohci_batch_t));83 101 instance->private_data = data; 84 102 85 /* we needs + 1 transfer descriptor as the last one won't be executed */ 86 data->td_count = 1 + 103 data->td_count = 87 104 ((buffer_size + OHCI_TD_MAX_TRANSFER - 1) / OHCI_TD_MAX_TRANSFER); 88 105 if (ep->transfer_type == USB_TRANSFER_CONTROL) { … … 90 107 } 91 108 92 data->tds = malloc32(sizeof(td_t) * data->td_count); 109 /* we need one extra place for td that is currently assigned to hcd_ep*/ 110 data->tds = calloc(sizeof(td_t*), data->td_count + 1); 93 111 CHECK_NULL_DISPOSE_RETURN(data->tds, 94 112 "Failed to allocate transfer descriptors.\n"); 95 bzero(data->tds, sizeof(td_t) * data->td_count); 96 97 data->ed = malloc32(sizeof(ed_t)); 98 CHECK_NULL_DISPOSE_RETURN(data->ed, 99 "Failed to allocate endpoint descriptor.\n"); 100 101 if (buffer_size > 0) { 102 instance->transport_buffer = malloc32(buffer_size); 103 CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer, 113 114 data->tds[0] = hcd_ep->td; 115 data->leave_td = 0; 116 unsigned i = 1; 117 for (; i <= data->td_count; ++i) { 118 data->tds[i] = malloc32(sizeof(td_t)); 119 CHECK_NULL_DISPOSE_RETURN(data->tds[i], 120 "Failed to allocate TD %d.\n", i ); 121 } 122 123 data->ed = hcd_ep->ed; 124 125 if (setup_size + buffer_size > 0) { 126 data->device_buffer = malloc32(setup_size + buffer_size); 127 CHECK_NULL_DISPOSE_RETURN(data->device_buffer, 104 128 "Failed to allocate device accessible buffer.\n"); 105 } 106 107 if (setup_size > 0) { 108 instance->setup_buffer = malloc32(setup_size); 109 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer, 110 "Failed to allocate device accessible setup buffer.\n"); 129 instance->setup_buffer = data->device_buffer; 130 instance->data_buffer = data->device_buffer + setup_size; 111 131 memcpy(instance->setup_buffer, setup_buffer, setup_size); 112 132 } … … 115 135 } 116 136 /*----------------------------------------------------------------------------*/ 117 void batch_dispose(usb_transfer_batch_t *instance)118 {119 assert(instance);120 ohci_batch_t *data = instance->private_data;121 assert(data);122 free32(data->ed);123 free32(data->tds);124 free32(instance->setup_buffer);125 free32(instance->transport_buffer);126 free(data);127 free(instance);128 }129 /*----------------------------------------------------------------------------*/130 137 bool batch_is_complete(usb_transfer_batch_t *instance) 131 138 { 132 139 assert(instance); 133 ohci_ batch_t *data = instance->private_data;134 assert(data); 135 size_t tds = data->td_count - 1;136 usb_log_debug 2("Batch(%p) checking %dtd(s) for completion.\n",140 ohci_transfer_batch_t *data = instance->private_data; 141 assert(data); 142 size_t tds = data->td_count; 143 usb_log_debug("Batch(%p) checking %zu td(s) for completion.\n", 137 144 instance, tds); 145 usb_log_debug("ED: %x:%x:%x:%x.\n", 146 data->ed->status, data->ed->td_head, data->ed->td_tail, 147 data->ed->next); 138 148 size_t i = 0; 149 instance->transfered_size = instance->buffer_size; 139 150 for (; i < tds; ++i) { 140 if (!td_is_finished(&data->tds[i])) 151 assert(data->tds[i] != NULL); 152 usb_log_debug("TD %zu: %x:%x:%x:%x.\n", i, 153 data->tds[i]->status, data->tds[i]->cbp, data->tds[i]->next, 154 data->tds[i]->be); 155 if (!td_is_finished(data->tds[i])) { 141 156 return false; 142 instance->error = td_error(&data->tds[i]); 143 /* FIXME: calculate real transfered size */ 144 instance->transfered_size = instance->buffer_size; 157 } 158 instance->error = td_error(data->tds[i]); 145 159 if (instance->error != EOK) { 146 usb_log_debug("Batch(%p) found error TD(%d):%x.\n", 147 instance, i, data->tds[i].status); 148 return true; 149 // endpoint_toggle_set(instance->ep, 160 usb_log_debug("Batch(%p) found error TD(%zu):%x.\n", 161 instance, i, data->tds[i]->status); 162 /* Make sure TD queue is empty (one TD), 163 * ED should be marked as halted */ 164 data->ed->td_tail = 165 (data->ed->td_head & ED_TDTAIL_PTR_MASK); 166 ++i; 167 break; 150 168 } 151 169 } 170 data->leave_td = i; 171 assert(data->leave_td <= data->td_count); 172 hcd_endpoint_t *hcd_ep = hcd_endpoint_get(instance->ep); 173 assert(hcd_ep); 174 hcd_ep->td = data->tds[i]; 175 if (i > 0) 176 instance->transfered_size -= td_remain_size(data->tds[i - 1]); 177 178 /* Clear possible ED HALT */ 179 data->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG; 180 uint32_t pa = addr_to_phys(hcd_ep->td); 181 assert(pa == (data->ed->td_head & ED_TDHEAD_PTR_MASK)); 182 assert(pa == (data->ed->td_tail & ED_TDTAIL_PTR_MASK)); 183 152 184 return true; 153 185 } 154 186 /*----------------------------------------------------------------------------*/ 187 void batch_commit(usb_transfer_batch_t *instance) 188 { 189 assert(instance); 190 ohci_transfer_batch_t *data = instance->private_data; 191 assert(data); 192 ed_set_end_td(data->ed, data->tds[data->td_count]); 193 } 194 /*----------------------------------------------------------------------------*/ 155 195 void batch_control_write(usb_transfer_batch_t *instance) 156 196 { 157 197 assert(instance); 158 198 /* We are data out, we are supposed to provide data */ 159 memcpy(instance->transport_buffer, instance->buffer, 160 instance->buffer_size); 161 instance->next_step = batch_call_out_and_dispose; 199 memcpy(instance->data_buffer, instance->buffer, instance->buffer_size); 200 instance->next_step = usb_transfer_batch_call_out_and_dispose; 162 201 batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN); 163 202 usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance); … … 167 206 { 168 207 assert(instance); 169 instance->next_step = batch_call_in_and_dispose;208 instance->next_step = usb_transfer_batch_call_in_and_dispose; 170 209 batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT); 171 210 usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance); … … 175 214 { 176 215 assert(instance); 177 assert(instance->direction == USB_DIRECTION_IN); 178 instance->next_step = batch_call_in_and_dispose; 179 /* TODO: implement */ 216 instance->next_step = usb_transfer_batch_call_in_and_dispose; 217 batch_data(instance); 180 218 usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance); 181 219 } … … 184 222 { 185 223 assert(instance); 186 assert(instance->direction == USB_DIRECTION_OUT);187 224 /* We are data out, we are supposed to provide data */ 188 memcpy(instance->transport_buffer, instance->buffer, 189 instance->buffer_size); 190 instance->next_step = batch_call_out_and_dispose; 191 /* TODO: implement */ 225 memcpy(instance->data_buffer, instance->buffer, instance->buffer_size); 226 instance->next_step = usb_transfer_batch_call_out_and_dispose; 227 batch_data(instance); 192 228 usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance); 193 229 } … … 196 232 { 197 233 assert(instance); 198 instance->direction = USB_DIRECTION_IN; 199 instance->next_step = batch_call_in_and_dispose; 200 /* TODO: implement */ 234 instance->next_step = usb_transfer_batch_call_in_and_dispose; 235 batch_data(instance); 201 236 usb_log_debug("Batch(%p) BULK IN initialized.\n", instance); 202 237 } … … 205 240 { 206 241 assert(instance); 207 instance->direction = USB_DIRECTION_IN; 208 instance->next_step = batch_call_in_and_dispose; 209 /* TODO: implement */ 210 usb_log_debug("Batch(%p) BULK IN initialized.\n", instance); 242 /* We are data out, we are supposed to provide data */ 243 memcpy(instance->data_buffer, instance->buffer, instance->buffer_size); 244 instance->next_step = usb_transfer_batch_call_out_and_dispose; 245 batch_data(instance); 246 usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance); 211 247 } 212 248 /*----------------------------------------------------------------------------*/ … … 214 250 { 215 251 assert(instance); 216 ohci_ batch_t *data = instance->private_data;252 ohci_transfer_batch_t *data = instance->private_data; 217 253 assert(data); 218 254 return data->ed; … … 223 259 { 224 260 assert(instance); 225 ohci_batch_t *data = instance->private_data; 226 assert(data); 227 ed_init(data->ed, instance->ep); 228 ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]); 229 usb_log_debug("Created ED(%p): %x:%x:%x:%x.\n", data->ed, 261 ohci_transfer_batch_t *data = instance->private_data; 262 assert(data); 263 usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed, 230 264 data->ed->status, data->ed->td_tail, data->ed->td_head, 231 265 data->ed->next); 232 266 int toggle = 0; 233 267 /* setup stage */ 234 td_init( &data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,268 td_init(data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer, 235 269 instance->setup_size, toggle); 236 td_set_next( &data->tds[0], &data->tds[1]);237 usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0] .status,238 data->tds[0] .cbp, data->tds[0].next, data->tds[0].be);270 td_set_next(data->tds[0], data->tds[1]); 271 usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0]->status, 272 data->tds[0]->cbp, data->tds[0]->next, data->tds[0]->be); 239 273 240 274 /* data stage */ 241 275 size_t td_current = 1; 242 276 size_t remain_size = instance->buffer_size; 243 char * transfer_buffer = instance->transport_buffer;277 char *buffer = instance->data_buffer; 244 278 while (remain_size > 0) { 245 279 size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ? … … 247 281 toggle = 1 - toggle; 248 282 249 td_init( &data->tds[td_current], data_dir, transfer_buffer,283 td_init(data->tds[td_current], data_dir, buffer, 250 284 transfer_size, toggle); 251 td_set_next( &data->tds[td_current], &data->tds[td_current + 1]);285 td_set_next(data->tds[td_current], data->tds[td_current + 1]); 252 286 usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n", 253 data->tds[td_current] .status, data->tds[td_current].cbp,254 data->tds[td_current] .next, data->tds[td_current].be);255 256 transfer_buffer += transfer_size;287 data->tds[td_current]->status, data->tds[td_current]->cbp, 288 data->tds[td_current]->next, data->tds[td_current]->be); 289 290 buffer += transfer_size; 257 291 remain_size -= transfer_size; 258 assert(td_current < data->td_count - 2);292 assert(td_current < data->td_count - 1); 259 293 ++td_current; 260 294 } 261 295 262 296 /* status stage */ 263 assert(td_current == data->td_count - 2); 264 td_init(&data->tds[td_current], status_dir, NULL, 0, 1); 297 assert(td_current == data->td_count - 1); 298 td_init(data->tds[td_current], status_dir, NULL, 0, 1); 299 td_set_next(data->tds[td_current], data->tds[td_current + 1]); 265 300 usb_log_debug("Created STATUS TD: %x:%x:%x:%x.\n", 266 data->tds[td_current].status, data->tds[td_current].cbp, 267 data->tds[td_current].next, data->tds[td_current].be); 268 } 269 /*----------------------------------------------------------------------------*/ 270 /** Helper function calls callback and correctly disposes of batch structure. 271 * 272 * @param[in] instance Batch structure to use. 273 */ 274 void batch_call_in_and_dispose(usb_transfer_batch_t *instance) 275 { 276 assert(instance); 277 usb_transfer_batch_call_in(instance); 278 batch_dispose(instance); 279 } 280 /*----------------------------------------------------------------------------*/ 281 /** Helper function calls callback and correctly disposes of batch structure. 282 * 283 * @param[in] instance Batch structure to use. 284 */ 285 void batch_call_out_and_dispose(usb_transfer_batch_t *instance) 286 { 287 assert(instance); 288 usb_transfer_batch_call_out(instance); 289 batch_dispose(instance); 301 data->tds[td_current]->status, data->tds[td_current]->cbp, 302 data->tds[td_current]->next, data->tds[td_current]->be); 303 } 304 /*----------------------------------------------------------------------------*/ 305 void batch_data(usb_transfer_batch_t *instance) 306 { 307 assert(instance); 308 ohci_transfer_batch_t *data = instance->private_data; 309 assert(data); 310 usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed, 311 data->ed->status, data->ed->td_tail, data->ed->td_head, 312 data->ed->next); 313 314 size_t td_current = 0; 315 size_t remain_size = instance->buffer_size; 316 char *buffer = instance->data_buffer; 317 while (remain_size > 0) { 318 size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ? 319 OHCI_TD_MAX_TRANSFER : remain_size; 320 321 td_init(data->tds[td_current], instance->ep->direction, 322 buffer, transfer_size, -1); 323 td_set_next(data->tds[td_current], data->tds[td_current + 1]); 324 usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n", 325 data->tds[td_current]->status, data->tds[td_current]->cbp, 326 data->tds[td_current]->next, data->tds[td_current]->be); 327 328 buffer += transfer_size; 329 remain_size -= transfer_size; 330 assert(td_current < data->td_count); 331 ++td_current; 332 } 290 333 } 291 334 /** -
uspace/drv/ohci/batch.h
r380e0364 re1dbcbc 50 50 void *arg); 51 51 52 void batch_dispose(usb_transfer_batch_t *instance);52 bool batch_is_complete(usb_transfer_batch_t *instance); 53 53 54 bool batch_is_complete(usb_transfer_batch_t *instance);54 void batch_commit(usb_transfer_batch_t *instance); 55 55 56 56 void batch_control_write(usb_transfer_batch_t *instance); -
uspace/drv/ohci/endpoint_list.c
r380e0364 re1dbcbc 35 35 #include <usb/debug.h> 36 36 37 #include "transfer_list.h" 38 39 static void transfer_list_remove_batch( 40 transfer_list_t *instance, usb_transfer_batch_t *batch); 41 /*----------------------------------------------------------------------------*/ 37 #include "endpoint_list.h" 38 42 39 /** Initialize transfer list structures. 43 40 * … … 48 45 * Allocates memory for internal qh_t structure. 49 46 */ 50 int transfer_list_init(transfer_list_t *instance, const char *name)47 int endpoint_list_init(endpoint_list_t *instance, const char *name) 51 48 { 52 49 assert(instance); … … 58 55 } 59 56 instance->list_head_pa = addr_to_phys(instance->list_head); 60 usb_log_debug2("Transfer list %s setup with ED: %p( %p).\n",57 usb_log_debug2("Transfer list %s setup with ED: %p(0x%0" PRIx32 ")).\n", 61 58 name, instance->list_head, instance->list_head_pa); 62 59 63 60 ed_init(instance->list_head, NULL); 64 list_initialize(&instance-> batch_list);61 list_initialize(&instance->endpoint_list); 65 62 fibril_mutex_initialize(&instance->guard); 66 63 return EOK; … … 75 72 * Does not check whether this replaces an existing list . 76 73 */ 77 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next)74 void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next) 78 75 { 79 76 assert(instance); 80 77 assert(next); 81 /* Set both queue_head.next to point to the follower */82 78 ed_append_ed(instance->list_head, next->list_head); 83 79 } 84 80 /*----------------------------------------------------------------------------*/ 85 /** Submit transfer batchto the list and queue.86 * 87 * @param[in] instance List to use. 88 * @param[in] batch Transfer batchto submit.89 * @return Error code 90 * 91 * The batchis added to the end of the list and queue.92 */ 93 void transfer_list_add_batch(94 transfer_list_t *instance, usb_transfer_batch_t *batch) 95 { 96 assert( instance);97 assert(batch);98 usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch);81 /** Submit transfer endpoint to the list and queue. 82 * 83 * @param[in] instance List to use. 84 * @param[in] endpoint Transfer endpoint to submit. 85 * @return Error code 86 * 87 * The endpoint is added to the end of the list and queue. 88 */ 89 void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep) 90 { 91 assert(instance); 92 assert(hcd_ep); 93 usb_log_debug2("Queue %s: Adding endpoint(%p).\n", 94 instance->name, hcd_ep); 99 95 100 96 fibril_mutex_lock(&instance->guard); … … 102 98 ed_t *last_ed = NULL; 103 99 /* Add to the hardware queue. */ 104 if (list_empty(&instance-> batch_list)) {100 if (list_empty(&instance->endpoint_list)) { 105 101 /* There is nothing scheduled */ 106 102 last_ed = instance->list_head; 107 103 } else { 108 104 /* There is something scheduled */ 109 usb_transfer_batch_t *last = list_get_instance(110 instance-> batch_list.prev, usb_transfer_batch_t, link);111 last_ed = batch_ed(last);105 hcd_endpoint_t *last = list_get_instance( 106 instance->endpoint_list.prev, hcd_endpoint_t, link); 107 last_ed = last->ed; 112 108 } 113 109 /* keep link */ 114 batch_ed(batch)->next = last_ed->next;115 ed_append_ed(last_ed, batch_ed(batch));110 hcd_ep->ed->next = last_ed->next; 111 ed_append_ed(last_ed, hcd_ep->ed); 116 112 117 113 asm volatile ("": : :"memory"); 118 114 119 115 /* Add to the driver list */ 120 list_append(& batch->link, &instance->batch_list);121 122 usb_transfer_batch_t *first = list_get_instance(123 instance-> batch_list.next, usb_transfer_batch_t, link);124 usb_log_debug(" Batch(%p) added to list %s, first is %p(%p).\n",125 batch, instance->name, first, batch_ed(first));116 list_append(&hcd_ep->link, &instance->endpoint_list); 117 118 hcd_endpoint_t *first = list_get_instance( 119 instance->endpoint_list.next, hcd_endpoint_t, link); 120 usb_log_debug("HCD EP(%p) added to list %s, first is %p(%p).\n", 121 hcd_ep, instance->name, first, first->ed); 126 122 if (last_ed == instance->list_head) { 127 usb_log_debug2("%s head ED: %x:%x:%x:%x.\n", instance->name, 128 last_ed->status, last_ed->td_tail, last_ed->td_head, 129 last_ed->next); 130 } 131 fibril_mutex_unlock(&instance->guard); 132 } 133 /*----------------------------------------------------------------------------*/ 134 /** Create list for finished batches. 123 usb_log_debug2("%s head ED(%p-0x%0" PRIx32 "): %x:%x:%x:%x.\n", 124 instance->name, last_ed, instance->list_head_pa, 125 last_ed->status, last_ed->td_tail, last_ed->td_head, 126 last_ed->next); 127 } 128 fibril_mutex_unlock(&instance->guard); 129 } 130 /*----------------------------------------------------------------------------*/ 131 #if 0 132 /** Create list for finished endpoints. 135 133 * 136 134 * @param[in] instance List to use. 137 135 * @param[in] done list to fill 138 136 */ 139 void transfer_list_remove_finished(transfer_list_t *instance, link_t *done)137 void endpoint_list_remove_finished(endpoint_list_t *instance, link_t *done) 140 138 { 141 139 assert(instance); … … 143 141 144 142 fibril_mutex_lock(&instance->guard); 145 link_t *current = instance->batch_list.next; 146 while (current != &instance->batch_list) { 143 usb_log_debug2("Checking list %s for completed endpointes(%d).\n", 144 instance->name, list_count(&instance->endpoint_list)); 145 link_t *current = instance->endpoint_list.next; 146 while (current != &instance->endpoint_list) { 147 147 link_t *next = current->next; 148 usb_transfer_batch_t *batch=149 list_get_instance(current, usb_transfer_batch_t, link);150 151 if ( batch_is_complete(batch)) {148 hcd_endpoint_t *endpoint = 149 list_get_instance(current, hcd_endpoint_t, link); 150 151 if (endpoint_is_complete(endpoint)) { 152 152 /* Save for post-processing */ 153 transfer_list_remove_batch(instance, batch);153 endpoint_list_remove_endpoint(instance, endpoint); 154 154 list_append(current, done); 155 155 } … … 159 159 } 160 160 /*----------------------------------------------------------------------------*/ 161 /** Walk the list and abort all batches. 162 * 163 * @param[in] instance List to use. 164 */ 165 void transfer_list_abort_all(transfer_list_t *instance) 166 { 167 fibril_mutex_lock(&instance->guard); 168 while (!list_empty(&instance->batch_list)) { 169 link_t *current = instance->batch_list.next; 170 usb_transfer_batch_t *batch = 171 list_get_instance(current, usb_transfer_batch_t, link); 172 transfer_list_remove_batch(instance, batch); 173 usb_transfer_batch_finish_error(batch, EIO); 174 } 175 fibril_mutex_unlock(&instance->guard); 176 } 177 /*----------------------------------------------------------------------------*/ 178 /** Remove a transfer batch from the list and queue. 179 * 180 * @param[in] instance List to use. 181 * @param[in] batch Transfer batch to remove. 161 /** Walk the list and abort all endpointes. 162 * 163 * @param[in] instance List to use. 164 */ 165 void endpoint_list_abort_all(endpoint_list_t *instance) 166 { 167 fibril_mutex_lock(&instance->guard); 168 while (!list_empty(&instance->endpoint_list)) { 169 link_t *current = instance->endpoint_list.next; 170 hcd_endpoint_t *endpoint = 171 list_get_instance(current, hcd_endpoint_t, link); 172 endpoint_list_remove_endpoint(instance, endpoint); 173 hcd_endpoint_finish_error(endpoint, EIO); 174 } 175 fibril_mutex_unlock(&instance->guard); 176 } 177 #endif 178 /*----------------------------------------------------------------------------*/ 179 /** Remove a transfer endpoint from the list and queue. 180 * 181 * @param[in] instance List to use. 182 * @param[in] endpoint Transfer endpoint to remove. 182 183 * @return Error code 183 184 * 184 185 * Does not lock the transfer list, caller is responsible for that. 185 186 */ 186 void transfer_list_remove_batch( 187 transfer_list_t *instance, usb_transfer_batch_t *batch) 187 void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep) 188 188 { 189 189 assert(instance); 190 190 assert(instance->list_head); 191 assert(batch); 192 assert(batch_ed(batch)); 193 assert(fibril_mutex_is_locked(&instance->guard)); 191 assert(hcd_ep); 192 assert(hcd_ep->ed); 193 194 fibril_mutex_lock(&instance->guard); 194 195 195 196 usb_log_debug2( 196 "Queue %s: removing batch(%p).\n", instance->name, batch);197 "Queue %s: removing endpoint(%p).\n", instance->name, hcd_ep); 197 198 198 199 const char *qpos = NULL; 200 ed_t *prev_ed; 199 201 /* Remove from the hardware queue */ 200 if (instance-> batch_list.next == &batch->link) {202 if (instance->endpoint_list.next == &hcd_ep->link) { 201 203 /* I'm the first one here */ 202 assert((instance->list_head->next & ED_NEXT_PTR_MASK) 203 == addr_to_phys(batch_ed(batch))); 204 instance->list_head->next = batch_ed(batch)->next; 204 prev_ed = instance->list_head; 205 205 qpos = "FIRST"; 206 206 } else { 207 usb_transfer_batch_t *prev = 208 list_get_instance( 209 batch->link.prev, usb_transfer_batch_t, link); 210 assert((batch_ed(prev)->next & ED_NEXT_PTR_MASK) 211 == addr_to_phys(batch_ed(batch))); 212 batch_ed(prev)->next = batch_ed(batch)->next; 207 hcd_endpoint_t *prev = 208 list_get_instance(hcd_ep->link.prev, hcd_endpoint_t, link); 209 prev_ed = prev->ed; 213 210 qpos = "NOT FIRST"; 214 211 } 212 assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(hcd_ep->ed)); 213 prev_ed->next = hcd_ep->ed->next; 214 215 215 asm volatile ("": : :"memory"); 216 usb_log_debug("Batch(%p) removed (%s) from %s, next %x.\n", 217 batch, qpos, instance->name, batch_ed(batch)->next); 218 219 /* Remove from the batch list */ 220 list_remove(&batch->link); 216 usb_log_debug("HCD EP(%p) removed (%s) from %s, next %x.\n", 217 hcd_ep, qpos, instance->name, hcd_ep->ed->next); 218 219 /* Remove from the endpoint list */ 220 list_remove(&hcd_ep->link); 221 fibril_mutex_unlock(&instance->guard); 221 222 } 222 223 /** -
uspace/drv/ohci/endpoint_list.h
r380e0364 re1dbcbc 32 32 * @brief OHCI driver transfer list structure 33 33 */ 34 #ifndef DRV_OHCI_ TRANSFER_LIST_H35 #define DRV_OHCI_ TRANSFER_LIST_H34 #ifndef DRV_OHCI_ENDPOINT_LIST_H 35 #define DRV_OHCI_ENDPOINT_LIST_H 36 36 37 37 #include <fibril_synch.h> 38 38 39 #include " batch.h"39 #include "hcd_endpoint.h" 40 40 #include "hw_struct/endpoint_descriptor.h" 41 41 #include "utils/malloc32.h" 42 42 43 typedef struct transfer_list43 typedef struct endpoint_list 44 44 { 45 45 fibril_mutex_t guard; … … 47 47 uint32_t list_head_pa; 48 48 const char *name; 49 link_t batch_list;50 } transfer_list_t;49 link_t endpoint_list; 50 } endpoint_list_t; 51 51 52 52 /** Dispose transfer list structures. … … 56 56 * Frees memory for internal qh_t structure. 57 57 */ 58 static inline void transfer_list_fini(transfer_list_t *instance)58 static inline void endpoint_list_fini(endpoint_list_t *instance) 59 59 { 60 60 assert(instance); … … 62 62 } 63 63 64 int transfer_list_init(transfer_list_t *instance, const char *name);64 int endpoint_list_init(endpoint_list_t *instance, const char *name); 65 65 66 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);66 void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next); 67 67 68 void transfer_list_add_batch(transfer_list_t *instance, usb_transfer_batch_t *batch);68 void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep); 69 69 70 void transfer_list_remove_finished(transfer_list_t *instance, link_t *done); 70 void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep); 71 #if 0 72 void endpoint_list_remove_finished(endpoint_list_t *instance, link_t *done); 71 73 72 void transfer_list_abort_all(transfer_list_t *instance); 74 void endpoint_list_abort_all(endpoint_list_t *instance); 75 #endif 73 76 #endif 74 77 /** -
uspace/drv/ohci/hc.c
r380e0364 re1dbcbc 43 43 44 44 #include "hc.h" 45 #include "hcd_endpoint.h" 45 46 46 47 static int interrupt_emulator(hc_t *instance); … … 55 56 assert(hub_fun); 56 57 58 int ret; 59 57 60 usb_address_t hub_address = 58 61 device_keeper_get_free_address(&instance->manager, USB_SPEED_FULL); 62 if (hub_address <= 0) { 63 usb_log_error("Failed to get OHCI root hub address.\n"); 64 return hub_address; 65 } 59 66 instance->rh.address = hub_address; 60 67 usb_device_keeper_bind( 61 68 &instance->manager, hub_address, hub_fun->handle); 62 69 63 endpoint_t *ep = malloc(sizeof(endpoint_t));64 assert(ep);65 i nt ret = endpoint_init(ep, hub_address, 0, USB_DIRECTION_BOTH,66 USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64);67 assert(ret == EOK);68 ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, 0);69 assert(ret == EOK);70 ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL, 71 USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0); 72 if (ret != EOK) { 73 usb_log_error("Failed to add OHCI rh endpoint 0.\n"); 74 usb_device_keeper_release(&instance->manager, hub_address); 75 return ret; 76 } 70 77 71 78 char *match_str = NULL; 79 /* DDF needs heap allocated string */ 72 80 ret = asprintf(&match_str, "usb&class=hub"); 73 // ret = (match_str == NULL) ? ret : EOK;74 81 if (ret < 0) { 75 82 usb_log_error( 76 83 "Failed(%d) to create root hub match-id string.\n", ret); 84 usb_device_keeper_release(&instance->manager, hub_address); 77 85 return ret; 78 86 } … … 80 88 ret = ddf_fun_add_match_id(hub_fun, match_str, 100); 81 89 if (ret != EOK) { 82 usb_log_error("Failed add createroot hub match-id.\n");90 usb_log_error("Failed add root hub match-id.\n"); 83 91 } 84 92 return ret; … … 101 109 ret, str_error(ret)); 102 110 103 instance->ddf_instance = fun;104 111 usb_device_keeper_init(&instance->manager); 105 112 ret = usb_endpoint_manager_init(&instance->ep_manager, 106 113 BANDWIDTH_AVAILABLE_USB11); 107 114 CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n", 108 ret,str_error(ret));115 str_error(ret)); 109 116 110 117 hc_gain_control(instance); 111 118 ret = hc_init_memory(instance); 112 CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures: %s.\n",113 ret,str_error(ret));119 CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures: %s.\n", 120 str_error(ret)); 114 121 hc_init_hw(instance); 115 116 rh_init(&instance->rh, dev, instance->registers); 122 fibril_mutex_initialize(&instance->guard); 123 124 rh_init(&instance->rh, instance->registers); 117 125 118 126 if (!interrupts) { … … 122 130 } 123 131 124 return EOK; 125 } 126 /*----------------------------------------------------------------------------*/ 127 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch) 128 { 129 assert(instance); 130 assert(batch); 131 132 /* check for root hub communication */ 133 if (batch->target.address == instance->rh.address) { 134 return rh_request(&instance->rh, batch); 135 } 136 137 transfer_list_add_batch( 138 instance->transfers[batch->transfer_type], batch); 139 140 switch (batch->transfer_type) { 132 list_initialize(&instance->pending_batches); 133 #undef CHECK_RET_RETURN 134 return EOK; 135 } 136 /*----------------------------------------------------------------------------*/ 137 int hc_add_endpoint( 138 hc_t *instance, usb_address_t address, usb_endpoint_t endpoint, 139 usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction, 140 size_t mps, size_t size, unsigned interval) 141 { 142 endpoint_t *ep = malloc(sizeof(endpoint_t)); 143 if (ep == NULL) 144 return ENOMEM; 145 int ret = 146 endpoint_init(ep, address, endpoint, direction, type, speed, mps); 147 if (ret != EOK) { 148 free(ep); 149 return ret; 150 } 151 152 hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep); 153 if (hcd_ep == NULL) { 154 endpoint_destroy(ep); 155 return ENOMEM; 156 } 157 158 ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size); 159 if (ret != EOK) { 160 hcd_endpoint_clear(ep); 161 endpoint_destroy(ep); 162 return ret; 163 } 164 165 /* Enqueue hcd_ep */ 166 switch (ep->transfer_type) { 141 167 case USB_TRANSFER_CONTROL: 142 168 instance->registers->control &= ~C_CLE; 169 endpoint_list_add_ep( 170 &instance->lists[ep->transfer_type], hcd_ep); 171 instance->registers->control_current = 0; 172 instance->registers->control |= C_CLE; 173 break; 174 case USB_TRANSFER_BULK: 175 instance->registers->control &= ~C_BLE; 176 endpoint_list_add_ep( 177 &instance->lists[ep->transfer_type], hcd_ep); 178 instance->registers->control |= C_BLE; 179 break; 180 case USB_TRANSFER_ISOCHRONOUS: 181 case USB_TRANSFER_INTERRUPT: 182 instance->registers->control &= (~C_PLE & ~C_IE); 183 endpoint_list_add_ep( 184 &instance->lists[ep->transfer_type], hcd_ep); 185 instance->registers->control |= C_PLE | C_IE; 186 break; 187 default: 188 break; 189 } 190 191 return EOK; 192 } 193 /*----------------------------------------------------------------------------*/ 194 int hc_remove_endpoint(hc_t *instance, usb_address_t address, 195 usb_endpoint_t endpoint, usb_direction_t direction) 196 { 197 assert(instance); 198 fibril_mutex_lock(&instance->guard); 199 endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager, 200 address, endpoint, direction, NULL); 201 if (ep == NULL) { 202 usb_log_error("Endpoint unregister failed: No such EP.\n"); 203 fibril_mutex_unlock(&instance->guard); 204 return ENOENT; 205 } 206 207 hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep); 208 if (hcd_ep) { 209 /* Dequeue hcd_ep */ 210 switch (ep->transfer_type) { 211 case USB_TRANSFER_CONTROL: 212 instance->registers->control &= ~C_CLE; 213 endpoint_list_remove_ep( 214 &instance->lists[ep->transfer_type], hcd_ep); 215 instance->registers->control_current = 0; 216 instance->registers->control |= C_CLE; 217 break; 218 case USB_TRANSFER_BULK: 219 instance->registers->control &= ~C_BLE; 220 endpoint_list_remove_ep( 221 &instance->lists[ep->transfer_type], hcd_ep); 222 instance->registers->control |= C_BLE; 223 break; 224 case USB_TRANSFER_ISOCHRONOUS: 225 case USB_TRANSFER_INTERRUPT: 226 instance->registers->control &= (~C_PLE & ~C_IE); 227 endpoint_list_remove_ep( 228 &instance->lists[ep->transfer_type], hcd_ep); 229 instance->registers->control |= C_PLE | C_IE; 230 break; 231 default: 232 break; 233 } 234 hcd_endpoint_clear(ep); 235 } else { 236 usb_log_warning("Endpoint without hcd equivalent structure.\n"); 237 } 238 int ret = usb_endpoint_manager_unregister_ep(&instance->ep_manager, 239 address, endpoint, direction); 240 fibril_mutex_unlock(&instance->guard); 241 return ret; 242 } 243 /*----------------------------------------------------------------------------*/ 244 endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address, 245 usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw) 246 { 247 assert(instance); 248 fibril_mutex_lock(&instance->guard); 249 endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager, 250 address, endpoint, direction, bw); 251 fibril_mutex_unlock(&instance->guard); 252 return ep; 253 } 254 /*----------------------------------------------------------------------------*/ 255 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch) 256 { 257 assert(instance); 258 assert(batch); 259 assert(batch->ep); 260 261 /* check for root hub communication */ 262 if (batch->ep->address == instance->rh.address) { 263 return rh_request(&instance->rh, batch); 264 } 265 266 fibril_mutex_lock(&instance->guard); 267 list_append(&batch->link, &instance->pending_batches); 268 batch_commit(batch); 269 switch (batch->ep->transfer_type) { 270 case USB_TRANSFER_CONTROL: 143 271 instance->registers->command_status |= CS_CLF; 144 usb_log_debug2("Set control transfer filled: %x.\n",145 instance->registers->command_status);146 instance->registers->control |= C_CLE;147 272 break; 148 273 case USB_TRANSFER_BULK: 149 274 instance->registers->command_status |= CS_BLF; 150 usb_log_debug2("Set bulk transfer filled: %x.\n",151 instance->registers->command_status);152 275 break; 153 276 default: 154 277 break; 155 278 } 279 280 fibril_mutex_unlock(&instance->guard); 156 281 return EOK; 157 282 } … … 165 290 rh_interrupt(&instance->rh); 166 291 167 usb_log_info("OHCI interrupt: %x.\n", status); 168 169 170 LIST_INITIALIZE(done); 171 transfer_list_remove_finished(&instance->transfers_interrupt, &done); 172 transfer_list_remove_finished(&instance->transfers_isochronous, &done); 173 transfer_list_remove_finished(&instance->transfers_control, &done); 174 transfer_list_remove_finished(&instance->transfers_bulk, &done); 175 176 while (!list_empty(&done)) { 177 link_t *item = done.next; 178 list_remove(item); 179 usb_transfer_batch_t *batch = 180 list_get_instance(item, usb_transfer_batch_t, link); 181 usb_transfer_batch_finish(batch); 292 usb_log_debug("OHCI interrupt: %x.\n", status); 293 294 if (status & IS_WDH) { 295 fibril_mutex_lock(&instance->guard); 296 usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca, 297 instance->registers->hcca, 298 (void *) addr_to_phys(instance->hcca)); 299 usb_log_debug2("Periodic current: %#" PRIx32 ".\n", 300 instance->registers->periodic_current); 301 302 link_t *current = instance->pending_batches.next; 303 while (current != &instance->pending_batches) { 304 link_t *next = current->next; 305 usb_transfer_batch_t *batch = 306 usb_transfer_batch_from_link(current); 307 308 if (batch_is_complete(batch)) { 309 list_remove(current); 310 usb_transfer_batch_finish(batch); 311 } 312 current = next; 313 } 314 fibril_mutex_unlock(&instance->guard); 182 315 } 183 316 } … … 191 324 instance->registers->interrupt_status = status; 192 325 hc_interrupt(instance, status); 193 async_usleep( 1000);326 async_usleep(50000); 194 327 } 195 328 return EOK; … … 267 400 instance->registers->control); 268 401 402 /* Use HCCA */ 403 instance->registers->hcca = addr_to_phys(instance->hcca); 404 405 /* Use queues */ 406 instance->registers->bulk_head = 407 instance->lists[USB_TRANSFER_BULK].list_head_pa; 408 usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n", 409 instance->lists[USB_TRANSFER_BULK].list_head, 410 instance->lists[USB_TRANSFER_BULK].list_head_pa); 411 412 instance->registers->control_head = 413 instance->lists[USB_TRANSFER_CONTROL].list_head_pa; 414 usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n", 415 instance->lists[USB_TRANSFER_CONTROL].list_head, 416 instance->lists[USB_TRANSFER_CONTROL].list_head_pa); 417 269 418 /* Enable queues */ 270 419 instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE); … … 296 445 assert(instance); 297 446 298 #define SETUP_ TRANSFER_LIST(type, name) \447 #define SETUP_ENDPOINT_LIST(type) \ 299 448 do { \ 300 int ret = transfer_list_init(&instance->type, name); \ 449 const char *name = usb_str_transfer_type(type); \ 450 int ret = endpoint_list_init(&instance->lists[type], name); \ 301 451 if (ret != EOK) { \ 302 usb_log_error("Failed(%d) to setup %s transferlist.\n", \452 usb_log_error("Failed(%d) to setup %s endpoint list.\n", \ 303 453 ret, name); \ 304 transfer_list_fini(&instance->transfers_isochronous); \305 transfer_list_fini(&instance->transfers_interrupt); \306 transfer_list_fini(&instance->transfers_control); \307 transfer_list_fini(&instance->transfers_bulk); \454 endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]); \ 455 endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \ 456 endpoint_list_fini(&instance->lists[USB_TRANSFER_CONTROL]); \ 457 endpoint_list_fini(&instance->lists[USB_TRANSFER_BULK]); \ 308 458 } \ 309 459 } while (0) 310 460 311 SETUP_TRANSFER_LIST(transfers_isochronous, "ISOCHRONOUS"); 312 SETUP_TRANSFER_LIST(transfers_interrupt, "INTERRUPT"); 313 SETUP_TRANSFER_LIST(transfers_control, "CONTROL"); 314 SETUP_TRANSFER_LIST(transfers_bulk, "BULK"); 315 316 transfer_list_set_next(&instance->transfers_interrupt, 317 &instance->transfers_isochronous); 318 319 /* Assign pointers to be used during scheduling */ 320 instance->transfers[USB_TRANSFER_INTERRUPT] = 321 &instance->transfers_interrupt; 322 instance->transfers[USB_TRANSFER_ISOCHRONOUS] = 323 &instance->transfers_interrupt; 324 instance->transfers[USB_TRANSFER_CONTROL] = 325 &instance->transfers_control; 326 instance->transfers[USB_TRANSFER_BULK] = 327 &instance->transfers_bulk; 328 329 return EOK; 330 #undef CHECK_RET_CLEAR_RETURN 461 SETUP_ENDPOINT_LIST(USB_TRANSFER_ISOCHRONOUS); 462 SETUP_ENDPOINT_LIST(USB_TRANSFER_INTERRUPT); 463 SETUP_ENDPOINT_LIST(USB_TRANSFER_CONTROL); 464 SETUP_ENDPOINT_LIST(USB_TRANSFER_BULK); 465 #undef SETUP_ENDPOINT_LIST 466 endpoint_list_set_next(&instance->lists[USB_TRANSFER_INTERRUPT], 467 &instance->lists[USB_TRANSFER_ISOCHRONOUS]); 468 469 return EOK; 331 470 } 332 471 /*----------------------------------------------------------------------------*/ … … 342 481 return ENOMEM; 343 482 bzero(instance->hcca, sizeof(hcca_t)); 344 instance->registers->hcca = addr_to_phys(instance->hcca); 345 usb_log_debug2("OHCI HCCA initialized at %p(%p).\n", 346 instance->hcca, instance->registers->hcca); 347 348 /* Use queues */ 349 instance->registers->bulk_head = instance->transfers_bulk.list_head_pa; 350 usb_log_debug2("Bulk HEAD set to: %p(%p).\n", 351 instance->transfers_bulk.list_head, 352 instance->transfers_bulk.list_head_pa); 353 354 instance->registers->control_head = 355 instance->transfers_control.list_head_pa; 356 usb_log_debug2("Control HEAD set to: %p(%p).\n", 357 instance->transfers_control.list_head, 358 instance->transfers_control.list_head_pa); 483 usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca); 359 484 360 485 unsigned i = 0; 361 486 for (; i < 32; ++i) { 362 487 instance->hcca->int_ep[i] = 363 instance-> transfers_interrupt.list_head_pa;364 } 365 usb_log_debug2("Interrupt HEADs set to: %p (%p).\n",366 instance-> transfers_interrupt.list_head,367 instance-> transfers_interrupt.list_head_pa);488 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa; 489 } 490 usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n", 491 instance->lists[USB_TRANSFER_INTERRUPT].list_head, 492 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa); 368 493 369 494 return EOK; -
uspace/drv/ohci/hc.h
r380e0364 re1dbcbc 48 48 #include "ohci_regs.h" 49 49 #include "root_hub.h" 50 #include " transfer_list.h"50 #include "endpoint_list.h" 51 51 #include "hw_struct/hcca.h" 52 52 53 53 typedef struct hc { 54 54 ohci_regs_t *registers; 55 hcca_t *hcca; 56 55 57 usb_address_t rh_address; 56 58 rh_t rh; 57 59 58 hcca_t *hcca; 60 endpoint_list_t lists[4]; 61 link_t pending_batches; 59 62 60 transfer_list_t transfers_isochronous;61 transfer_list_t transfers_interrupt;62 transfer_list_t transfers_control;63 transfer_list_t transfers_bulk;64 65 transfer_list_t *transfers[4];66 67 ddf_fun_t *ddf_instance;68 63 usb_device_keeper_t manager; 69 64 usb_endpoint_manager_t ep_manager; 70 65 fid_t interrupt_emulator; 66 fibril_mutex_t guard; 71 67 } hc_t; 72 68 … … 76 72 uintptr_t regs, size_t reg_size, bool interrupts); 77 73 78 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);79 80 void hc_interrupt(hc_t *instance, uint32_t status);81 82 74 /** Safely dispose host controller internal structures 83 75 * … … 85 77 */ 86 78 static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ }; 79 80 int hc_add_endpoint(hc_t *instance, usb_address_t address, usb_endpoint_t ep, 81 usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction, 82 size_t max_packet_size, size_t size, unsigned interval); 83 84 int hc_remove_endpoint(hc_t *instance, usb_address_t address, 85 usb_endpoint_t endpoint, usb_direction_t direction); 86 87 endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address, 88 usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw); 89 90 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch); 91 92 void hc_interrupt(hc_t *instance, uint32_t status); 87 93 88 94 /** Get and cast pointer to the driver data -
uspace/drv/ohci/hcd_endpoint.h
r380e0364 re1dbcbc 1 1 /* 2 * Copyright (c) 201 0 Vojtech Horky2 * Copyright (c) 2011 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusbohci 29 * @{ 30 */ 31 /** @file 32 * @brief OHCI driver 33 */ 34 #ifndef DRV_OHCI_HCD_ENDPOINT_H 35 #define DRV_OHCI_HCD_ENDPOINT_H 28 36 29 /** @addtogroup drvusbvhc 30 * @{ 31 */ 32 /** @file 33 * @brief Virtual device management. 34 */ 35 #ifndef VHCD_DEVICES_H_ 36 #define VHCD_DEVICES_H_ 37 #include <assert.h> 38 #include <adt/list.h> 37 39 38 #include <adt/list.h> 39 #include <usb/usb.h> 40 #include <usb/host/endpoint.h> 40 41 41 #include "hc.h" 42 #include "hw_struct/endpoint_descriptor.h" 43 #include "hw_struct/transfer_descriptor.h" 42 44 43 /** Connected virtual device. */ 44 typedef struct { 45 /** Phone used when sending data to device. */ 46 int phone; 47 /** Unique identification. */ 48 sysarg_t id; 49 /** Linked-list handle. */ 45 typedef struct hcd_endpoint { 46 ed_t *ed; 47 td_t *td; 50 48 link_t link; 51 } virtdev_connection_t;49 } hcd_endpoint_t; 52 50 53 virtdev_connection_t *virtdev_add_device(int, sysarg_t); 54 virtdev_connection_t *virtdev_find(sysarg_t); 55 void virtdev_destroy_device(virtdev_connection_t *); 56 int virtdev_send_to_all(transaction_t *); 51 hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep); 57 52 53 hcd_endpoint_t * hcd_endpoint_get(endpoint_t *ep); 54 55 void hcd_endpoint_clear(endpoint_t *ep); 58 56 #endif 59 57 /** -
uspace/drv/ohci/hw_struct/endpoint_descriptor.c
r380e0364 re1dbcbc 53 53 << ED_STATUS_MPS_SHIFT); 54 54 55 55 56 if (ep->speed == USB_SPEED_LOW) 56 57 instance->status |= ED_STATUS_S_FLAG; 57 58 if (ep->transfer_type == USB_TRANSFER_ISOCHRONOUS) 58 59 instance->status |= ED_STATUS_F_FLAG; 60 61 if (ep->toggle) 62 instance->td_head |= ED_TDHEAD_TOGGLE_CARRY; 59 63 } 60 64 /** -
uspace/drv/ohci/hw_struct/endpoint_descriptor.h
r380e0364 re1dbcbc 53 53 #define ED_STATUS_D_MASK (0x3) /* direction */ 54 54 #define ED_STATUS_D_SHIFT (11) 55 #define ED_STATUS_D_ IN(0x1)56 #define ED_STATUS_D_ OUT(0x2)55 #define ED_STATUS_D_OUT (0x1) 56 #define ED_STATUS_D_IN (0x2) 57 57 #define ED_STATUS_D_TRANSFER (0x3) 58 58 … … 73 73 #define ED_TDHEAD_ZERO_SHIFT (2) 74 74 #define ED_TDHEAD_TOGGLE_CARRY (0x2) 75 #define ED_TDHEAD_HALTED_FLAG (0x1) 75 76 76 77 volatile uint32_t next; … … 81 82 void ed_init(ed_t *instance, endpoint_t *ep); 82 83 83 static inline void ed_ add_tds(ed_t *instance, td_t *head, td_t *tail)84 static inline void ed_set_td(ed_t *instance, td_t *td) 84 85 { 85 86 assert(instance); 86 instance->td_head = addr_to_phys(head) & ED_TDHEAD_PTR_MASK; 87 instance->td_tail = addr_to_phys(tail) & ED_TDTAIL_PTR_MASK; 87 uintptr_t pa = addr_to_phys(td); 88 instance->td_head = 89 ((pa & ED_TDHEAD_PTR_MASK) 90 | (instance->td_head & ~ED_TDHEAD_PTR_MASK)); 91 instance->td_tail = pa & ED_TDTAIL_PTR_MASK; 92 } 93 94 static inline void ed_set_end_td(ed_t *instance, td_t *td) 95 { 96 assert(instance); 97 uintptr_t pa = addr_to_phys(td); 98 instance->td_tail = pa & ED_TDTAIL_PTR_MASK; 88 99 } 89 100 … … 97 108 } 98 109 110 static inline int ed_toggle_get(ed_t *instance) 111 { 112 assert(instance); 113 return (instance->td_head & ED_TDHEAD_TOGGLE_CARRY) ? 1 : 0; 114 } 115 116 static inline void ed_toggle_set(ed_t *instance, int toggle) 117 { 118 assert(instance); 119 assert(toggle == 0 || toggle == 1); 120 if (toggle == 1) { 121 instance->td_head |= ED_TDHEAD_TOGGLE_CARRY; 122 } else { 123 /* clear halted flag when reseting toggle */ 124 instance->td_head &= ~ED_TDHEAD_TOGGLE_CARRY; 125 instance->td_head &= ~ED_TDHEAD_HALTED_FLAG; 126 } 127 } 99 128 #endif 100 129 /** -
uspace/drv/ohci/hw_struct/hcca.h
r380e0364 re1dbcbc 43 43 uint32_t done_head; 44 44 uint32_t reserved[29]; 45 } __attribute__((packed )) hcca_t;45 } __attribute__((packed, aligned)) hcca_t; 46 46 47 47 #endif -
uspace/drv/ohci/hw_struct/transfer_descriptor.c
r380e0364 re1dbcbc 52 52 instance->status |= togg[toggle] << TD_STATUS_T_SHIFT; 53 53 } 54 if (dir == USB_DIRECTION_IN) { 55 instance->status |= TD_STATUS_ROUND_FLAG; 56 } 54 57 if (buffer != NULL) { 58 assert(size != 0); 55 59 instance->cbp = addr_to_phys(buffer); 56 60 instance->be = addr_to_phys(buffer + size - 1); -
uspace/drv/ohci/hw_struct/transfer_descriptor.h
r380e0364 re1dbcbc 50 50 #define TD_STATUS_DP_SHIFT (19) 51 51 #define TD_STATUS_DP_SETUP (0x0) 52 #define TD_STATUS_DP_ IN(0x1)53 #define TD_STATUS_DP_ OUT(0x2)52 #define TD_STATUS_DP_OUT (0x1) 53 #define TD_STATUS_DP_IN (0x2) 54 54 #define TD_STATUS_DI_MASK (0x7) /* delay interrupt, wait DI frames before int */ 55 55 #define TD_STATUS_DI_SHIFT (21) … … 59 59 #define TD_STATUS_T_0 (0x2) 60 60 #define TD_STATUS_T_1 (0x3) 61 #define TD_STATUS_T_ED (0) 61 62 #define TD_STATUS_EC_MASK (0x3) /* error count */ 62 63 #define TD_STATUS_EC_SHIFT (26) … … 86 87 int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK; 87 88 /* something went wrong, error code is set */ 88 if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2 && cc != CC_NOERROR) {89 if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2) { 89 90 return true; 90 91 } … … 102 103 return cc_to_rc(cc); 103 104 } 105 106 static inline size_t td_remain_size(td_t *instance) 107 { 108 assert(instance); 109 if (instance->cbp == 0) 110 return 0; 111 return instance->be - instance->cbp + 1; 112 } 104 113 #endif 105 114 /** -
uspace/drv/ohci/iface.c
r380e0364 re1dbcbc 55 55 56 56 size_t res_bw; 57 endpoint_t *ep = usb_endpoint_manager_get_ep(&(*hc)->ep_manager,57 endpoint_t *ep = hc_get_endpoint(*hc, 58 58 target.address, target.endpoint, direction, &res_bw); 59 59 if (ep == NULL) { … … 118 118 hc_t *hc = fun_to_hc(fun); 119 119 assert(hc); 120 usb_log_debug("Address bind %d-% d.\n", address, handle);120 usb_log_debug("Address bind %d-%" PRIun ".\n", address, handle); 121 121 usb_device_keeper_bind(&hc->manager, address, handle); 122 122 return EOK; … … 164 164 } 165 165 const size_t size = max_packet_size; 166 int ret;167 166 168 167 usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n", … … 170 169 usb_str_speed(speed), direction, size, max_packet_size, interval); 171 170 172 endpoint_t *ep = malloc(sizeof(endpoint_t)); 173 if (ep == NULL) 174 return ENOMEM; 175 ret = endpoint_init(ep, address, endpoint, direction, 176 transfer_type, speed, max_packet_size); 177 if (ret != EOK) { 178 free(ep); 179 return ret; 180 } 181 182 ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size); 183 if (ret != EOK) { 184 endpoint_destroy(ep); 185 } 186 return ret; 171 return hc_add_endpoint(hc, address, endpoint, speed, transfer_type, 172 direction, max_packet_size, size, interval); 187 173 } 188 174 /*----------------------------------------------------------------------------*/ … … 195 181 usb_log_debug("Unregister endpoint %d:%d %d.\n", 196 182 address, endpoint, direction); 197 return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address, 198 endpoint, direction); 183 return hc_remove_endpoint(hc, address, endpoint, direction); 199 184 } 200 185 /*----------------------------------------------------------------------------*/ … … 228 213 ret = hc_schedule(hc, batch); 229 214 if (ret != EOK) { 230 batch_dispose(batch);215 usb_transfer_batch_dispose(batch); 231 216 } 232 217 return ret; … … 262 247 ret = hc_schedule(hc, batch); 263 248 if (ret != EOK) { 264 batch_dispose(batch);249 usb_transfer_batch_dispose(batch); 265 250 } 266 251 return ret; … … 296 281 ret = hc_schedule(hc, batch); 297 282 if (ret != EOK) { 298 batch_dispose(batch);283 usb_transfer_batch_dispose(batch); 299 284 } 300 285 return ret; … … 330 315 ret = hc_schedule(hc, batch); 331 316 if (ret != EOK) { 332 batch_dispose(batch);317 usb_transfer_batch_dispose(batch); 333 318 } 334 319 return ret; … … 346 331 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 347 332 * and deallocated by the caller). 348 * @param[in] setup_ packet_size Size of @p setup_packet buffer in bytes.333 * @param[in] setup_size Size of @p setup_packet buffer in bytes. 349 334 * @param[in] data_buffer Data buffer (in USB endianess, allocated and 350 335 * deallocated by the caller). 351 * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.336 * @param[in] size Size of @p data_buffer buffer in bytes. 352 337 * @param[in] callback Callback to be issued once the transfer is complete. 353 338 * @param[in] arg Pass-through argument to the callback. … … 370 355 ret = hc_schedule(hc, batch); 371 356 if (ret != EOK) { 372 batch_dispose(batch);357 usb_transfer_batch_dispose(batch); 373 358 } 374 359 return ret; … … 386 371 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 387 372 * and deallocated by the caller). 388 * @param[in] setup_ packet_size Size of @p setup_packet buffer in bytes.373 * @param[in] setup_size Size of @p setup_packet buffer in bytes. 389 374 * @param[in] data_buffer Buffer where to store the data (in USB endianess, 390 375 * allocated and deallocated by the caller). 391 * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.376 * @param[in] size Size of @p data_buffer buffer in bytes. 392 377 * @param[in] callback Callback to be issued once the transfer is complete. 393 378 * @param[in] arg Pass-through argument to the callback. … … 409 394 ret = hc_schedule(hc, batch); 410 395 if (ret != EOK) { 411 batch_dispose(batch);396 usb_transfer_batch_dispose(batch); 412 397 } 413 398 return ret; -
uspace/drv/ohci/ohci.c
r380e0364 re1dbcbc 148 148 pci_get_my_registers(device, &mem_reg_base, &mem_reg_size, &irq); 149 149 CHECK_RET_DEST_FUN_RETURN(ret, 150 "Failed(%d) to get memory addresses:.\n", ret, device->handle); 151 usb_log_debug("Memory mapped regs at 0x%X (size %zu), IRQ %d.\n", 152 mem_reg_base, mem_reg_size, irq); 150 "Failed to get memory addresses for %" PRIun ": %s.\n", 151 device->handle, str_error(ret)); 152 usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n", 153 (void *) mem_reg_base, mem_reg_size, irq); 153 154 154 155 ret = pci_disable_legacy(device); -
uspace/drv/ohci/ohci.ma
r380e0364 re1dbcbc 1 1 10 pci/ven=106b&dev=003f 2 10 pci/ven=10de&dev=0aa5 3 10 pci/ven=10de&dev=0aa5 -
uspace/drv/ohci/ohci_regs.h
r380e0364 re1dbcbc 55 55 #define C_HCFS_MASK (0x3) /* Host controller functional state */ 56 56 #define C_HCFS_RESET (0x0) 57 #define C_HCFS_ OPERATIONAL(0x1)58 #define C_HCFS_ RESUME(0x2)57 #define C_HCFS_RESUME (0x1) 58 #define C_HCFS_OPERATIONAL (0x2) 59 59 #define C_HCFS_SUSPEND (0x3) 60 60 #define C_HCFS_SHIFT (6) … … 100 100 #define HCCA_PTR_MASK 0xffffff00 /* HCCA is 256B aligned */ 101 101 102 /** Currently executed period endpoint */103 const volatile uint32_t period _current;102 /** Currently executed periodic endpoint */ 103 const volatile uint32_t periodic_current; 104 104 105 105 /** The first control endpoint */ -
uspace/drv/ohci/pci.c
r380e0364 re1dbcbc 117 117 mem_address = res->res.mem_range.address; 118 118 mem_size = res->res.mem_range.size; 119 usb_log_debug2("Found mem: % llx%zu.\n",120 mem_address, mem_size);119 usb_log_debug2("Found mem: %p %zu.\n", 120 (void *) mem_address, mem_size); 121 121 mem_found = true; 122 122 } -
uspace/drv/ohci/root_hub.c
r380e0364 re1dbcbc 149 149 150 150 151 static void usb_create_serialized_hub_descriptor(rh_t *instance, 152 uint8_t ** out_result, 153 size_t * out_size); 154 155 static void rh_init_descriptors(rh_t *instance); 151 static int create_serialized_hub_descriptor(rh_t *instance); 152 153 static int rh_init_descriptors(rh_t *instance); 156 154 157 155 static int process_get_port_status_request(rh_t *instance, uint16_t port, … … 164 162 usb_transfer_batch_t * request); 165 163 166 static void create_interrupt_mask(rh_t *instance, void ** buffer, 167 size_t * buffer_size); 164 static void create_interrupt_mask_in_instance(rh_t *instance); 168 165 169 166 static int process_get_descriptor_request(rh_t *instance, … … 198 195 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request); 199 196 200 197 static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request); 198 199 static bool is_zeros(void * buffer, size_t size); 201 200 202 201 … … 205 204 * @return Error code. 206 205 */ 207 int rh_init(rh_t *instance, ddf_dev_t *dev,ohci_regs_t *regs) {206 int rh_init(rh_t *instance, ohci_regs_t *regs) { 208 207 assert(instance); 209 //instance->address = -1;210 208 instance->registers = regs; 211 instance->device = dev;212 209 instance->port_count = 213 210 (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK; 214 rh_init_descriptors(instance); 211 int opResult = rh_init_descriptors(instance); 212 if(opResult != EOK){ 213 return opResult; 214 } 215 215 // set port power mode to no-power-switching 216 instance->registers->rh_desc_a = 217 instance->registers->rh_desc_a | (1<<9); 216 instance->registers->rh_desc_a |= RHDA_NPS_FLAG; 217 instance->unfinished_interrupt_transfer = NULL; 218 instance->interrupt_mask_size = (instance->port_count + 8)/8; 219 instance->interrupt_buffer = malloc(instance->interrupt_mask_size); 220 if(!instance->interrupt_buffer) 221 return ENOMEM; 222 218 223 219 224 usb_log_info("OHCI root hub with %d ports.\n", instance->port_count); 220 221 //start generic usb hub driver222 223 /* TODO: implement */224 225 return EOK; 225 226 } … … 237 238 assert(request); 238 239 int opResult; 239 if (request-> transfer_type == USB_TRANSFER_CONTROL) {240 if (request->ep->transfer_type == USB_TRANSFER_CONTROL) { 240 241 usb_log_info("Root hub got CONTROL packet\n"); 241 242 opResult = process_ctrl_request(instance, request); 242 } else if (request->transfer_type == USB_TRANSFER_INTERRUPT) { 243 usb_transfer_batch_finish_error(request, opResult); 244 } else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) { 243 245 usb_log_info("Root hub got INTERRUPT packet\n"); 244 void * buffer; 245 create_interrupt_mask(instance, &buffer, 246 &(request->transfered_size)); 247 memcpy(request->transport_buffer, buffer, 248 request->transfered_size); 246 create_interrupt_mask_in_instance(instance); 247 if(is_zeros(instance->interrupt_buffer, 248 instance->interrupt_mask_size)){ 249 usb_log_debug("no changes..\n"); 250 instance->unfinished_interrupt_transfer = request; 251 //will be finished later 252 }else{ 253 usb_log_debug("processing changes..\n"); 254 process_interrupt_mask_in_instance(instance, request); 255 } 249 256 opResult = EOK; 250 257 } else { 251 258 opResult = EINVAL; 252 } 253 usb_transfer_batch_finish_error(request, opResult); 254 return EOK; 255 } 256 257 /*----------------------------------------------------------------------------*/ 258 259 259 usb_transfer_batch_finish_error(request, opResult); 260 } 261 return EOK; 262 } 263 264 /*----------------------------------------------------------------------------*/ 265 266 /** 267 * process interrupt on a hub 268 * 269 * If there is no pending interrupt transfer, nothing happens. 270 * @param instance 271 */ 260 272 void rh_interrupt(rh_t *instance) { 261 usb_log_info("Whoa whoa wait, I`m not supposed to receive any " 262 "interrupts, am I?\n"); 263 /* TODO: implement? */ 273 if(!instance->unfinished_interrupt_transfer){ 274 return; 275 } 276 usb_log_debug("finalizing interrupt transfer\n"); 277 create_interrupt_mask_in_instance(instance); 278 process_interrupt_mask_in_instance(instance, 279 instance->unfinished_interrupt_transfer); 264 280 } 265 281 /*----------------------------------------------------------------------------*/ … … 272 288 * 273 289 * @param instance root hub instance 274 * @param@out out_result pointer to resultant serialized descriptor 275 * @param@out out_size size of serialized descriptor 276 */ 277 static void usb_create_serialized_hub_descriptor(rh_t *instance, 278 uint8_t ** out_result, 279 size_t * out_size) { 280 //base size 281 size_t size = 7; 282 //variable size according to port count 283 size_t var_size = instance->port_count / 8 + 284 ((instance->port_count % 8 > 0) ? 1 : 0); 285 size += 2 * var_size; 290 * @return error code 291 */ 292 static int create_serialized_hub_descriptor(rh_t *instance) { 293 size_t size = 7 + 294 ((instance->port_count +7 )/ 8) * 2; 295 size_t var_size = (instance->port_count +7 )/ 8; 286 296 uint8_t * result = (uint8_t*) malloc(size); 297 if(!result) return ENOMEM; 298 287 299 bzero(result, size); 288 300 //size … … 313 325 result[7 + var_size + i] = 255; 314 326 } 315 (*out_result) = result; 316 (*out_size) = size; 327 instance->hub_descriptor = result; 328 instance->descriptor_size = size; 329 return EOK; 317 330 } 318 331 /*----------------------------------------------------------------------------*/ … … 323 336 * be initialized only once per hub. 324 337 * @instance root hub instance 325 */ 326 static void rh_init_descriptors(rh_t *instance) { 338 * @return error code 339 */ 340 static int rh_init_descriptors(rh_t *instance) { 327 341 memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor, 328 342 sizeof (ohci_rh_device_descriptor) … … 331 345 memcpy(&descriptor, &ohci_rh_conf_descriptor, 332 346 sizeof (ohci_rh_conf_descriptor)); 333 uint8_t * hub_descriptor; 334 size_t hub_desc_size;335 usb_create_serialized_hub_descriptor(instance, &hub_descriptor,336 &hub_desc_size);337 347 348 int opResult = create_serialized_hub_descriptor(instance); 349 if(opResult != EOK){ 350 return opResult; 351 } 338 352 descriptor.total_length = 339 353 sizeof (usb_standard_configuration_descriptor_t) + 340 354 sizeof (usb_standard_endpoint_descriptor_t) + 341 355 sizeof (usb_standard_interface_descriptor_t) + 342 hub_desc_size;356 instance->descriptor_size; 343 357 344 358 uint8_t * full_config_descriptor = 345 359 (uint8_t*) malloc(descriptor.total_length); 360 if(!full_config_descriptor){ 361 return ENOMEM; 362 } 346 363 memcpy(full_config_descriptor, &descriptor, sizeof (descriptor)); 347 364 memcpy(full_config_descriptor + sizeof (descriptor), … … 353 370 sizeof (ohci_rh_iface_descriptor) + 354 371 sizeof (ohci_rh_ep_descriptor), 355 hub_descriptor, hub_desc_size);356 372 instance->hub_descriptor, instance->descriptor_size); 373 357 374 instance->descriptors.configuration = full_config_descriptor; 358 375 instance->descriptors.configuration_size = descriptor.total_length; 376 return EOK; 359 377 } 360 378 /*----------------------------------------------------------------------------*/ … … 374 392 if (port < 1 || port > instance->port_count) 375 393 return EINVAL; 376 uint32_t * uint32_buffer = (uint32_t*) request-> transport_buffer;394 uint32_t * uint32_buffer = (uint32_t*) request->data_buffer; 377 395 request->transfered_size = 4; 378 396 uint32_buffer[0] = instance->registers->rh_port_status[port - 1]; … … 400 418 static int process_get_hub_status_request(rh_t *instance, 401 419 usb_transfer_batch_t * request) { 402 uint32_t * uint32_buffer = (uint32_t*) request-> transport_buffer;420 uint32_t * uint32_buffer = (uint32_t*) request->data_buffer; 403 421 request->transfered_size = 4; 404 422 //bits, 0,1,16,17 … … 447 465 * bit i indicates change on i`th port (i>0). For more info see 448 466 * Hub and Port status bitmap specification in USB specification 449 * (chapter 11.13.4) 450 * @param instance root hub instance 451 * @param@out buffer pointer to created interrupt mas 452 * @param@out buffer_size size of created interrupt mask 453 */ 454 static void create_interrupt_mask(rh_t *instance, void ** buffer, 455 size_t * buffer_size) { 456 int bit_count = instance->port_count + 1; 457 (*buffer_size) = (bit_count / 8) + ((bit_count % 8 == 0) ? 0 : 1); 458 459 (*buffer) = malloc(*buffer_size); 460 uint8_t * bitmap = (uint8_t*) (*buffer); 467 * (chapter 11.13.4). 468 * Uses instance`s interrupt buffer to store the interrupt information. 469 * @param instance root hub instance 470 */ 471 static void create_interrupt_mask_in_instance(rh_t * instance) { 472 uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer); 461 473 uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16)) 462 474 | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16)); 463 bzero(bitmap, (*buffer_size));475 bzero(bitmap, instance->interrupt_mask_size); 464 476 if (instance->registers->rh_status & mask) { 465 477 bitmap[0] = 1; … … 492 504 const uint16_t setup_request_value = setup_request->value_high; 493 505 //(setup_request->value_low << 8); 494 bool del = false;495 506 switch (setup_request_value) { 496 507 case USB_DESCTYPE_HUB: 497 508 { 498 uint8_t * descriptor; 499 usb_create_serialized_hub_descriptor( 500 instance, &descriptor, &size); 501 result_descriptor = descriptor; 502 if (result_descriptor) del = true; 509 usb_log_debug("USB_DESCTYPE_HUB\n"); 510 result_descriptor = instance->hub_descriptor; 511 size = instance->descriptor_size; 503 512 break; 504 513 } … … 550 559 } 551 560 request->transfered_size = size; 552 memcpy(request->transport_buffer, result_descriptor, size); 553 if (del) 554 free(result_descriptor); 561 memcpy(request->data_buffer, result_descriptor, size); 555 562 return EOK; 556 563 } … … 571 578 if (request->buffer_size != 1) 572 579 return EINVAL; 573 request-> transport_buffer[0] = 1;580 request->data_buffer[0] = 1; 574 581 request->transfered_size = 1; 575 582 return EOK; … … 866 873 return opResult; 867 874 } 875 /*----------------------------------------------------------------------------*/ 876 877 /** 878 * process hanging interrupt request 879 * 880 * If an interrupt transfer has been received and there was no change, 881 * the driver stores the transfer information and waits for change to occcur. 882 * This routine is called when that happens and it finalizes the interrupt 883 * transfer. 884 * 885 * @param instance hub instance 886 * @param request batch request to be processed 887 * 888 * @return 889 */ 890 static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request){ 891 memcpy(request->data_buffer, instance->interrupt_buffer, 892 instance->interrupt_mask_size); 893 request->transfered_size = instance->interrupt_mask_size; 894 instance->unfinished_interrupt_transfer = NULL; 895 usb_transfer_batch_finish_error(request, EOK); 896 return EOK; 897 } 898 899 /*----------------------------------------------------------------------------*/ 900 901 /** 902 * return whether the buffer is full of zeros 903 * 904 * Convenience function. 905 * @param buffer 906 * @param size 907 * @return 908 */ 909 static bool is_zeros(void * buffer, size_t size){ 910 if(!buffer) return true; 911 if(!size) return true; 912 size_t i; 913 for(i=0;i<size;++i){ 914 if(((char*)buffer)[i]) 915 return false; 916 } 917 return true; 918 } 868 919 869 920 /** -
uspace/drv/ohci/root_hub.h
r380e0364 re1dbcbc 50 50 /** usb address of the root hub */ 51 51 usb_address_t address; 52 /** ddf device information */53 ddf_dev_t *device;54 52 /** hub port count */ 55 53 int port_count; 56 54 /** hubs descriptors */ 57 55 usb_device_descriptors_t descriptors; 56 /** interrupt transfer waiting for an actual interrupt to occur */ 57 usb_transfer_batch_t * unfinished_interrupt_transfer; 58 /** pre-allocated interrupt mask 59 * 60 * This is allocated when initializing instance, so that memory 61 * allocation is not needed when processing request. Buffer is used for 62 * interrupt bitmask. 63 */ 64 uint8_t * interrupt_buffer; 65 /** size of interrupt buffer */ 66 size_t interrupt_mask_size; 67 /** instance`s descriptor*/ 68 uint8_t * hub_descriptor; 69 /** size of hub descriptor */ 70 size_t descriptor_size; 71 72 58 73 } rh_t; 59 74 60 int rh_init(rh_t *instance, ddf_dev_t *dev,ohci_regs_t *regs);75 int rh_init(rh_t *instance, ohci_regs_t *regs); 61 76 62 77 int rh_request(rh_t *instance, usb_transfer_batch_t *request); -
uspace/drv/ohci/utils/malloc32.h
r380e0364 re1dbcbc 41 41 #include <as.h> 42 42 43 #define UHCI_STRCUTURES_ALIGNMENT 1644 43 #define UHCI_REQUIRED_PAGE_SIZE 4096 45 44 … … 65 64 */ 66 65 static inline void * malloc32(size_t size) 67 { return memalign( UHCI_STRCUTURES_ALIGNMENT, size); }66 { return memalign(size, size); } 68 67 /*----------------------------------------------------------------------------*/ 69 68 /** Physical mallocator simulator
Note:
See TracChangeset
for help on using the changeset viewer.
