Changeset a39cfb8 in mainline for uspace/drv
- Timestamp:
- 2011-04-14T07:54:33Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- e05d6c3
- Parents:
- 3f3afb9 (diff), 34e8bab (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- uspace/drv
- Files:
-
- 26 edited
- 4 moved
-
isa/isa.c (modified) (1 diff)
-
ohci/Makefile (modified) (2 diffs)
-
ohci/batch.c (modified) (16 diffs)
-
ohci/batch.h (modified) (1 diff)
-
ohci/endpoint_list.c (moved) (moved from uspace/drv/ohci/transfer_list.c ) (9 diffs)
-
ohci/endpoint_list.h (moved) (moved from uspace/drv/ohci/transfer_list.h ) (4 diffs)
-
ohci/hc.c (modified) (11 diffs)
-
ohci/hc.h (modified) (3 diffs)
-
ohci/hcd_endpoint.c (moved) (moved from kernel/generic/src/proc/tasklet.c ) (2 diffs)
-
ohci/hcd_endpoint.h (moved) (moved from kernel/generic/include/proc/tasklet.h ) (2 diffs)
-
ohci/hw_struct/endpoint_descriptor.h (modified) (1 diff)
-
ohci/iface.c (modified) (12 diffs)
-
ohci/root_hub.c (modified) (6 diffs)
-
ohci/root_hub.h (modified) (2 diffs)
-
uhci-hcd/batch.c (modified) (13 diffs)
-
uhci-hcd/batch.h (modified) (1 diff)
-
uhci-hcd/hc.c (modified) (8 diffs)
-
uhci-hcd/hc.h (modified) (5 diffs)
-
uhci-hcd/hw_struct/queue_head.h (modified) (4 diffs)
-
uhci-hcd/hw_struct/transfer_descriptor.c (modified) (4 diffs)
-
uhci-hcd/hw_struct/transfer_descriptor.h (modified) (1 diff)
-
uhci-hcd/iface.c (modified) (8 diffs)
-
uhci-hcd/main.c (modified) (5 diffs)
-
uhci-hcd/pci.c (modified) (5 diffs)
-
uhci-hcd/root_hub.c (modified) (2 diffs)
-
uhci-hcd/root_hub.h (modified) (1 diff)
-
uhci-hcd/transfer_list.c (modified) (11 diffs)
-
uhci-hcd/transfer_list.h (modified) (1 diff)
-
uhci-hcd/uhci.c (modified) (13 diffs)
-
uhci-hcd/uhci.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/isa/isa.c
r3f3afb9 ra39cfb8 83 83 static bool isa_enable_fun_interrupt(ddf_fun_t *fnode) 84 84 { 85 / / TODO85 /* TODO */ 86 86 87 87 return false; -
uspace/drv/ohci/Makefile
r3f3afb9 ra39cfb8 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
r3f3afb9 ra39cfb8 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 73 static void batch_data(usb_transfer_batch_t *instance); 54 static void batch_call_in_and_dispose(usb_transfer_batch_t *instance); 55 static void batch_call_out_and_dispose(usb_transfer_batch_t *instance); 56 57 #define DEFAULT_ERROR_COUNT 3 74 /*----------------------------------------------------------------------------*/ 58 75 usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep, 59 76 char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size, … … 65 82 usb_log_error(message); \ 66 83 if (instance) { \ 67 batch_dispose(instance); \84 usb_transfer_batch_dispose(instance); \ 68 85 } \ 69 86 return NULL; \ … … 73 90 CHECK_NULL_DISPOSE_RETURN(instance, 74 91 "Failed to allocate batch instance.\n"); 75 usb_target_t target = 76 { .address = ep->address, .endpoint = ep->endpoint }; 77 usb_transfer_batch_init(instance, target, ep->transfer_type, ep->speed, 78 ep->max_packet_size, buffer, NULL, buffer_size, NULL, setup_size, 79 func_in, func_out, arg, fun, ep, NULL); 80 81 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); 82 100 CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n"); 83 bzero(data, sizeof(ohci_batch_t));84 101 instance->private_data = data; 85 102 86 /* we needs + 1 transfer descriptor as the last one won't be executed */ 87 data->td_count = 1 + 103 data->td_count = 88 104 ((buffer_size + OHCI_TD_MAX_TRANSFER - 1) / OHCI_TD_MAX_TRANSFER); 89 105 if (ep->transfer_type == USB_TRANSFER_CONTROL) { … … 91 107 } 92 108 93 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); 94 111 CHECK_NULL_DISPOSE_RETURN(data->tds, 95 112 "Failed to allocate transfer descriptors.\n"); 96 bzero(data->tds, sizeof(td_t) * data->td_count); 97 98 data->ed = malloc32(sizeof(ed_t)); 99 CHECK_NULL_DISPOSE_RETURN(data->ed, 100 "Failed to allocate endpoint descriptor.\n"); 101 102 if (buffer_size > 0) { 103 instance->transport_buffer = malloc32(buffer_size); 104 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, 105 128 "Failed to allocate device accessible buffer.\n"); 106 } 107 108 if (setup_size > 0) { 109 instance->setup_buffer = malloc32(setup_size); 110 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer, 111 "Failed to allocate device accessible setup buffer.\n"); 129 instance->setup_buffer = data->device_buffer; 130 instance->data_buffer = data->device_buffer + setup_size; 112 131 memcpy(instance->setup_buffer, setup_buffer, setup_size); 113 132 } … … 116 135 } 117 136 /*----------------------------------------------------------------------------*/ 118 void batch_dispose(usb_transfer_batch_t *instance)119 {120 assert(instance);121 ohci_batch_t *data = instance->private_data;122 assert(data);123 free32(data->ed);124 free32(data->tds);125 free32(instance->setup_buffer);126 free32(instance->transport_buffer);127 free(data);128 free(instance);129 }130 /*----------------------------------------------------------------------------*/131 137 bool batch_is_complete(usb_transfer_batch_t *instance) 132 138 { 133 139 assert(instance); 134 ohci_ batch_t *data = instance->private_data;135 assert(data); 136 size_t tds = data->td_count - 1;140 ohci_transfer_batch_t *data = instance->private_data; 141 assert(data); 142 size_t tds = data->td_count; 137 143 usb_log_debug("Batch(%p) checking %d td(s) for completion.\n", 138 144 instance, tds); … … 142 148 size_t i = 0; 143 149 for (; i < tds; ++i) { 150 assert(data->tds[i] != NULL); 144 151 usb_log_debug("TD %d: %x:%x:%x:%x.\n", i, 145 data->tds[i] .status, data->tds[i].cbp, data->tds[i].next,146 data->tds[i] .be);147 if (!td_is_finished( &data->tds[i])) {152 data->tds[i]->status, data->tds[i]->cbp, data->tds[i]->next, 153 data->tds[i]->be); 154 if (!td_is_finished(data->tds[i])) { 148 155 return false; 149 156 } 150 instance->error = td_error( &data->tds[i]);157 instance->error = td_error(data->tds[i]); 151 158 /* FIXME: calculate real transfered size */ 152 159 instance->transfered_size = instance->buffer_size; 153 160 if (instance->error != EOK) { 154 161 usb_log_debug("Batch(%p) found error TD(%d):%x.\n", 155 instance, i, data->tds[i].status); 156 return true; 157 // endpoint_toggle_set(instance->ep, 162 instance, i, data->tds[i]->status); 163 break; 158 164 } 159 165 } 166 data->leave_td = i; 167 assert(data->leave_td <= data->td_count); 168 hcd_endpoint_t *hcd_ep = hcd_endpoint_get(instance->ep); 169 assert(hcd_ep); 170 hcd_ep->td = data->tds[i]; 171 160 172 return true; 161 173 } 162 174 /*----------------------------------------------------------------------------*/ 175 void batch_commit(usb_transfer_batch_t *instance) 176 { 177 assert(instance); 178 ohci_transfer_batch_t *data = instance->private_data; 179 assert(data); 180 ed_set_end_td(data->ed, data->tds[data->td_count]); 181 } 182 /*----------------------------------------------------------------------------*/ 163 183 void batch_control_write(usb_transfer_batch_t *instance) 164 184 { 165 185 assert(instance); 166 186 /* We are data out, we are supposed to provide data */ 167 memcpy(instance->transport_buffer, instance->buffer, 168 instance->buffer_size); 169 instance->next_step = batch_call_out_and_dispose; 187 memcpy(instance->data_buffer, instance->buffer, instance->buffer_size); 188 instance->next_step = usb_transfer_batch_call_out_and_dispose; 170 189 batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN); 171 190 usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance); … … 175 194 { 176 195 assert(instance); 177 instance->next_step = batch_call_in_and_dispose;196 instance->next_step = usb_transfer_batch_call_in_and_dispose; 178 197 batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT); 179 198 usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance); … … 183 202 { 184 203 assert(instance); 185 assert(instance->direction == USB_DIRECTION_IN); 186 instance->next_step = batch_call_in_and_dispose; 204 instance->next_step = usb_transfer_batch_call_in_and_dispose; 187 205 batch_data(instance); 188 206 usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance); … … 192 210 { 193 211 assert(instance); 194 assert(instance->direction == USB_DIRECTION_OUT);195 212 /* We are data out, we are supposed to provide data */ 196 memcpy(instance->transport_buffer, instance->buffer, 197 instance->buffer_size); 198 instance->next_step = batch_call_out_and_dispose; 213 memcpy(instance->data_buffer, instance->buffer, instance->buffer_size); 214 instance->next_step = usb_transfer_batch_call_out_and_dispose; 199 215 batch_data(instance); 200 216 usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance); … … 204 220 { 205 221 assert(instance); 206 instance->direction = USB_DIRECTION_IN; 207 instance->next_step = batch_call_in_and_dispose; 222 instance->next_step = usb_transfer_batch_call_in_and_dispose; 208 223 batch_data(instance); 209 224 usb_log_debug("Batch(%p) BULK IN initialized.\n", instance); … … 213 228 { 214 229 assert(instance); 215 instance->direction = USB_DIRECTION_IN; 216 instance->next_step = batch_call_in_and_dispose; 230 instance->next_step = usb_transfer_batch_call_in_and_dispose; 217 231 batch_data(instance); 218 232 usb_log_debug("Batch(%p) BULK IN initialized.\n", instance); … … 222 236 { 223 237 assert(instance); 224 ohci_ batch_t *data = instance->private_data;238 ohci_transfer_batch_t *data = instance->private_data; 225 239 assert(data); 226 240 return data->ed; … … 231 245 { 232 246 assert(instance); 233 ohci_batch_t *data = instance->private_data; 234 assert(data); 235 ed_init(data->ed, instance->ep); 236 ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]); 237 usb_log_debug("Created ED(%p): %x:%x:%x:%x.\n", data->ed, 247 ohci_transfer_batch_t *data = instance->private_data; 248 assert(data); 249 usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed, 238 250 data->ed->status, data->ed->td_tail, data->ed->td_head, 239 251 data->ed->next); 240 252 int toggle = 0; 241 253 /* setup stage */ 242 td_init( &data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,254 td_init(data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer, 243 255 instance->setup_size, toggle); 244 td_set_next( &data->tds[0], &data->tds[1]);245 usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0] .status,246 data->tds[0] .cbp, data->tds[0].next, data->tds[0].be);256 td_set_next(data->tds[0], data->tds[1]); 257 usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0]->status, 258 data->tds[0]->cbp, data->tds[0]->next, data->tds[0]->be); 247 259 248 260 /* data stage */ 249 261 size_t td_current = 1; 250 262 size_t remain_size = instance->buffer_size; 251 char * transfer_buffer = instance->transport_buffer;263 char *buffer = instance->data_buffer; 252 264 while (remain_size > 0) { 253 265 size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ? … … 255 267 toggle = 1 - toggle; 256 268 257 td_init( &data->tds[td_current], data_dir, transfer_buffer,269 td_init(data->tds[td_current], data_dir, buffer, 258 270 transfer_size, toggle); 259 td_set_next( &data->tds[td_current], &data->tds[td_current + 1]);271 td_set_next(data->tds[td_current], data->tds[td_current + 1]); 260 272 usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n", 261 data->tds[td_current] .status, data->tds[td_current].cbp,262 data->tds[td_current] .next, data->tds[td_current].be);263 264 transfer_buffer += transfer_size;273 data->tds[td_current]->status, data->tds[td_current]->cbp, 274 data->tds[td_current]->next, data->tds[td_current]->be); 275 276 buffer += transfer_size; 265 277 remain_size -= transfer_size; 266 assert(td_current < data->td_count - 2);278 assert(td_current < data->td_count - 1); 267 279 ++td_current; 268 280 } 269 281 270 282 /* status stage */ 271 assert(td_current == data->td_count - 2); 272 td_init(&data->tds[td_current], status_dir, NULL, 0, 1); 283 assert(td_current == data->td_count - 1); 284 td_init(data->tds[td_current], status_dir, NULL, 0, 1); 285 td_set_next(data->tds[td_current], data->tds[td_current + 1]); 273 286 usb_log_debug("Created STATUS TD: %x:%x:%x:%x.\n", 274 data->tds[td_current] .status, data->tds[td_current].cbp,275 data->tds[td_current] .next, data->tds[td_current].be);287 data->tds[td_current]->status, data->tds[td_current]->cbp, 288 data->tds[td_current]->next, data->tds[td_current]->be); 276 289 } 277 290 /*----------------------------------------------------------------------------*/ … … 279 292 { 280 293 assert(instance); 281 ohci_batch_t *data = instance->private_data; 282 assert(data); 283 ed_init(data->ed, instance->ep); 284 ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]); 285 usb_log_debug("Created ED(%p): %x:%x:%x:%x.\n", data->ed, 294 ohci_transfer_batch_t *data = instance->private_data; 295 assert(data); 296 usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed, 286 297 data->ed->status, data->ed->td_tail, data->ed->td_head, 287 298 data->ed->next); 288 299 289 /* data stage */290 300 size_t td_current = 0; 291 301 size_t remain_size = instance->buffer_size; 292 char * transfer_buffer = instance->transport_buffer;302 char *buffer = instance->data_buffer; 293 303 while (remain_size > 0) { 294 304 size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ? 295 305 OHCI_TD_MAX_TRANSFER : remain_size; 296 306 297 td_init( &data->tds[td_current], instance->ep->direction,298 transfer_buffer, transfer_size, -1);299 td_set_next( &data->tds[td_current], &data->tds[td_current + 1]);307 td_init(data->tds[td_current], instance->ep->direction, 308 buffer, transfer_size, -1); 309 td_set_next(data->tds[td_current], data->tds[td_current + 1]); 300 310 usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n", 301 data->tds[td_current] .status, data->tds[td_current].cbp,302 data->tds[td_current] .next, data->tds[td_current].be);303 304 transfer_buffer += transfer_size;311 data->tds[td_current]->status, data->tds[td_current]->cbp, 312 data->tds[td_current]->next, data->tds[td_current]->be); 313 314 buffer += transfer_size; 305 315 remain_size -= transfer_size; 306 316 assert(td_current < data->td_count); … … 308 318 } 309 319 } 310 /*----------------------------------------------------------------------------*/311 /** Helper function calls callback and correctly disposes of batch structure.312 *313 * @param[in] instance Batch structure to use.314 */315 void batch_call_in_and_dispose(usb_transfer_batch_t *instance)316 {317 assert(instance);318 usb_transfer_batch_call_in(instance);319 batch_dispose(instance);320 }321 /*----------------------------------------------------------------------------*/322 /** Helper function calls callback and correctly disposes of batch structure.323 *324 * @param[in] instance Batch structure to use.325 */326 void batch_call_out_and_dispose(usb_transfer_batch_t *instance)327 {328 assert(instance);329 usb_transfer_batch_call_out(instance);330 batch_dispose(instance);331 }332 320 /** 333 321 * @} -
uspace/drv/ohci/batch.h
r3f3afb9 ra39cfb8 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
r3f3afb9 ra39cfb8 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); … … 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); … … 82 79 } 83 80 /*----------------------------------------------------------------------------*/ 84 /** Submit transfer batchto the list and queue.85 * 86 * @param[in] instance List to use. 87 * @param[in] batch Transfer batchto submit.88 * @return Error code 89 * 90 * The batchis added to the end of the list and queue.91 */ 92 void transfer_list_add_batch(93 transfer_list_t *instance, usb_transfer_batch_t *batch) 94 { 95 assert( instance);96 assert(batch);97 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); 98 95 99 96 fibril_mutex_lock(&instance->guard); … … 101 98 ed_t *last_ed = NULL; 102 99 /* Add to the hardware queue. */ 103 if (list_empty(&instance-> batch_list)) {100 if (list_empty(&instance->endpoint_list)) { 104 101 /* There is nothing scheduled */ 105 102 last_ed = instance->list_head; 106 103 } else { 107 104 /* There is something scheduled */ 108 usb_transfer_batch_t *last = list_get_instance(109 instance-> batch_list.prev, usb_transfer_batch_t, link);110 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; 111 108 } 112 109 /* keep link */ 113 batch_ed(batch)->next = last_ed->next;114 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); 115 112 116 113 asm volatile ("": : :"memory"); 117 114 118 115 /* Add to the driver list */ 119 list_append(& batch->link, &instance->batch_list);120 121 usb_transfer_batch_t *first = list_get_instance(122 instance-> batch_list.next, usb_transfer_batch_t, link);123 usb_log_debug(" Batch(%p) added to list %s, first is %p(%p).\n",124 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); 125 122 if (last_ed == instance->list_head) { 126 123 usb_log_debug2("%s head ED(%p-%p): %x:%x:%x:%x.\n", … … 132 129 } 133 130 /*----------------------------------------------------------------------------*/ 134 /** Create list for finished batches. 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 usb_log_debug2("Checking list %s for completed batches(%d).\n",146 instance->name, list_count(&instance-> batch_list));147 link_t *current = instance-> batch_list.next;148 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) { 149 147 link_t *next = current->next; 150 usb_transfer_batch_t *batch=151 list_get_instance(current, usb_transfer_batch_t, link);152 153 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)) { 154 152 /* Save for post-processing */ 155 transfer_list_remove_batch(instance, batch);153 endpoint_list_remove_endpoint(instance, endpoint); 156 154 list_append(current, done); 157 155 } … … 161 159 } 162 160 /*----------------------------------------------------------------------------*/ 163 /** Walk the list and abort all batches. 164 * 165 * @param[in] instance List to use. 166 */ 167 void transfer_list_abort_all(transfer_list_t *instance) 168 { 169 fibril_mutex_lock(&instance->guard); 170 while (!list_empty(&instance->batch_list)) { 171 link_t *current = instance->batch_list.next; 172 usb_transfer_batch_t *batch = 173 list_get_instance(current, usb_transfer_batch_t, link); 174 transfer_list_remove_batch(instance, batch); 175 usb_transfer_batch_finish_error(batch, EIO); 176 } 177 fibril_mutex_unlock(&instance->guard); 178 } 179 /*----------------------------------------------------------------------------*/ 180 /** Remove a transfer batch from the list and queue. 181 * 182 * @param[in] instance List to use. 183 * @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. 184 183 * @return Error code 185 184 * 186 185 * Does not lock the transfer list, caller is responsible for that. 187 186 */ 188 void transfer_list_remove_batch( 189 transfer_list_t *instance, usb_transfer_batch_t *batch) 187 void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep) 190 188 { 191 189 assert(instance); 192 190 assert(instance->list_head); 193 assert(batch); 194 assert(batch_ed(batch)); 195 assert(fibril_mutex_is_locked(&instance->guard)); 191 assert(hcd_ep); 192 assert(hcd_ep->ed); 193 194 fibril_mutex_lock(&instance->guard); 196 195 197 196 usb_log_debug2( 198 "Queue %s: removing batch(%p).\n", instance->name, batch);197 "Queue %s: removing endpoint(%p).\n", instance->name, hcd_ep); 199 198 200 199 const char *qpos = NULL; 200 ed_t *prev_ed; 201 201 /* Remove from the hardware queue */ 202 if (instance-> batch_list.next == &batch->link) {202 if (instance->endpoint_list.next == &hcd_ep->link) { 203 203 /* I'm the first one here */ 204 assert((instance->list_head->next & ED_NEXT_PTR_MASK) 205 == addr_to_phys(batch_ed(batch))); 206 instance->list_head->next = batch_ed(batch)->next; 204 prev_ed = instance->list_head; 207 205 qpos = "FIRST"; 208 206 } else { 209 usb_transfer_batch_t *prev = 210 list_get_instance( 211 batch->link.prev, usb_transfer_batch_t, link); 212 assert((batch_ed(prev)->next & ED_NEXT_PTR_MASK) 213 == addr_to_phys(batch_ed(batch))); 214 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; 215 210 qpos = "NOT FIRST"; 216 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 217 215 asm volatile ("": : :"memory"); 218 usb_log_debug("Batch(%p) removed (%s) from %s, next %x.\n", 219 batch, qpos, instance->name, batch_ed(batch)->next); 220 221 /* Remove from the batch list */ 222 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); 223 222 } 224 223 /** -
uspace/drv/ohci/endpoint_list.h
r3f3afb9 ra39cfb8 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
r3f3afb9 ra39cfb8 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, … … 115 122 fibril_mutex_initialize(&instance->guard); 116 123 117 rh_init(&instance->rh, dev,instance->registers);124 rh_init(&instance->rh, instance->registers); 118 125 119 126 if (!interrupts) { … … 123 130 } 124 131 125 return EOK; 126 } 127 /*----------------------------------------------------------------------------*/ 128 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch) 129 { 130 assert(instance); 131 assert(batch); 132 133 /* check for root hub communication */ 134 if (batch->target.address == instance->rh.address) { 135 return rh_request(&instance->rh, batch); 136 } 137 138 fibril_mutex_lock(&instance->guard); 139 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) { 140 167 case USB_TRANSFER_CONTROL: 141 168 instance->registers->control &= ~C_CLE; 142 transfer_list_add_batch( 143 instance->transfers[batch->transfer_type], batch); 144 instance->registers->command_status |= CS_CLF; 145 usb_log_debug2("Set CS control transfer filled: %x.\n", 146 instance->registers->command_status); 169 endpoint_list_add_ep( 170 &instance->lists[ep->transfer_type], hcd_ep); 147 171 instance->registers->control_current = 0; 148 172 instance->registers->control |= C_CLE; … … 150 174 case USB_TRANSFER_BULK: 151 175 instance->registers->control &= ~C_BLE; 152 transfer_list_add_batch( 153 instance->transfers[batch->transfer_type], batch); 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: 271 instance->registers->command_status |= CS_CLF; 272 break; 273 case USB_TRANSFER_BULK: 154 274 instance->registers->command_status |= CS_BLF; 155 usb_log_debug2("Set bulk transfer filled: %x.\n",156 instance->registers->command_status);157 instance->registers->control |= C_BLE;158 break;159 case USB_TRANSFER_INTERRUPT:160 case USB_TRANSFER_ISOCHRONOUS:161 instance->registers->control &= (~C_PLE & ~C_IE);162 transfer_list_add_batch(163 instance->transfers[batch->transfer_type], batch);164 instance->registers->control |= C_PLE | C_IE;165 usb_log_debug2("Added periodic transfer: %x.\n",166 instance->registers->periodic_current);167 275 break; 168 276 default: 169 277 break; 170 278 } 279 171 280 fibril_mutex_unlock(&instance->guard); 172 281 return EOK; … … 189 298 usb_log_debug2("Periodic current: %p.\n", 190 299 instance->registers->periodic_current); 191 LIST_INITIALIZE(done); 192 transfer_list_remove_finished( 193 &instance->transfers_interrupt, &done); 194 transfer_list_remove_finished( 195 &instance->transfers_isochronous, &done); 196 transfer_list_remove_finished( 197 &instance->transfers_control, &done); 198 transfer_list_remove_finished( 199 &instance->transfers_bulk, &done); 200 201 while (!list_empty(&done)) { 202 link_t *item = done.next; 203 list_remove(item); 300 301 link_t *current = instance->pending_batches.next; 302 while (current != &instance->pending_batches) { 303 link_t *next = current->next; 204 304 usb_transfer_batch_t *batch = 205 list_get_instance(item, usb_transfer_batch_t, link); 206 usb_transfer_batch_finish(batch); 305 usb_transfer_batch_from_link(current); 306 307 if (batch_is_complete(batch)) { 308 list_remove(current); 309 usb_transfer_batch_finish(batch); 310 } 311 current = next; 207 312 } 208 313 fibril_mutex_unlock(&instance->guard); … … 298 403 299 404 /* Use queues */ 300 instance->registers->bulk_head = instance->transfers_bulk.list_head_pa; 405 instance->registers->bulk_head = 406 instance->lists[USB_TRANSFER_BULK].list_head_pa; 301 407 usb_log_debug2("Bulk HEAD set to: %p(%p).\n", 302 instance-> transfers_bulk.list_head,303 instance-> transfers_bulk.list_head_pa);408 instance->lists[USB_TRANSFER_BULK].list_head, 409 instance->lists[USB_TRANSFER_BULK].list_head_pa); 304 410 305 411 instance->registers->control_head = 306 instance-> transfers_control.list_head_pa;412 instance->lists[USB_TRANSFER_CONTROL].list_head_pa; 307 413 usb_log_debug2("Control HEAD set to: %p(%p).\n", 308 instance-> transfers_control.list_head,309 instance-> transfers_control.list_head_pa);414 instance->lists[USB_TRANSFER_CONTROL].list_head, 415 instance->lists[USB_TRANSFER_CONTROL].list_head_pa); 310 416 311 417 /* Enable queues */ … … 338 444 assert(instance); 339 445 340 #define SETUP_ TRANSFER_LIST(type, name) \446 #define SETUP_ENDPOINT_LIST(type) \ 341 447 do { \ 342 int ret = transfer_list_init(&instance->type, name); \ 448 const char *name = usb_str_transfer_type(type); \ 449 int ret = endpoint_list_init(&instance->lists[type], name); \ 343 450 if (ret != EOK) { \ 344 usb_log_error("Failed(%d) to setup %s transferlist.\n", \451 usb_log_error("Failed(%d) to setup %s endpoint list.\n", \ 345 452 ret, name); \ 346 transfer_list_fini(&instance->transfers_isochronous); \347 transfer_list_fini(&instance->transfers_interrupt); \348 transfer_list_fini(&instance->transfers_control); \349 transfer_list_fini(&instance->transfers_bulk); \453 endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]); \ 454 endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \ 455 endpoint_list_fini(&instance->lists[USB_TRANSFER_CONTROL]); \ 456 endpoint_list_fini(&instance->lists[USB_TRANSFER_BULK]); \ 350 457 } \ 351 458 } while (0) 352 459 353 SETUP_TRANSFER_LIST(transfers_isochronous, "ISOCHRONOUS"); 354 SETUP_TRANSFER_LIST(transfers_interrupt, "INTERRUPT"); 355 SETUP_TRANSFER_LIST(transfers_control, "CONTROL"); 356 SETUP_TRANSFER_LIST(transfers_bulk, "BULK"); 357 #undef SETUP_TRANSFER_LIST 358 transfer_list_set_next(&instance->transfers_interrupt, 359 &instance->transfers_isochronous); 360 361 /* Assign pointers to be used during scheduling */ 362 instance->transfers[USB_TRANSFER_INTERRUPT] = 363 &instance->transfers_interrupt; 364 instance->transfers[USB_TRANSFER_ISOCHRONOUS] = 365 &instance->transfers_interrupt; 366 instance->transfers[USB_TRANSFER_CONTROL] = 367 &instance->transfers_control; 368 instance->transfers[USB_TRANSFER_BULK] = 369 &instance->transfers_bulk; 460 SETUP_ENDPOINT_LIST(USB_TRANSFER_ISOCHRONOUS); 461 SETUP_ENDPOINT_LIST(USB_TRANSFER_INTERRUPT); 462 SETUP_ENDPOINT_LIST(USB_TRANSFER_CONTROL); 463 SETUP_ENDPOINT_LIST(USB_TRANSFER_BULK); 464 #undef SETUP_ENDPOINT_LIST 465 endpoint_list_set_next(&instance->lists[USB_TRANSFER_INTERRUPT], 466 &instance->lists[USB_TRANSFER_ISOCHRONOUS]); 370 467 371 468 return EOK; … … 388 485 for (; i < 32; ++i) { 389 486 instance->hcca->int_ep[i] = 390 instance-> transfers_interrupt.list_head_pa;487 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa; 391 488 } 392 489 usb_log_debug2("Interrupt HEADs set to: %p(%p).\n", 393 instance-> transfers_interrupt.list_head,394 instance-> transfers_interrupt.list_head_pa);490 instance->lists[USB_TRANSFER_INTERRUPT].list_head, 491 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa); 395 492 396 493 return EOK; -
uspace/drv/ohci/hc.h
r3f3afb9 ra39cfb8 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; … … 77 72 uintptr_t regs, size_t reg_size, bool interrupts); 78 73 79 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);80 81 void hc_interrupt(hc_t *instance, uint32_t status);82 83 74 /** Safely dispose host controller internal structures 84 75 * … … 86 77 */ 87 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); 88 93 89 94 /** Get and cast pointer to the driver data -
uspace/drv/ohci/hcd_endpoint.c
r3f3afb9 ra39cfb8 1 1 /* 2 * Copyright (c) 2007 Jan Hudecek 3 * Copyright (c) 2008 Martin Decky 2 * Copyright (c) 2011 Jan Vesely 4 3 * All rights reserved. 5 4 * … … 27 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 27 */ 29 30 /** @addtogroup genericproc 28 /** @addtogroup drvusbohci 31 29 * @{ 32 30 */ 33 /** @file tasklet.c34 * @brief Tasklet implementation31 /** @file 32 * @brief OHCI driver 35 33 */ 34 #include "utils/malloc32.h" 35 #include "hcd_endpoint.h" 36 36 37 #include <proc/tasklet.h> 38 #include <synch/spinlock.h> 39 #include <mm/slab.h> 40 #include <config.h> 37 hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep) 38 { 39 assert(ep); 40 hcd_endpoint_t *hcd_ep = malloc(sizeof(hcd_endpoint_t)); 41 if (hcd_ep == NULL) 42 return NULL; 41 43 42 /** Spinlock protecting list of tasklets */ 43 SPINLOCK_INITIALIZE(tasklet_lock); 44 hcd_ep->ed = malloc32(sizeof(ed_t)); 45 if (hcd_ep->ed == NULL) { 46 free(hcd_ep); 47 return NULL; 48 } 44 49 45 /** Array of tasklet lists for every CPU */ 46 tasklet_descriptor_t **tasklet_list; 50 hcd_ep->td = malloc32(sizeof(td_t)); 51 if (hcd_ep->td == NULL) { 52 free32(hcd_ep->ed); 53 free(hcd_ep); 54 return NULL; 55 } 47 56 48 void tasklet_init(void) 57 ed_init(hcd_ep->ed, ep); 58 ed_set_td(hcd_ep->ed, hcd_ep->td); 59 endpoint_set_hc_data(ep, hcd_ep, NULL, NULL); 60 61 return hcd_ep; 62 } 63 /*----------------------------------------------------------------------------*/ 64 hcd_endpoint_t * hcd_endpoint_get(endpoint_t *ep) 49 65 { 50 unsigned int i; 51 52 tasklet_list = malloc(sizeof(tasklet_descriptor_t *) * config.cpu_count, 0); 53 if (!tasklet_list) 54 panic("Error initializing tasklets."); 55 56 for (i = 0; i < config.cpu_count; i++) 57 tasklet_list[i] = NULL; 58 59 spinlock_initialize(&tasklet_lock, "tasklet_lock"); 66 assert(ep); 67 return ep->hc_data.data; 60 68 } 61 62 63 /** @} 69 /*----------------------------------------------------------------------------*/ 70 void hcd_endpoint_clear(endpoint_t *ep) 71 { 72 assert(ep); 73 hcd_endpoint_t *hcd_ep = ep->hc_data.data; 74 assert(hcd_ep); 75 free32(hcd_ep->ed); 76 free32(hcd_ep->td); 77 free(hcd_ep); 78 } 79 /** 80 * @} 64 81 */ -
uspace/drv/ohci/hcd_endpoint.h
r3f3afb9 ra39cfb8 1 1 /* 2 * Copyright (c) 2007 Jan Hudecek 3 * Copyright (c) 2008 Martin Decky 2 * Copyright (c) 2011 Jan Vesely 4 3 * All rights reserved. 5 4 * … … 27 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 27 */ 29 30 /** @addtogroup genericproc 28 /** @addtogroup drvusbohci 31 29 * @{ 32 30 */ 33 /** @file tasklet.h34 * @brief Tasklets declarations31 /** @file 32 * @brief OHCI driver 35 33 */ 34 #ifndef DRV_OHCI_HCD_ENDPOINT_H 35 #define DRV_OHCI_HCD_ENDPOINT_H 36 36 37 #ifndef KERN_TASKLET_H_ 38 #define KERN_TASKLET_H_ 39 37 #include <assert.h> 40 38 #include <adt/list.h> 41 39 42 /** Tasklet callback type */ 43 typedef void (* tasklet_callback_t)(void *arg); 40 #include <usb/host/endpoint.h> 44 41 45 /** Tasklet state */ 46 typedef enum { 47 NotActive, 48 Scheduled, 49 InProgress, 50 Disabled 51 } tasklet_state_t; 42 #include "hw_struct/endpoint_descriptor.h" 43 #include "hw_struct/transfer_descriptor.h" 52 44 53 /** Structure describing a tasklet */ 54 typedef struct tasklet_descriptor { 45 typedef struct hcd_endpoint { 46 ed_t *ed; 47 td_t *td; 55 48 link_t link; 56 57 /** Callback to call */ 58 tasklet_callback_t callback; 59 60 /** Argument passed to the callback */ 61 void *arg; 62 63 /** State of the tasklet */ 64 tasklet_state_t state; 65 } tasklet_descriptor_t; 49 } hcd_endpoint_t; 66 50 51 hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep); 67 52 68 extern void tasklet_init(void);53 hcd_endpoint_t * hcd_endpoint_get(endpoint_t *ep); 69 54 55 void hcd_endpoint_clear(endpoint_t *ep); 70 56 #endif 71 72 /** @}57 /** 58 * @} 73 59 */ -
uspace/drv/ohci/hw_struct/endpoint_descriptor.h
r3f3afb9 ra39cfb8 81 81 void ed_init(ed_t *instance, endpoint_t *ep); 82 82 83 static inline void ed_ add_tds(ed_t *instance, td_t *head, td_t *tail)83 static inline void ed_set_td(ed_t *instance, td_t *td) 84 84 { 85 85 assert(instance); 86 uintptr_t pa = addr_to_phys(td); 86 87 instance->td_head = 87 (( addr_to_phys(head)& ED_TDHEAD_PTR_MASK)88 ((pa & ED_TDHEAD_PTR_MASK) 88 89 | (instance->td_head & ~ED_TDHEAD_PTR_MASK)); 89 instance->td_tail = addr_to_phys(tail) & ED_TDTAIL_PTR_MASK; 90 instance->td_tail = pa & ED_TDTAIL_PTR_MASK; 91 } 92 93 static inline void ed_set_end_td(ed_t *instance, td_t *td) 94 { 95 assert(instance); 96 uintptr_t pa = addr_to_phys(td); 97 instance->td_tail = pa & ED_TDTAIL_PTR_MASK; 90 98 } 91 99 -
uspace/drv/ohci/iface.c
r3f3afb9 ra39cfb8 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) { … … 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/root_hub.c
r3f3afb9 ra39cfb8 205 205 * @return Error code. 206 206 */ 207 int rh_init(rh_t *instance, ddf_dev_t *dev,ohci_regs_t *regs) {207 int rh_init(rh_t *instance, ohci_regs_t *regs) { 208 208 assert(instance); 209 //instance->address = -1;210 209 instance->registers = regs; 211 instance->device = dev;212 210 instance->port_count = 213 211 (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK; 214 212 rh_init_descriptors(instance); 215 213 // set port power mode to no-power-switching 216 instance->registers->rh_desc_a = 217 instance->registers->rh_desc_a | (1<<9); 214 instance->registers->rh_desc_a |= RHDA_NPS_FLAG; 218 215 219 216 usb_log_info("OHCI root hub with %d ports.\n", instance->port_count); 220 221 //start generic usb hub driver222 223 /* TODO: implement */224 217 return EOK; 225 218 } … … 237 230 assert(request); 238 231 int opResult; 239 if (request-> transfer_type == USB_TRANSFER_CONTROL) {232 if (request->ep->transfer_type == USB_TRANSFER_CONTROL) { 240 233 usb_log_info("Root hub got CONTROL packet\n"); 241 234 opResult = process_ctrl_request(instance, request); 242 } else if (request-> transfer_type == USB_TRANSFER_INTERRUPT) {235 } else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) { 243 236 usb_log_info("Root hub got INTERRUPT packet\n"); 244 237 void * buffer; 245 238 create_interrupt_mask(instance, &buffer, 246 239 &(request->transfered_size)); 247 memcpy(request-> transport_buffer, buffer,240 memcpy(request->data_buffer, buffer, 248 241 request->transfered_size); 249 242 opResult = EOK; … … 374 367 if (port < 1 || port > instance->port_count) 375 368 return EINVAL; 376 uint32_t * uint32_buffer = (uint32_t*) request-> transport_buffer;369 uint32_t * uint32_buffer = (uint32_t*) request->data_buffer; 377 370 request->transfered_size = 4; 378 371 uint32_buffer[0] = instance->registers->rh_port_status[port - 1]; … … 400 393 static int process_get_hub_status_request(rh_t *instance, 401 394 usb_transfer_batch_t * request) { 402 uint32_t * uint32_buffer = (uint32_t*) request-> transport_buffer;395 uint32_t * uint32_buffer = (uint32_t*) request->data_buffer; 403 396 request->transfered_size = 4; 404 397 //bits, 0,1,16,17 … … 550 543 } 551 544 request->transfered_size = size; 552 memcpy(request-> transport_buffer, result_descriptor, size);545 memcpy(request->data_buffer, result_descriptor, size); 553 546 if (del) 554 547 free(result_descriptor); … … 571 564 if (request->buffer_size != 1) 572 565 return EINVAL; 573 request-> transport_buffer[0] = 1;566 request->data_buffer[0] = 1; 574 567 request->transfered_size = 1; 575 568 return EOK; -
uspace/drv/ohci/root_hub.h
r3f3afb9 ra39cfb8 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; … … 58 56 } rh_t; 59 57 60 int rh_init(rh_t *instance, ddf_dev_t *dev,ohci_regs_t *regs);58 int rh_init(rh_t *instance, ohci_regs_t *regs); 61 59 62 60 int rh_request(rh_t *instance, usb_transfer_batch_t *request); -
uspace/drv/uhci-hcd/batch.c
r3f3afb9 ra39cfb8 30 30 */ 31 31 /** @file 32 * @brief UHCI driver USB trans actionstructure32 * @brief UHCI driver USB transfer structure 33 33 */ 34 34 #include <errno.h> … … 45 45 #define DEFAULT_ERROR_COUNT 3 46 46 47 typedef struct uhci_ batch {47 typedef struct uhci_transfer_batch { 48 48 qh_t *qh; 49 49 td_t *tds; 50 size_t transfers; 51 } uhci_batch_t; 50 void *device_buffer; 51 size_t td_count; 52 } uhci_transfer_batch_t; 53 /*----------------------------------------------------------------------------*/ 54 static void uhci_transfer_batch_dispose(void *uhci_batch) 55 { 56 uhci_transfer_batch_t *instance = uhci_batch; 57 assert(instance); 58 free32(instance->device_buffer); 59 free(instance); 60 } 61 /*----------------------------------------------------------------------------*/ 52 62 53 63 static void batch_control(usb_transfer_batch_t *instance, 54 64 usb_packet_id data_stage, usb_packet_id status_stage); 55 65 static void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid); 56 static void batch_call_in_and_dispose(usb_transfer_batch_t *instance);57 static void batch_call_out_and_dispose(usb_transfer_batch_t *instance);58 59 66 60 67 /** Allocate memory and initialize internal data structure. 61 68 * 62 69 * @param[in] fun DDF function to pass to callback. 63 * @param[in] target Device and endpoint target of the transaction. 64 * @param[in] transfer_type Interrupt, Control or Bulk. 65 * @param[in] max_packet_size maximum allowed size of data transfers. 66 * @param[in] speed Speed of the transaction. 70 * @param[in] ep Communication target 67 71 * @param[in] buffer Data source/destination. 68 72 * @param[in] size Size of the buffer. 69 73 * @param[in] setup_buffer Setup data source (if not NULL) 70 74 * @param[in] setup_size Size of setup_buffer (should be always 8) 71 * @param[in] func_in function to call on inbound trans actioncompletion72 * @param[in] func_out function to call on outbound trans actioncompletion75 * @param[in] func_in function to call on inbound transfer completion 76 * @param[in] func_out function to call on outbound transfer completion 73 77 * @param[in] arg additional parameter to func_in or func_out 74 * @param[in] ep Pointer to endpoint toggle management structure. 75 * @return Valid pointer if all substructures were successfully created, 78 * @return Valid pointer if all structures were successfully created, 76 79 * NULL otherwise. 77 80 * 78 * Determines the number of needed transfer s (TDs). Prepares a transport buffer79 * (that is accessible by the hardware). Initializes parameters needed for the80 * transactionand callback.81 * Determines the number of needed transfer descriptors (TDs). 82 * Prepares a transport buffer (that is accessible by the hardware). 83 * Initializes parameters needed for the transfer and callback. 81 84 */ 82 85 usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep, … … 92 95 if (ptr == NULL) { \ 93 96 usb_log_error(message); \ 94 if ( instance) { \95 batch_dispose(instance); \97 if (uhci_data) { \ 98 uhci_transfer_batch_dispose(uhci_data); \ 96 99 } \ 97 100 return NULL; \ 98 101 } else (void)0 99 102 103 uhci_transfer_batch_t *uhci_data = 104 malloc(sizeof(uhci_transfer_batch_t)); 105 CHECK_NULL_DISPOSE_RETURN(uhci_data, 106 "Failed to allocate UHCI batch.\n"); 107 bzero(uhci_data, sizeof(uhci_transfer_batch_t)); 108 109 uhci_data->td_count = 110 (buffer_size + ep->max_packet_size - 1) / ep->max_packet_size; 111 if (ep->transfer_type == USB_TRANSFER_CONTROL) { 112 uhci_data->td_count += 2; 113 } 114 115 assert((sizeof(td_t) % 16) == 0); 116 const size_t total_size = (sizeof(td_t) * uhci_data->td_count) 117 + sizeof(qh_t) + setup_size + buffer_size; 118 uhci_data->device_buffer = malloc32(total_size); 119 CHECK_NULL_DISPOSE_RETURN(uhci_data->device_buffer, 120 "Failed to allocate UHCI buffer.\n"); 121 bzero(uhci_data->device_buffer, total_size); 122 123 uhci_data->tds = uhci_data->device_buffer; 124 uhci_data->qh = 125 (uhci_data->device_buffer + (sizeof(td_t) * uhci_data->td_count)); 126 127 qh_init(uhci_data->qh); 128 qh_set_element_td(uhci_data->qh, uhci_data->tds); 129 100 130 usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t)); 101 131 CHECK_NULL_DISPOSE_RETURN(instance, 102 132 "Failed to allocate batch instance.\n"); 133 void *setup = 134 uhci_data->device_buffer + (sizeof(td_t) * uhci_data->td_count) 135 + sizeof(qh_t); 136 void *data_buffer = setup + setup_size; 103 137 usb_target_t target = 104 138 { .address = ep->address, .endpoint = ep->endpoint }; 105 usb_transfer_batch_init(instance, target, ep->transfer_type, ep->speed, 106 ep->max_packet_size, buffer, NULL, buffer_size, NULL, setup_size, 107 func_in, func_out, arg, fun, ep, NULL); 108 109 110 uhci_batch_t *data = malloc(sizeof(uhci_batch_t)); 111 CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n"); 112 bzero(data, sizeof(uhci_batch_t)); 113 instance->private_data = data; 114 115 data->transfers = 116 (buffer_size + ep->max_packet_size - 1) / ep->max_packet_size; 117 if (ep->transfer_type == USB_TRANSFER_CONTROL) { 118 data->transfers += 2; 119 } 120 121 data->tds = malloc32(sizeof(td_t) * data->transfers); 122 CHECK_NULL_DISPOSE_RETURN( 123 data->tds, "Failed to allocate transfer descriptors.\n"); 124 bzero(data->tds, sizeof(td_t) * data->transfers); 125 126 data->qh = malloc32(sizeof(qh_t)); 127 CHECK_NULL_DISPOSE_RETURN(data->qh, 128 "Failed to allocate batch queue head.\n"); 129 qh_init(data->qh); 130 qh_set_element_td(data->qh, addr_to_phys(data->tds)); 131 132 if (buffer_size > 0) { 133 instance->transport_buffer = malloc32(buffer_size); 134 CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer, 135 "Failed to allocate device accessible buffer.\n"); 136 } 137 138 if (setup_size > 0) { 139 instance->setup_buffer = malloc32(setup_size); 140 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer, 141 "Failed to allocate device accessible setup buffer.\n"); 142 memcpy(instance->setup_buffer, setup_buffer, setup_size); 143 } 144 139 usb_transfer_batch_init(instance, ep, buffer, data_buffer, buffer_size, 140 setup, setup_size, func_in, func_out, arg, fun, 141 uhci_data, uhci_transfer_batch_dispose); 142 143 memcpy(instance->setup_buffer, setup_buffer, setup_size); 145 144 usb_log_debug("Batch(%p) %d:%d memory structures ready.\n", 146 145 instance, target.address, target.endpoint); … … 154 153 * 155 154 * Walk all TDs. Stop with false if there is an active one (it is to be 156 * processed). Stop with true if an error is found. Return true if the last T S155 * processed). Stop with true if an error is found. Return true if the last TD 157 156 * is reached. 158 157 */ … … 160 159 { 161 160 assert(instance); 162 uhci_ batch_t *data = instance->private_data;161 uhci_transfer_batch_t *data = instance->private_data; 163 162 assert(data); 164 163 165 164 usb_log_debug2("Batch(%p) checking %d transfer(s) for completion.\n", 166 instance, data->t ransfers);165 instance, data->td_count); 167 166 instance->transfered_size = 0; 168 167 size_t i = 0; 169 for (;i < data->t ransfers; ++i) {168 for (;i < data->td_count; ++i) { 170 169 if (td_is_active(&data->tds[i])) { 171 170 return false; … … 177 176 instance, i, data->tds[i].status); 178 177 td_print_status(&data->tds[i]); 178 179 179 assert(instance->ep != NULL); 180 181 180 endpoint_toggle_set(instance->ep, 182 181 td_toggle(&data->tds[i])); … … 195 194 } 196 195 /*----------------------------------------------------------------------------*/ 197 /** Prepares control write trans action.198 * 199 * @param[in] instance Batch structure to use. 200 * 201 * Uses gener circontrol function with pids OUT and IN.196 /** Prepares control write transfer. 197 * 198 * @param[in] instance Batch structure to use. 199 * 200 * Uses generic control function with pids OUT and IN. 202 201 */ 203 202 void batch_control_write(usb_transfer_batch_t *instance) … … 205 204 assert(instance); 206 205 /* We are data out, we are supposed to provide data */ 207 memcpy(instance->transport_buffer, instance->buffer, 208 instance->buffer_size); 206 memcpy(instance->data_buffer, instance->buffer, instance->buffer_size); 209 207 batch_control(instance, USB_PID_OUT, USB_PID_IN); 210 instance->next_step = batch_call_out_and_dispose;208 instance->next_step = usb_transfer_batch_call_out_and_dispose; 211 209 usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance); 212 210 } 213 211 /*----------------------------------------------------------------------------*/ 214 /** Prepares control read trans action.212 /** Prepares control read transfer. 215 213 * 216 214 * @param[in] instance Batch structure to use. … … 222 220 assert(instance); 223 221 batch_control(instance, USB_PID_IN, USB_PID_OUT); 224 instance->next_step = batch_call_in_and_dispose;222 instance->next_step = usb_transfer_batch_call_in_and_dispose; 225 223 usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance); 226 224 } 227 225 /*----------------------------------------------------------------------------*/ 228 /** Prepare interrupt in trans action.229 * 230 * @param[in] instance Batch structure to use. 231 * 232 * Data trans actionwith PID_IN.226 /** Prepare interrupt in transfer. 227 * 228 * @param[in] instance Batch structure to use. 229 * 230 * Data transfer with PID_IN. 233 231 */ 234 232 void batch_interrupt_in(usb_transfer_batch_t *instance) 235 233 { 236 234 assert(instance); 237 instance->direction = USB_DIRECTION_IN;238 235 batch_data(instance, USB_PID_IN); 239 instance->next_step = batch_call_in_and_dispose;236 instance->next_step = usb_transfer_batch_call_in_and_dispose; 240 237 usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance); 241 238 } 242 239 /*----------------------------------------------------------------------------*/ 243 /** Prepare interrupt out trans action.244 * 245 * @param[in] instance Batch structure to use. 246 * 247 * Data trans actionwith PID_OUT.240 /** Prepare interrupt out transfer. 241 * 242 * @param[in] instance Batch structure to use. 243 * 244 * Data transfer with PID_OUT. 248 245 */ 249 246 void batch_interrupt_out(usb_transfer_batch_t *instance) 250 247 { 251 248 assert(instance); 252 instance->direction = USB_DIRECTION_OUT;253 249 /* We are data out, we are supposed to provide data */ 254 memcpy(instance->transport_buffer, instance->buffer, 255 instance->buffer_size); 250 memcpy(instance->data_buffer, instance->buffer, instance->buffer_size); 256 251 batch_data(instance, USB_PID_OUT); 257 instance->next_step = batch_call_out_and_dispose;252 instance->next_step = usb_transfer_batch_call_out_and_dispose; 258 253 usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance); 259 254 } 260 255 /*----------------------------------------------------------------------------*/ 261 /** Prepare bulk in trans action.262 * 263 * @param[in] instance Batch structure to use. 264 * 265 * Data trans actionwith PID_IN.256 /** Prepare bulk in transfer. 257 * 258 * @param[in] instance Batch structure to use. 259 * 260 * Data transfer with PID_IN. 266 261 */ 267 262 void batch_bulk_in(usb_transfer_batch_t *instance) … … 269 264 assert(instance); 270 265 batch_data(instance, USB_PID_IN); 271 instance->direction = USB_DIRECTION_IN; 272 instance->next_step = batch_call_in_and_dispose; 266 instance->next_step = usb_transfer_batch_call_in_and_dispose; 273 267 usb_log_debug("Batch(%p) BULK IN initialized.\n", instance); 274 268 } 275 269 /*----------------------------------------------------------------------------*/ 276 /** Prepare bulk out trans action.277 * 278 * @param[in] instance Batch structure to use. 279 * 280 * Data trans actionwith PID_OUT.270 /** Prepare bulk out transfer. 271 * 272 * @param[in] instance Batch structure to use. 273 * 274 * Data transfer with PID_OUT. 281 275 */ 282 276 void batch_bulk_out(usb_transfer_batch_t *instance) 283 277 { 284 278 assert(instance); 285 instance->direction = USB_DIRECTION_OUT;286 279 /* We are data out, we are supposed to provide data */ 287 memcpy(instance->transport_buffer, instance->buffer, 288 instance->buffer_size); 280 memcpy(instance->data_buffer, instance->buffer, instance->buffer_size); 289 281 batch_data(instance, USB_PID_OUT); 290 instance->next_step = batch_call_out_and_dispose;282 instance->next_step = usb_transfer_batch_call_out_and_dispose; 291 283 usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance); 292 284 } 293 285 /*----------------------------------------------------------------------------*/ 294 /** Prepare generic data trans action295 * 296 * @param[in] instance Batch structure to use. 297 * @param[in] pid Pid to use for data trans fers.298 * 299 * Packets with alternating toggle bit and supplied pid value.286 /** Prepare generic data transfer 287 * 288 * @param[in] instance Batch structure to use. 289 * @param[in] pid Pid to use for data transactions. 290 * 291 * Transactions with alternating toggle bit and supplied pid value. 300 292 * The last transfer is marked with IOC flag. 301 293 */ … … 303 295 { 304 296 assert(instance); 305 uhci_ batch_t *data = instance->private_data;297 uhci_transfer_batch_t *data = instance->private_data; 306 298 assert(data); 307 299 308 const bool low_speed = instance-> speed == USB_SPEED_LOW;300 const bool low_speed = instance->ep->speed == USB_SPEED_LOW; 309 301 int toggle = endpoint_toggle_get(instance->ep); 310 302 assert(toggle == 0 || toggle == 1); 311 303 312 size_t t ransfer= 0;304 size_t td = 0; 313 305 size_t remain_size = instance->buffer_size; 306 char *buffer = instance->data_buffer; 314 307 while (remain_size > 0) { 315 char *trans_data =316 instance->transport_buffer + instance->buffer_size317 - remain_size;318 319 308 const size_t packet_size = 320 (instance->max_packet_size > remain_size) ? 321 remain_size : instance->max_packet_size; 322 323 td_t *next_transfer = (transfer + 1 < data->transfers) 324 ? &data->tds[transfer + 1] : NULL; 325 326 assert(transfer < data->transfers); 309 (instance->ep->max_packet_size > remain_size) ? 310 remain_size : instance->ep->max_packet_size; 311 312 td_t *next_td = (td + 1 < data->td_count) 313 ? &data->tds[td + 1] : NULL; 314 315 316 usb_target_t target = 317 { instance->ep->address, instance->ep->endpoint }; 318 319 assert(td < data->td_count); 320 td_init( 321 &data->tds[td], DEFAULT_ERROR_COUNT, packet_size, 322 toggle, false, low_speed, target, pid, buffer, next_td); 323 324 ++td; 325 toggle = 1 - toggle; 326 buffer += packet_size; 327 327 assert(packet_size <= remain_size); 328 329 td_init(330 &data->tds[transfer], DEFAULT_ERROR_COUNT, packet_size,331 toggle, false, low_speed, instance->target, pid, trans_data,332 next_transfer);333 334 335 toggle = 1 - toggle;336 328 remain_size -= packet_size; 337 ++transfer;338 329 } 339 td_set_ioc(&data->tds[t ransfer- 1]);330 td_set_ioc(&data->tds[td - 1]); 340 331 endpoint_toggle_set(instance->ep, toggle); 341 332 } 342 333 /*----------------------------------------------------------------------------*/ 343 /** Prepare generic control trans action344 * 345 * @param[in] instance Batch structure to use. 346 * @param[in] data_stage Pid to use for data t ransfers.347 * @param[in] status_stage Pid to use for data t ransfers.334 /** Prepare generic control transfer 335 * 336 * @param[in] instance Batch structure to use. 337 * @param[in] data_stage Pid to use for data tds. 338 * @param[in] status_stage Pid to use for data tds. 348 339 * 349 340 * Setup stage with toggle 0 and USB_PID_SETUP. … … 356 347 { 357 348 assert(instance); 358 uhci_ batch_t *data = instance->private_data;349 uhci_transfer_batch_t *data = instance->private_data; 359 350 assert(data); 360 assert(data->transfers >= 2); 361 362 const bool low_speed = instance->speed == USB_SPEED_LOW; 363 int toggle = 0; 351 assert(data->td_count >= 2); 352 353 const bool low_speed = instance->ep->speed == USB_SPEED_LOW; 354 const usb_target_t target = 355 { instance->ep->address, instance->ep->endpoint }; 356 364 357 /* setup stage */ 365 358 td_init( 366 data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, toggle, false,367 low_speed, instance->target, USB_PID_SETUP, instance->setup_buffer,359 data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, 0, false, 360 low_speed, target, USB_PID_SETUP, instance->setup_buffer, 368 361 &data->tds[1]); 369 362 370 363 /* data stage */ 371 size_t transfer = 1; 364 size_t td = 1; 365 unsigned toggle = 1; 372 366 size_t remain_size = instance->buffer_size; 367 char *buffer = instance->data_buffer; 373 368 while (remain_size > 0) { 374 char *control_data = 375 instance->transport_buffer + instance->buffer_size 376 - remain_size; 377 369 const size_t packet_size = 370 (instance->ep->max_packet_size > remain_size) ? 371 remain_size : instance->ep->max_packet_size; 372 373 td_init( 374 &data->tds[td], DEFAULT_ERROR_COUNT, packet_size, 375 toggle, false, low_speed, target, data_stage, 376 buffer, &data->tds[td + 1]); 377 378 ++td; 378 379 toggle = 1 - toggle; 379 380 const size_t packet_size = 381 (instance->max_packet_size > remain_size) ? 382 remain_size : instance->max_packet_size; 383 384 td_init( 385 &data->tds[transfer], DEFAULT_ERROR_COUNT, packet_size, 386 toggle, false, low_speed, instance->target, data_stage, 387 control_data, &data->tds[transfer + 1]); 388 389 ++transfer; 390 assert(transfer < data->transfers); 380 buffer += packet_size; 381 assert(td < data->td_count); 391 382 assert(packet_size <= remain_size); 392 383 remain_size -= packet_size; … … 394 385 395 386 /* status stage */ 396 assert(t ransfer == data->transfers- 1);387 assert(td == data->td_count - 1); 397 388 398 389 td_init( 399 &data->tds[t ransfer], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,400 instance->target, status_stage, NULL, NULL);401 td_set_ioc(&data->tds[t ransfer]);390 &data->tds[td], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed, 391 target, status_stage, NULL, NULL); 392 td_set_ioc(&data->tds[td]); 402 393 403 394 usb_log_debug2("Control last TD status: %x.\n", 404 data->tds[transfer].status); 405 } 406 /*----------------------------------------------------------------------------*/ 395 data->tds[td].status); 396 } 397 /*----------------------------------------------------------------------------*/ 398 /** Provides access to QH data structure. 399 * @param[in] instance Batch pointer to use. 400 * @return Pointer to the QH used by the batch. 401 */ 407 402 qh_t * batch_qh(usb_transfer_batch_t *instance) 408 403 { 409 404 assert(instance); 410 uhci_ batch_t *data = instance->private_data;405 uhci_transfer_batch_t *data = instance->private_data; 411 406 assert(data); 412 407 return data->qh; 413 408 } 414 /*----------------------------------------------------------------------------*/415 /** Helper function calls callback and correctly disposes of batch structure.416 *417 * @param[in] instance Batch structure to use.418 */419 void batch_call_in_and_dispose(usb_transfer_batch_t *instance)420 {421 assert(instance);422 usb_transfer_batch_call_in(instance);423 batch_dispose(instance);424 }425 /*----------------------------------------------------------------------------*/426 /** Helper function calls callback and correctly disposes of batch structure.427 *428 * @param[in] instance Batch structure to use.429 */430 void batch_call_out_and_dispose(usb_transfer_batch_t *instance)431 {432 assert(instance);433 usb_transfer_batch_call_out(instance);434 batch_dispose(instance);435 }436 /*----------------------------------------------------------------------------*/437 /** Correctly dispose all used data structures.438 *439 * @param[in] instance Batch structure to use.440 */441 void batch_dispose(usb_transfer_batch_t *instance)442 {443 assert(instance);444 uhci_batch_t *data = instance->private_data;445 assert(data);446 usb_log_debug("Batch(%p) disposing.\n", instance);447 /* free32 is NULL safe */448 free32(data->tds);449 free32(data->qh);450 free32(instance->setup_buffer);451 free32(instance->transport_buffer);452 free(data);453 free(instance);454 }455 409 /** 456 410 * @} -
uspace/drv/uhci-hcd/batch.h
r3f3afb9 ra39cfb8 30 30 */ 31 31 /** @file 32 * @brief UHCI driver USB tran saction structure32 * @brief UHCI driver USB tranfer helper functions 33 33 */ 34 34 #ifndef DRV_UHCI_BATCH_H -
uspace/drv/uhci-hcd/hc.c
r3f3afb9 ra39cfb8 66 66 static int hc_interrupt_emulator(void *arg); 67 67 static int hc_debug_checker(void *arg); 68 #if 069 static bool usb_is_allowed(70 bool low_speed, usb_transfer_type_t transfer, size_t size);71 #endif72 68 /*----------------------------------------------------------------------------*/ 73 69 /** Initialize UHCI hcd driver structure … … 89 85 int ret; 90 86 91 #define CHECK_RET_ DEST_FUN_RETURN(ret, message...) \87 #define CHECK_RET_RETURN(ret, message...) \ 92 88 if (ret != EOK) { \ 93 89 usb_log_error(message); \ 94 if (instance->ddf_instance) \95 ddf_fun_destroy(instance->ddf_instance); \96 90 return ret; \ 97 91 } else (void) 0 … … 99 93 instance->hw_interrupts = interrupts; 100 94 instance->hw_failures = 0; 101 102 /* Setup UHCI function. */103 instance->ddf_instance = fun;104 95 105 96 /* allow access to hc control registers */ 106 97 regs_t *io; 107 98 ret = pio_enable(regs, reg_size, (void**)&io); 108 CHECK_RET_ DEST_FUN_RETURN(ret,99 CHECK_RET_RETURN(ret, 109 100 "Failed(%d) to gain access to registers at %p: %s.\n", 110 ret, str_error(ret), io);101 ret, io, str_error(ret)); 111 102 instance->registers = io; 112 103 usb_log_debug("Device registers at %p(%u) accessible.\n", … … 114 105 115 106 ret = hc_init_mem_structures(instance); 116 CHECK_RET_DEST_FUN_RETURN(ret, 117 "Failed to initialize UHCI memory structures.\n"); 107 CHECK_RET_RETURN(ret, 108 "Failed(%d) to initialize UHCI memory structures: %s.\n", 109 ret, str_error(ret)); 118 110 119 111 hc_init_hw(instance); 120 112 if (!interrupts) { 121 instance-> cleaner =113 instance->interrupt_emulator = 122 114 fibril_create(hc_interrupt_emulator, instance); 123 fibril_add_ready(instance->cleaner); 124 } else { 125 /* TODO: enable interrupts here */ 126 } 127 128 instance->debug_checker = 129 fibril_create(hc_debug_checker, instance); 130 // fibril_add_ready(instance->debug_checker); 115 fibril_add_ready(instance->interrupt_emulator); 116 } 117 (void)hc_debug_checker; 131 118 132 119 return EOK; … … 228 215 /* Set all frames to point to the first queue head */ 229 216 const uint32_t queue = 230 instance->transfers_interrupt.queue_head_pa231 | LINK_POINTER_QUEUE_HEAD_FLAG;217 LINK_POINTER_QH(addr_to_phys( 218 instance->transfers_interrupt.queue_head)); 232 219 233 220 unsigned i = 0; … … 236 223 } 237 224 238 /* Init device keeper */225 /* Init device keeper */ 239 226 usb_device_keeper_init(&instance->manager); 240 227 usb_log_debug("Initialized device manager.\n"); … … 329 316 330 317 transfer_list_t *list = 331 instance->transfers[batch-> speed][batch->transfer_type];318 instance->transfers[batch->ep->speed][batch->ep->transfer_type]; 332 319 assert(list); 333 320 transfer_list_add_batch(list, batch); … … 479 466 #undef QH 480 467 } 481 /*----------------------------------------------------------------------------*/482 /** Check transfers for USB validity483 *484 * @param[in] low_speed Transfer speed.485 * @param[in] transfer Transer type486 * @param[in] size Size of data packets487 * @return True if transaction is allowed by USB specs, false otherwise488 */489 #if 0490 bool usb_is_allowed(491 bool low_speed, usb_transfer_type_t transfer, size_t size)492 {493 /* see USB specification chapter 5.5-5.8 for magic numbers used here */494 switch(transfer)495 {496 case USB_TRANSFER_ISOCHRONOUS:497 return (!low_speed && size < 1024);498 case USB_TRANSFER_INTERRUPT:499 return size <= (low_speed ? 8 : 64);500 case USB_TRANSFER_CONTROL: /* device specifies its own max size */501 return (size <= (low_speed ? 8 : 64));502 case USB_TRANSFER_BULK: /* device specifies its own max size */503 return (!low_speed && size <= 64);504 }505 return false;506 }507 #endif508 468 /** 509 469 * @} -
uspace/drv/uhci-hcd/hc.h
r3f3afb9 ra39cfb8 48 48 #include "transfer_list.h" 49 49 50 /** UHCI I/O registers layout */ 50 51 typedef struct uhci_regs { 52 /** Command register, controls HC behaviour */ 51 53 uint16_t usbcmd; 52 54 #define UHCI_CMD_MAX_PACKET (1 << 7) … … 59 61 #define UHCI_CMD_RUN_STOP (1 << 0) 60 62 63 /** Status register, 1 means interrupt is asserted (if enabled) */ 61 64 uint16_t usbsts; 62 65 #define UHCI_STATUS_HALTED (1 << 5) … … 67 70 #define UHCI_STATUS_INTERRUPT (1 << 0) 68 71 72 /** Interrupt enabled registers */ 69 73 uint16_t usbintr; 70 74 #define UHCI_INTR_SHORT_PACKET (1 << 3) … … 73 77 #define UHCI_INTR_CRC (1 << 0) 74 78 79 /** Register stores frame number used in SOF packet */ 75 80 uint16_t frnum; 81 82 /** Pointer(physical) to the Frame List */ 76 83 uint32_t flbaseadd; 84 85 /** SOF modification to match external timers */ 77 86 uint8_t sofmod; 78 87 } regs_t; … … 83 92 #define UHCI_ALLOWED_HW_FAIL 5 84 93 94 /* Main HC driver structure */ 85 95 typedef struct hc { 96 /** USB bus driver, devices and addresses */ 86 97 usb_device_keeper_t manager; 98 /** USB bus driver, endpoints */ 87 99 usb_endpoint_manager_t ep_manager; 88 100 101 /** Addresses of I/O registers */ 89 102 regs_t *registers; 90 103 104 /** Frame List contains 1024 link pointers */ 91 105 link_pointer_t *frame_list; 92 106 107 /** List and queue of interrupt transfers */ 108 transfer_list_t transfers_interrupt; 109 /** List and queue of low speed control transfers */ 110 transfer_list_t transfers_control_slow; 111 /** List and queue of full speed bulk transfers */ 93 112 transfer_list_t transfers_bulk_full; 113 /** List and queue of full speed control transfers */ 94 114 transfer_list_t transfers_control_full; 95 transfer_list_t transfers_control_slow;96 transfer_list_t transfers_interrupt;97 115 116 /** Pointer table to the above lists, helps during scheduling */ 98 117 transfer_list_t *transfers[2][4]; 99 118 119 /** Code to be executed in kernel interrupt handler */ 100 120 irq_code_t interrupt_code; 101 121 102 fid_t cleaner; 103 fid_t debug_checker; 122 /** Fibril periodically checking status register*/ 123 fid_t interrupt_emulator; 124 125 /** Indicator of hw interrupts availability */ 104 126 bool hw_interrupts; 127 128 /** Number of hw failures detected. */ 105 129 unsigned hw_failures; 106 107 ddf_fun_t *ddf_instance;108 130 } hc_t; 109 131 -
uspace/drv/uhci-hcd/hw_struct/queue_head.h
r3f3afb9 ra39cfb8 34 34 #ifndef DRV_UHCI_QH_H 35 35 #define DRV_UHCI_QH_H 36 37 /* libc */38 36 #include <assert.h> 39 37 40 38 #include "link_pointer.h" 39 #include "transfer_descriptor.h" 40 #include "utils/malloc32.h" 41 41 42 /** This structure is defined in UHCI design guide p. 31 */ 42 43 typedef struct queue_head { 44 /** Pointer to the next entity (another QH or TD */ 43 45 volatile link_pointer_t next; 46 /** Pointer to the contained entities (execution controlled by vertical flag*/ 44 47 volatile link_pointer_t element; 45 48 } __attribute__((packed)) qh_t; … … 64 67 * @param[in] pa Physical address of the next queue head. 65 68 * 66 * Adds proper flag. If the pointer is NULL or terminal, sets next to terminal 67 * NULL. 69 * Adds proper flag. If the pointer is NULL, sets next to terminal NULL. 68 70 */ 69 static inline void qh_set_next_qh(qh_t *instance, uint32_t pa)71 static inline void qh_set_next_qh(qh_t *instance, qh_t *next) 70 72 { 71 /* Address is valid and not terminal */72 if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {73 uint32_t pa = addr_to_phys(next); 74 if (pa) { 73 75 instance->next = LINK_POINTER_QH(pa); 74 76 } else { … … 80 82 * 81 83 * @param[in] instance qh_t structure to initialize. 82 * @param[in] pa Physical address of the next queue head.83 *84 * Adds proper flag. If the pointer is NULL or terminal, sets element85 * to terminal NULL.86 */87 static inline void qh_set_element_qh(qh_t *instance, uint32_t pa)88 {89 /* Address is valid and not terminal */90 if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {91 instance->element = LINK_POINTER_QH(pa);92 } else {93 instance->element = LINK_POINTER_TERM;94 }95 }96 /*----------------------------------------------------------------------------*/97 /** Set queue head element pointer98 *99 * @param[in] instance qh_t structure to initialize.100 84 * @param[in] pa Physical address of the TD structure. 101 85 * 102 * Adds proper flag. If the pointer is NULL or terminal, sets element 103 * to terminal NULL. 86 * Adds proper flag. If the pointer is NULL, sets element to terminal NULL. 104 87 */ 105 static inline void qh_set_element_td(qh_t *instance, uint32_t pa)88 static inline void qh_set_element_td(qh_t *instance, td_t *td) 106 89 { 107 if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) { 90 uint32_t pa = addr_to_phys(td); 91 if (pa) { 108 92 instance->element = LINK_POINTER_TD(pa); 109 93 } else { … … 111 95 } 112 96 } 113 114 97 #endif 115 98 /** -
uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.c
r3f3afb9 ra39cfb8 77 77 78 78 instance->status = 0 79 | ((err_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS) 79 | ((err_count & TD_STATUS_ERROR_COUNT_MASK) 80 << TD_STATUS_ERROR_COUNT_POS) 80 81 | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0) 81 82 | (iso ? TD_STATUS_ISOCHRONOUS_FLAG : 0) … … 89 90 | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS) 90 91 | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0) 91 | ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS) 92 | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS) 92 | ((target.address & TD_DEVICE_ADDRESS_MASK) 93 << TD_DEVICE_ADDRESS_POS) 94 | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) 95 << TD_DEVICE_ENDPOINT_POS) 93 96 | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS); 94 97 … … 114 117 assert(instance); 115 118 116 /* this is hc internal error it should never be reported*/119 /* This is hc internal error it should never be reported. */ 117 120 if ((instance->status & TD_STATUS_ERROR_BIT_STUFF) != 0) 118 121 return EAGAIN; … … 123 126 return EBADCHECKSUM; 124 127 125 /* hc does not end transactionon these, it should never be reported */128 /* HC does not end transactions on these, it should never be reported */ 126 129 if ((instance->status & TD_STATUS_ERROR_NAK) != 0) 127 130 return EAGAIN; 128 131 129 /* buffer overrun or underrun */132 /* Buffer overrun or underrun */ 130 133 if ((instance->status & TD_STATUS_ERROR_BUFFER) != 0) 131 134 return ERANGE; 132 135 133 /* device babble is something serious */136 /* Device babble is something serious */ 134 137 if ((instance->status & TD_STATUS_ERROR_BABBLE) != 0) 135 138 return EIO; 136 139 137 /* stall might represent err count reaching zero or stall response from138 * the device , iserr count reached zero, one of the above is reported*/140 /* Stall might represent err count reaching zero or stall response from 141 * the device. If err count reached zero, one of the above is reported*/ 139 142 if ((instance->status & TD_STATUS_ERROR_STALLED) != 0) 140 143 return ESTALL; -
uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.h
r3f3afb9 ra39cfb8 40 40 #include "link_pointer.h" 41 41 42 /** UHCI Transfer Descriptor*/42 /** Transfer Descriptor, defined in UHCI design guide p. 26 */ 43 43 typedef struct transfer_descriptor { 44 /** Pointer to the next entity (TD or QH) */ 44 45 link_pointer_t next; 45 46 47 /** Status doubleword */ 46 48 volatile uint32_t status; 47 49 #define TD_STATUS_RESERVED_MASK 0xc000f800 48 #define TD_STATUS_SPD_FLAG ( 1 << 29)49 #define TD_STATUS_ERROR_COUNT_POS ( 27 )50 #define TD_STATUS_ERROR_COUNT_MASK ( 0x3 )51 #define TD_STATUS_LOW_SPEED_FLAG ( 1 << 26)52 #define TD_STATUS_ISOCHRONOUS_FLAG ( 1 << 25)53 #define TD_STATUS_IOC_FLAG ( 1 << 24)50 #define TD_STATUS_SPD_FLAG (1 << 29) 51 #define TD_STATUS_ERROR_COUNT_POS 27 52 #define TD_STATUS_ERROR_COUNT_MASK 0x3 53 #define TD_STATUS_LOW_SPEED_FLAG (1 << 26) 54 #define TD_STATUS_ISOCHRONOUS_FLAG (1 << 25) 55 #define TD_STATUS_IOC_FLAG (1 << 24) 54 56 55 #define TD_STATUS_ERROR_ACTIVE ( 1 << 23)56 #define TD_STATUS_ERROR_STALLED ( 1 << 22)57 #define TD_STATUS_ERROR_BUFFER ( 1 << 21)58 #define TD_STATUS_ERROR_BABBLE ( 1 << 20)59 #define TD_STATUS_ERROR_NAK ( 1 << 19)60 #define TD_STATUS_ERROR_CRC ( 1 << 18)61 #define TD_STATUS_ERROR_BIT_STUFF ( 1 << 17)62 #define TD_STATUS_ERROR_RESERVED ( 1 << 16)57 #define TD_STATUS_ERROR_ACTIVE (1 << 23) 58 #define TD_STATUS_ERROR_STALLED (1 << 22) 59 #define TD_STATUS_ERROR_BUFFER (1 << 21) 60 #define TD_STATUS_ERROR_BABBLE (1 << 20) 61 #define TD_STATUS_ERROR_NAK (1 << 19) 62 #define TD_STATUS_ERROR_CRC (1 << 18) 63 #define TD_STATUS_ERROR_BIT_STUFF (1 << 17) 64 #define TD_STATUS_ERROR_RESERVED (1 << 16) 63 65 #define TD_STATUS_ERROR_POS 16 64 #define TD_STATUS_ERROR_MASK ( 0xff )66 #define TD_STATUS_ERROR_MASK 0xff 65 67 66 68 #define TD_STATUS_ACTLEN_POS 0 67 69 #define TD_STATUS_ACTLEN_MASK 0x7ff 68 70 71 /* double word with USB device specific info */ 69 72 volatile uint32_t device; 70 73 #define TD_DEVICE_MAXLEN_POS 21 71 #define TD_DEVICE_MAXLEN_MASK ( 0x7ff )72 #define TD_DEVICE_RESERVED_FLAG ( 1 << 20)73 #define TD_DEVICE_DATA_TOGGLE_ONE_FLAG ( 1 << 19)74 #define TD_DEVICE_MAXLEN_MASK 0x7ff 75 #define TD_DEVICE_RESERVED_FLAG (1 << 20) 76 #define TD_DEVICE_DATA_TOGGLE_ONE_FLAG (1 << 19) 74 77 #define TD_DEVICE_ENDPOINT_POS 15 75 #define TD_DEVICE_ENDPOINT_MASK ( 0xf )78 #define TD_DEVICE_ENDPOINT_MASK 0xf 76 79 #define TD_DEVICE_ADDRESS_POS 8 77 #define TD_DEVICE_ADDRESS_MASK ( 0x7f )80 #define TD_DEVICE_ADDRESS_MASK 0x7f 78 81 #define TD_DEVICE_PID_POS 0 79 #define TD_DEVICE_PID_MASK ( 0xff )82 #define TD_DEVICE_PID_MASK 0xff 80 83 84 /** Pointer(physical) to the beginning of the transaction's buffer */ 81 85 volatile uint32_t buffer_ptr; 82 86 83 /* there is 16 bytes of data available here, according to UHCI 84 * Design guide, according to linux kernel the hardware does not care, 85 * it just needs to be aligned, we don't use it anyway 87 /* According to UHCI design guide, there is 16 bytes of 88 * data available here. 89 * According to linux kernel the hardware does not care, 90 * it just needs to be aligned. We don't use it anyway. 86 91 */ 87 92 } __attribute__((packed)) td_t; -
uspace/drv/uhci-hcd/iface.c
r3f3afb9 ra39cfb8 148 148 assert(hc); 149 149 const size_t size = max_packet_size; 150 int ret;151 150 usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address); 152 151 if (speed >= USB_SPEED_MAX) { … … 157 156 usb_str_speed(speed), direction, size, max_packet_size, interval); 158 157 159 160 endpoint_t *ep = malloc(sizeof(endpoint_t)); 161 if (ep == NULL) 162 return ENOMEM; 163 ret = endpoint_init(ep, address, endpoint, direction, 164 transfer_type, speed, max_packet_size); 165 if (ret != EOK) { 166 free(ep); 167 return ret; 168 } 169 170 ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size); 171 if (ret != EOK) { 172 endpoint_destroy(ep); 173 } 174 return ret; 158 return usb_endpoint_manager_add_ep(&hc->ep_manager, address, endpoint, 159 direction, transfer_type, speed, max_packet_size, size); 175 160 } 176 161 /*----------------------------------------------------------------------------*/ … … 210 195 ret = hc_schedule(hc, batch); 211 196 if (ret != EOK) { 212 batch_dispose(batch);197 usb_transfer_batch_dispose(batch); 213 198 } 214 199 return ret; … … 238 223 ret = hc_schedule(hc, batch); 239 224 if (ret != EOK) { 240 batch_dispose(batch);225 usb_transfer_batch_dispose(batch); 241 226 } 242 227 return ret; … … 266 251 ret = hc_schedule(hc, batch); 267 252 if (ret != EOK) { 268 batch_dispose(batch);253 usb_transfer_batch_dispose(batch); 269 254 } 270 255 return ret; … … 294 279 ret = hc_schedule(hc, batch); 295 280 if (ret != EOK) { 296 batch_dispose(batch);281 usb_transfer_batch_dispose(batch); 297 282 } 298 283 return ret; … … 327 312 ret = hc_schedule(hc, batch); 328 313 if (ret != EOK) { 329 batch_dispose(batch);314 usb_transfer_batch_dispose(batch); 330 315 } 331 316 return ret; … … 359 344 ret = hc_schedule(hc, batch); 360 345 if (ret != EOK) { 361 batch_dispose(batch);346 usb_transfer_batch_dispose(batch); 362 347 } 363 348 return ret; -
uspace/drv/uhci-hcd/main.c
r3f3afb9 ra39cfb8 39 39 #include <usb/debug.h> 40 40 41 #include "iface.h"42 41 #include "uhci.h" 43 42 … … 62 61 int uhci_add_device(ddf_dev_t *device) 63 62 { 64 usb_log_debug ("uhci_add_device() called\n");63 usb_log_debug2("uhci_add_device() called\n"); 65 64 assert(device); 65 66 66 uhci_t *uhci = malloc(sizeof(uhci_t)); 67 67 if (uhci == NULL) { … … 72 72 int ret = uhci_init(uhci, device); 73 73 if (ret != EOK) { 74 usb_log_error("Failed to initialize UHCI driver: %s.\n",75 str_error(ret));74 usb_log_error("Failed(%d) to initialize UHCI driver: %s.\n", 75 ret, str_error(ret)); 76 76 return ret; 77 77 } … … 85 85 /** Initialize global driver structures (NONE). 86 86 * 87 * @param[in] argc N mber of arguments in argv vector (ignored).87 * @param[in] argc Number of arguments in argv vector (ignored). 88 88 * @param[in] argv Cmdline argument vector (ignored). 89 89 * @return Error code. … … 94 94 { 95 95 printf(NAME ": HelenOS UHCI driver.\n"); 96 97 sleep(3); /* TODO: remove in final version */98 96 usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME); 99 97 -
uspace/drv/uhci-hcd/pci.c
r3f3afb9 ra39cfb8 44 44 #include "pci.h" 45 45 46 /** Get address of registers and IRQ for given device.46 /** Get I/O address of registers and IRQ for given device. 47 47 * 48 48 * @param[in] dev Device asking for the addresses. … … 53 53 */ 54 54 int pci_get_my_registers(ddf_dev_t *dev, 55 uintptr_t *io_reg_address, size_t *io_reg_size, 56 int *irq_no) 55 uintptr_t *io_reg_address, size_t *io_reg_size, int *irq_no) 57 56 { 58 57 assert(dev != NULL); 59 58 60 int parent_phone = devman_parent_device_connect(dev->handle,61 IPC_FLAG_BLOCKING);59 int parent_phone = 60 devman_parent_device_connect(dev->handle, IPC_FLAG_BLOCKING); 62 61 if (parent_phone < 0) { 63 62 return parent_phone; 64 63 } 65 64 66 int rc;67 65 hw_resource_list_t hw_resources; 68 rc = hw_res_get_resource_list(parent_phone, &hw_resources);66 int rc = hw_res_get_resource_list(parent_phone, &hw_resources); 69 67 if (rc != EOK) { 70 68 goto leave; … … 95 93 res->res.io_range.address, res->res.io_range.size); 96 94 io_found = true; 95 break; 97 96 98 97 default: … … 113 112 leave: 114 113 async_hangup(parent_phone); 115 116 114 return rc; 117 115 } … … 145 143 } 146 144 147 /* See UHCI design guide for these values ,145 /* See UHCI design guide for these values p.45, 148 146 * write all WC bits in USB legacy register */ 149 147 sysarg_t address = 0xc0; -
uspace/drv/uhci-hcd/root_hub.c
r3f3afb9 ra39cfb8 55 55 int ret = asprintf(&match_str, "usb&uhci&root-hub"); 56 56 if (ret < 0) { 57 usb_log_error("Failed to create root hub match string.\n"); 58 return ENOMEM; 57 usb_log_error( 58 "Failed(%d) to create root hub match string: %s.\n", 59 ret, str_error(ret)); 60 return ret; 59 61 } 60 62 61 63 ret = ddf_fun_add_match_id(fun, match_str, 100); 62 64 if (ret != EOK) { 65 free(match_str); 63 66 usb_log_error("Failed(%d) to add root hub match id: %s\n", 64 67 ret, str_error(ret)); … … 66 69 } 67 70 68 hw_resource_list_t *resource_list = &instance->resource_list;69 resource_list->count = 1;70 resource_list->resources = &instance->io_regs;71 assert(resource_list->resources); 71 /* Initialize resource structure */ 72 instance->resource_list.count = 1; 73 instance->resource_list.resources = &instance->io_regs; 74 72 75 instance->io_regs.type = IO_RANGE; 73 76 instance->io_regs.res.io_range.address = reg_addr; -
uspace/drv/uhci-hcd/root_hub.h
r3f3afb9 ra39cfb8 39 39 #include <ops/hw_res.h> 40 40 41 /** DDF support structure for uhci-rhd driver, provides I/O resources */ 41 42 typedef struct rh { 43 /** List of resources available to the root hub. */ 42 44 hw_resource_list_t resource_list; 45 /** The only resource in the above list */ 43 46 hw_resource_t io_regs; 44 47 } rh_t; -
uspace/drv/uhci-hcd/transfer_list.c
r3f3afb9 ra39cfb8 57 57 return ENOMEM; 58 58 } 59 instance->queue_head_pa = addr_to_phys(instance->queue_head);59 uint32_t queue_head_pa = addr_to_phys(instance->queue_head); 60 60 usb_log_debug2("Transfer list %s setup with QH: %p(%p).\n", 61 name, instance->queue_head, instance->queue_head_pa);61 name, instance->queue_head, queue_head_pa); 62 62 63 63 qh_init(instance->queue_head); … … 67 67 } 68 68 /*----------------------------------------------------------------------------*/ 69 /** Dispose transfer list structures. 70 * 71 * @param[in] instance Memory place to use. 72 * 73 * Frees memory for internal qh_t structure. 74 */ 75 void transfer_list_fini(transfer_list_t *instance) 76 { 77 assert(instance); 78 free32(instance->queue_head); 79 } 69 80 /** Set the next list in transfer list chain. 70 81 * … … 81 92 if (!instance->queue_head) 82 93 return; 83 /* Set bothqueue_head.next to point to the follower */84 qh_set_next_qh(instance->queue_head, next->queue_head _pa);85 } 86 /*----------------------------------------------------------------------------*/ 87 /** Submittransfer batch to the list and queue.94 /* Set queue_head.next to point to the follower */ 95 qh_set_next_qh(instance->queue_head, next->queue_head); 96 } 97 /*----------------------------------------------------------------------------*/ 98 /** Add transfer batch to the list and queue. 88 99 * 89 100 * @param[in] instance List to use. 90 101 * @param[in] batch Transfer batch to submit. 91 * @return Error code92 102 * 93 103 * The batch is added to the end of the list and queue. … … 109 119 } else { 110 120 /* There is something scheduled */ 111 usb_transfer_batch_t *last = list_get_instance(112 instance->batch_list.prev, usb_transfer_batch_t, link);121 usb_transfer_batch_t *last = 122 usb_transfer_batch_from_link(instance->batch_list.prev); 113 123 last_qh = batch_qh(last); 114 124 } … … 118 128 /* keep link */ 119 129 batch_qh(batch)->next = last_qh->next; 120 qh_set_next_qh(last_qh, pa);130 qh_set_next_qh(last_qh, batch_qh(batch)); 121 131 122 132 asm volatile ("": : :"memory"); … … 132 142 } 133 143 /*----------------------------------------------------------------------------*/ 134 /** Create list for finished batches.144 /** Add completed bantches to the provided list. 135 145 * 136 146 * @param[in] instance List to use. … … 147 157 link_t *next = current->next; 148 158 usb_transfer_batch_t *batch = 149 list_get_instance(current, usb_transfer_batch_t, link);159 usb_transfer_batch_from_link(current); 150 160 151 161 if (batch_is_complete(batch)) { 152 /* Save for p ost-processing */162 /* Save for processing */ 153 163 transfer_list_remove_batch(instance, batch); 154 164 list_append(current, done); … … 159 169 } 160 170 /*----------------------------------------------------------------------------*/ 161 /** Walk the list and abort all batches.171 /** Walk the list and finish all batches with EINTR. 162 172 * 163 173 * @param[in] instance List to use. … … 169 179 link_t *current = instance->batch_list.next; 170 180 usb_transfer_batch_t *batch = 171 list_get_instance(current, usb_transfer_batch_t, link);181 usb_transfer_batch_from_link(current); 172 182 transfer_list_remove_batch(instance, batch); 173 usb_transfer_batch_finish_error(batch, EI O);183 usb_transfer_batch_finish_error(batch, EINTR); 174 184 } 175 185 fibril_mutex_unlock(&instance->guard); … … 180 190 * @param[in] instance List to use. 181 191 * @param[in] batch Transfer batch to remove. 182 * @return Error code183 192 * 184 193 * Does not lock the transfer list, caller is responsible for that. … … 197 206 198 207 const char *qpos = NULL; 208 qh_t *prev_qh = NULL; 199 209 /* Remove from the hardware queue */ 200 210 if (instance->batch_list.next == &batch->link) { 201 211 /* I'm the first one here */ 202 assert((instance->queue_head->next & LINK_POINTER_ADDRESS_MASK) 203 == addr_to_phys(batch_qh(batch))); 204 instance->queue_head->next = batch_qh(batch)->next; 212 prev_qh = instance->queue_head; 205 213 qpos = "FIRST"; 206 214 } else { 215 /* The thing before me is a batch too */ 207 216 usb_transfer_batch_t *prev = 208 list_get_instance( 209 batch->link.prev, usb_transfer_batch_t, link); 210 assert((batch_qh(prev)->next & LINK_POINTER_ADDRESS_MASK) 211 == addr_to_phys(batch_qh(batch))); 212 batch_qh(prev)->next = batch_qh(batch)->next; 217 usb_transfer_batch_from_link(batch->link.prev); 218 prev_qh = batch_qh(prev); 213 219 qpos = "NOT FIRST"; 214 220 } 221 assert((prev_qh->next & LINK_POINTER_ADDRESS_MASK) 222 == addr_to_phys(batch_qh(batch))); 223 prev_qh->next = batch_qh(batch)->next; 215 224 asm volatile ("": : :"memory"); 216 225 /* Remove from the batch list */ 217 226 list_remove(&batch->link); 218 usb_log_debug("Batch(%p) removed (%s) from %s, next %x.\n",227 usb_log_debug("Batch(%p) removed (%s) from %s, next: %x.\n", 219 228 batch, qpos, instance->name, batch_qh(batch)->next); 220 229 } -
uspace/drv/uhci-hcd/transfer_list.h
r3f3afb9 ra39cfb8 39 39 #include "batch.h" 40 40 #include "hw_struct/queue_head.h" 41 #include "utils/malloc32.h"42 41 42 /** Structure maintaining both hw queue and software list 43 * of currently executed transfers 44 */ 43 45 typedef struct transfer_list 44 46 { 47 /** Guard against multiple add/remove races */ 45 48 fibril_mutex_t guard; 49 /** UHCI hw structure represeting this queue */ 46 50 qh_t *queue_head; 47 uint32_t queue_head_pa;51 /** Assigned name, for nicer debug output */ 48 52 const char *name; 53 /** List of all batches in this list */ 49 54 link_t batch_list; 50 55 } transfer_list_t; 51 56 52 /** Dispose transfer list structures. 53 * 54 * @param[in] instance Memory place to use. 55 * 56 * Frees memory for internal qh_t structure. 57 */ 58 static inline void transfer_list_fini(transfer_list_t *instance) 59 { 60 assert(instance); 61 free32(instance->queue_head); 62 } 63 57 void transfer_list_fini(transfer_list_t *instance); 64 58 int transfer_list_init(transfer_list_t *instance, const char *name); 65 66 59 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next); 67 68 void transfer_list_add_batch(transfer_list_t *instance, usb_transfer_batch_t *batch); 69 60 void transfer_list_add_batch( 61 transfer_list_t *instance, usb_transfer_batch_t *batch); 70 62 void transfer_list_remove_finished(transfer_list_t *instance, link_t *done); 71 72 63 void transfer_list_abort_all(transfer_list_t *instance); 73 64 #endif -
uspace/drv/uhci-hcd/uhci.c
r3f3afb9 ra39cfb8 44 44 #include "pci.h" 45 45 46 /** IRQ handling callback, identifies device46 /** IRQ handling callback, forward status from call to diver structure. 47 47 * 48 48 * @param[in] dev DDF instance of the device to use. 49 49 * @param[in] iid (Unused). 50 * @param[in] call Pointer to the call that represents interrupt.50 * @param[in] call Pointer to the call from kernel. 51 51 */ 52 52 static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call) … … 61 61 /** Get address of the device identified by handle. 62 62 * 63 * @param[in] dev DDF instance of the deviceto use.64 * @param[in] iid (Unused).65 * @param[ in] call Pointer to the call that represents interrupt.63 * @param[in] fun DDF instance of the function to use. 64 * @param[in] handle DDF handle of the driver seeking its USB address. 65 * @param[out] address Found address. 66 66 */ 67 67 static int usb_iface_get_address( … … 69 69 { 70 70 assert(fun); 71 usb_device_keeper_t *manager = &((uhci_t*)fun->dev->driver_data)->hc.manager; 71 usb_device_keeper_t *manager = 72 &((uhci_t*)fun->dev->driver_data)->hc.manager; 72 73 73 74 usb_address_t addr = usb_device_keeper_find(manager, handle); … … 83 84 } 84 85 /*----------------------------------------------------------------------------*/ 85 /** Gets handle of the respective hc (this or parent device).86 * 87 * @param[in] root_hub_fun Root hub function seeking hc handle.88 * @param[out] handle Place to write thehandle.86 /** Gets handle of the respective hc. 87 * 88 * @param[in] fun DDF function of uhci device. 89 * @param[out] handle Host cotnroller handle. 89 90 * @return Error code. 90 91 */ … … 100 101 } 101 102 /*----------------------------------------------------------------------------*/ 102 /** This iface is generic for both RH and HC.*/103 /** USB interface implementation used by RH */ 103 104 static usb_iface_t usb_iface = { 104 105 .get_hc_handle = usb_iface_get_hc_handle, … … 106 107 }; 107 108 /*----------------------------------------------------------------------------*/ 109 /** Operations supported by the HC driver */ 108 110 static ddf_dev_ops_t hc_ops = { 109 // .interfaces[USB_DEV_IFACE] = &usb_iface,110 111 .interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */ 111 112 }; … … 122 123 } 123 124 /*----------------------------------------------------------------------------*/ 125 /** Interface to provide the root hub driver with hw info */ 124 126 static hw_res_ops_t hw_res_iface = { 125 127 .get_resource_list = get_resource_list, … … 127 129 }; 128 130 /*----------------------------------------------------------------------------*/ 131 /** RH function support for uhci-rhd */ 129 132 static ddf_dev_ops_t rh_ops = { 130 133 .interfaces[USB_DEV_IFACE] = &usb_iface, … … 132 135 }; 133 136 /*----------------------------------------------------------------------------*/ 134 /** Initialize hc and rh ddfstructures and their respective drivers.137 /** Initialize hc and rh DDF structures and their respective drivers. 135 138 * 136 139 * @param[in] instance UHCI structure to use. … … 138 141 * 139 142 * This function does all the preparatory work for hc and rh drivers: 140 * - gets device hw resources141 * - disables UHCI legacy support 143 * - gets device's hw resources 144 * - disables UHCI legacy support (PCI config space) 142 145 * - asks for interrupt 143 146 * - registers interrupt handler … … 193 196 ret = (instance->hc_fun == NULL) ? ENOMEM : EOK; 194 197 CHECK_RET_DEST_FUN_RETURN(ret, 195 "Failed(%d) to create HC function .\n", ret);198 "Failed(%d) to create HC function: %s.\n", ret, str_error(ret)); 196 199 197 200 ret = hc_init(&instance->hc, instance->hc_fun, 198 201 (void*)io_reg_base, io_reg_size, interrupts); 199 CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret); 202 CHECK_RET_DEST_FUN_RETURN(ret, 203 "Failed(%d) to init uhci-hcd: %s.\n", ret, str_error(ret)); 204 200 205 instance->hc_fun->ops = &hc_ops; 201 206 instance->hc_fun->driver_data = &instance->hc; … … 221 226 &instance->hc.interrupt_code); 222 227 CHECK_RET_FINI_RETURN(ret, 223 "Failed(%d) to register interrupt handler.\n", ret); 228 "Failed(%d) to register interrupt handler: %s.\n", 229 ret, str_error(ret)); 224 230 225 231 instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci-rh"); 226 232 ret = (instance->rh_fun == NULL) ? ENOMEM : EOK; 227 233 CHECK_RET_FINI_RETURN(ret, 228 "Failed(%d) to create root hub function.\n", ret); 234 "Failed(%d) to create root hub function: %s.\n", 235 ret, str_error(ret)); 229 236 230 237 ret = rh_init(&instance->rh, instance->rh_fun, 231 238 (uintptr_t)instance->hc.registers + 0x10, 4); 232 239 CHECK_RET_FINI_RETURN(ret, 233 "Failed(%d) to setup UHCI root hub .\n", ret);240 "Failed(%d) to setup UHCI root hub: %s.\n", ret, str_error(ret)); 234 241 235 242 instance->rh_fun->ops = &rh_ops; … … 237 244 ret = ddf_fun_bind(instance->rh_fun); 238 245 CHECK_RET_FINI_RETURN(ret, 239 "Failed(%d) to register UHCI root hub .\n", ret);246 "Failed(%d) to register UHCI root hub: %s.\n", ret, str_error(ret)); 240 247 241 248 return EOK; -
uspace/drv/uhci-hcd/uhci.h
r3f3afb9 ra39cfb8 41 41 #include "root_hub.h" 42 42 43 /** Structure representing both functions of UHCI hc, USB host controller 44 * and USB root hub */ 43 45 typedef struct uhci { 46 /** Pointer to DDF represenation of UHCI host controller */ 44 47 ddf_fun_t *hc_fun; 48 /** Pointer to DDF represenation of UHCI root hub */ 45 49 ddf_fun_t *rh_fun; 46 50 51 /** Internal driver's represenation of UHCI host controller */ 47 52 hc_t hc; 53 /** Internal driver's represenation of UHCI root hub */ 48 54 rh_t rh; 49 55 } uhci_t; 50 56 51 57 int uhci_init(uhci_t *instance, ddf_dev_t *device); 52 53 58 #endif 54 59 /**
Note:
See TracChangeset
for help on using the changeset viewer.
