Changeset c7dd69d in mainline for uspace/drv
- Timestamp:
- 2011-04-15T13:19:59Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- da1dd48
- Parents:
- e3b5129 (diff), 8fd4ba0 (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:
-
- 7 added
- 42 edited
- 4 moved
-
isa/isa.c (modified) (1 diff)
-
ohci/Makefile (modified) (2 diffs)
-
ohci/batch.c (modified) (13 diffs)
-
ohci/batch.h (modified) (1 diff)
-
ohci/endpoint_list.c (moved) (moved from uspace/drv/ohci/transfer_list.c ) (7 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 (added)
-
ohci/hcd_endpoint.h (moved) (moved from kernel/generic/include/proc/tasklet.h ) (2 diffs)
-
ohci/hw_struct/endpoint_descriptor.c (modified) (1 diff)
-
ohci/hw_struct/endpoint_descriptor.h (modified) (4 diffs)
-
ohci/hw_struct/hcca.h (modified) (1 diff)
-
ohci/hw_struct/transfer_descriptor.c (modified) (1 diff)
-
ohci/hw_struct/transfer_descriptor.h (modified) (2 diffs)
-
ohci/iface.c (modified) (12 diffs)
-
ohci/ohci.ma (modified) (1 diff)
-
ohci/ohci_regs.h (modified) (2 diffs)
-
ohci/root_hub.c (modified) (6 diffs)
-
ohci/root_hub.h (modified) (2 diffs)
-
ohci/utils/malloc32.h (modified) (2 diffs)
-
uhci-hcd/batch.c (modified) (13 diffs)
-
uhci-hcd/batch.h (modified) (1 diff)
-
uhci-hcd/hc.c (modified) (13 diffs)
-
uhci-hcd/hc.h (modified) (4 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)
-
uhci-rhd/port.c (modified) (5 diffs)
-
uhci-rhd/port.h (modified) (1 diff)
-
uhci-rhd/root_hub.c (modified) (4 diffs)
-
uhci-rhd/root_hub.h (modified) (1 diff)
-
usbhid/main.c (modified) (1 diff)
-
usbhid/usbhid.c (modified) (5 diffs)
-
usbhub/usbhub.c (modified) (2 diffs)
-
usbkbd/main.c (modified) (1 diff)
-
usbmast/Makefile (added)
-
usbmast/cmds.h (added)
-
usbmast/main.c (added)
-
usbmast/mast.c (added)
-
usbmast/mast.h (moved) (moved from kernel/generic/src/proc/tasklet.c ) (2 diffs)
-
usbmast/scsi.h (added)
-
usbmast/usbmast.ma (added)
-
usbmouse/main.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/isa/isa.c
re3b5129 rc7dd69d 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
re3b5129 rc7dd69d 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
re3b5129 rc7dd69d 39 39 40 40 #include "batch.h" 41 #include "hcd_endpoint.h" 41 42 #include "utils/malloc32.h" 42 43 #include "hw_struct/endpoint_descriptor.h" 43 44 #include "hw_struct/transfer_descriptor.h" 44 45 45 typedef struct ohci_ batch {46 typedef struct ohci_transfer_batch { 46 47 ed_t *ed; 47 td_t * tds;48 td_t **tds; 48 49 size_t td_count; 49 } ohci_batch_t; 50 50 size_t leave_td; 51 char *device_buffer; 52 } ohci_transfer_batch_t; 53 54 static void ohci_transfer_batch_dispose(void *ohci_batch) 55 { 56 ohci_transfer_batch_t *instance = ohci_batch; 57 if (!instance) 58 return; 59 free32(instance->device_buffer); 60 unsigned i = 0; 61 if (instance->tds) { 62 for (; i< instance->td_count; ++i) { 63 if (i != instance->leave_td) 64 free32(instance->tds[i]); 65 } 66 free(instance->tds); 67 } 68 free(instance); 69 } 70 /*----------------------------------------------------------------------------*/ 51 71 static void batch_control(usb_transfer_batch_t *instance, 52 72 usb_direction_t data_dir, usb_direction_t status_dir); 53 static void batch_call_in_and_dispose(usb_transfer_batch_t *instance); 54 static void batch_call_out_and_dispose(usb_transfer_batch_t *instance); 55 56 #define DEFAULT_ERROR_COUNT 3 73 static void batch_data(usb_transfer_batch_t *instance); 74 /*----------------------------------------------------------------------------*/ 57 75 usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep, 58 76 char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size, … … 64 82 usb_log_error(message); \ 65 83 if (instance) { \ 66 batch_dispose(instance); \84 usb_transfer_batch_dispose(instance); \ 67 85 } \ 68 86 return NULL; \ … … 72 90 CHECK_NULL_DISPOSE_RETURN(instance, 73 91 "Failed to allocate batch instance.\n"); 74 usb_target_t target = 75 { .address = ep->address, .endpoint = ep->endpoint }; 76 usb_transfer_batch_init(instance, target, ep->transfer_type, ep->speed, 77 ep->max_packet_size, buffer, NULL, buffer_size, NULL, setup_size, 78 func_in, func_out, arg, fun, ep, NULL); 79 80 ohci_batch_t *data = malloc(sizeof(ohci_batch_t)); 92 usb_transfer_batch_init(instance, ep, buffer, NULL, buffer_size, 93 NULL, setup_size, func_in, func_out, arg, fun, NULL, 94 ohci_transfer_batch_dispose); 95 96 hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep); 97 assert(hcd_ep); 98 99 ohci_transfer_batch_t *data = calloc(sizeof(ohci_transfer_batch_t), 1); 81 100 CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n"); 82 bzero(data, sizeof(ohci_batch_t));83 101 instance->private_data = data; 84 102 85 /* we needs + 1 transfer descriptor as the last one won't be executed */ 86 data->td_count = 1 + 103 data->td_count = 87 104 ((buffer_size + OHCI_TD_MAX_TRANSFER - 1) / OHCI_TD_MAX_TRANSFER); 88 105 if (ep->transfer_type == USB_TRANSFER_CONTROL) { … … 90 107 } 91 108 92 data->tds = malloc32(sizeof(td_t) * data->td_count); 109 /* we need one extra place for td that is currently assigned to hcd_ep*/ 110 data->tds = calloc(sizeof(td_t*), data->td_count + 1); 93 111 CHECK_NULL_DISPOSE_RETURN(data->tds, 94 112 "Failed to allocate transfer descriptors.\n"); 95 bzero(data->tds, sizeof(td_t) * data->td_count); 96 97 data->ed = malloc32(sizeof(ed_t)); 98 CHECK_NULL_DISPOSE_RETURN(data->ed, 99 "Failed to allocate endpoint descriptor.\n"); 100 101 if (buffer_size > 0) { 102 instance->transport_buffer = malloc32(buffer_size); 103 CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer, 113 114 data->tds[0] = hcd_ep->td; 115 data->leave_td = 0; 116 unsigned i = 1; 117 for (; i <= data->td_count; ++i) { 118 data->tds[i] = malloc32(sizeof(td_t)); 119 CHECK_NULL_DISPOSE_RETURN(data->tds[i], 120 "Failed to allocate TD %d.\n", i ); 121 } 122 123 data->ed = hcd_ep->ed; 124 125 if (setup_size + buffer_size > 0) { 126 data->device_buffer = malloc32(setup_size + buffer_size); 127 CHECK_NULL_DISPOSE_RETURN(data->device_buffer, 104 128 "Failed to allocate device accessible buffer.\n"); 105 } 106 107 if (setup_size > 0) { 108 instance->setup_buffer = malloc32(setup_size); 109 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer, 110 "Failed to allocate device accessible setup buffer.\n"); 129 instance->setup_buffer = data->device_buffer; 130 instance->data_buffer = data->device_buffer + setup_size; 111 131 memcpy(instance->setup_buffer, setup_buffer, setup_size); 112 132 } … … 115 135 } 116 136 /*----------------------------------------------------------------------------*/ 117 void batch_dispose(usb_transfer_batch_t *instance)118 {119 assert(instance);120 ohci_batch_t *data = instance->private_data;121 assert(data);122 free32(data->ed);123 free32(data->tds);124 free32(instance->setup_buffer);125 free32(instance->transport_buffer);126 free(data);127 free(instance);128 }129 /*----------------------------------------------------------------------------*/130 137 bool batch_is_complete(usb_transfer_batch_t *instance) 131 138 { 132 139 assert(instance); 133 ohci_ batch_t *data = instance->private_data;134 assert(data); 135 size_t tds = data->td_count - 1;136 usb_log_debug 2("Batch(%p) checking %d td(s) for completion.\n",140 ohci_transfer_batch_t *data = instance->private_data; 141 assert(data); 142 size_t tds = data->td_count; 143 usb_log_debug("Batch(%p) checking %d td(s) for completion.\n", 137 144 instance, tds); 145 usb_log_debug("ED: %x:%x:%x:%x.\n", 146 data->ed->status, data->ed->td_head, data->ed->td_tail, 147 data->ed->next); 138 148 size_t i = 0; 139 149 for (; i < tds; ++i) { 140 if (!td_is_finished(&data->tds[i])) 150 assert(data->tds[i] != NULL); 151 usb_log_debug("TD %d: %x:%x:%x:%x.\n", 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])) { 141 155 return false; 142 instance->error = td_error(&data->tds[i]); 156 } 157 instance->error = td_error(data->tds[i]); 143 158 /* FIXME: calculate real transfered size */ 144 159 instance->transfered_size = instance->buffer_size; 145 160 if (instance->error != EOK) { 146 161 usb_log_debug("Batch(%p) found error TD(%d):%x.\n", 147 instance, i, data->tds[i].status); 148 return true; 149 // endpoint_toggle_set(instance->ep, 162 instance, i, data->tds[i]->status); 163 /* Make sure TD queue is empty (one TD), 164 * ED should be marked as halted */ 165 data->ed->td_tail = 166 (data->ed->td_head & ED_TDTAIL_PTR_MASK); 167 ++i; 168 break; 150 169 } 151 170 } 171 data->leave_td = i; 172 assert(data->leave_td <= data->td_count); 173 hcd_endpoint_t *hcd_ep = hcd_endpoint_get(instance->ep); 174 assert(hcd_ep); 175 hcd_ep->td = data->tds[i]; 176 /* Clear possible ED HALT */ 177 data->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG; 178 uint32_t pa = addr_to_phys(hcd_ep->td); 179 assert(pa == (data->ed->td_head & ED_TDHEAD_PTR_MASK)); 180 assert(pa == (data->ed->td_tail & ED_TDTAIL_PTR_MASK)); 181 152 182 return true; 153 183 } 154 184 /*----------------------------------------------------------------------------*/ 185 void batch_commit(usb_transfer_batch_t *instance) 186 { 187 assert(instance); 188 ohci_transfer_batch_t *data = instance->private_data; 189 assert(data); 190 ed_set_end_td(data->ed, data->tds[data->td_count]); 191 } 192 /*----------------------------------------------------------------------------*/ 155 193 void batch_control_write(usb_transfer_batch_t *instance) 156 194 { 157 195 assert(instance); 158 196 /* We are data out, we are supposed to provide data */ 159 memcpy(instance->transport_buffer, instance->buffer, 160 instance->buffer_size); 161 instance->next_step = batch_call_out_and_dispose; 197 memcpy(instance->data_buffer, instance->buffer, instance->buffer_size); 198 instance->next_step = usb_transfer_batch_call_out_and_dispose; 162 199 batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN); 163 200 usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance); … … 167 204 { 168 205 assert(instance); 169 instance->next_step = batch_call_in_and_dispose;206 instance->next_step = usb_transfer_batch_call_in_and_dispose; 170 207 batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT); 171 208 usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance); … … 175 212 { 176 213 assert(instance); 177 assert(instance->direction == USB_DIRECTION_IN); 178 instance->next_step = batch_call_in_and_dispose; 179 /* TODO: implement */ 214 instance->next_step = usb_transfer_batch_call_in_and_dispose; 215 batch_data(instance); 180 216 usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance); 181 217 } … … 184 220 { 185 221 assert(instance); 186 assert(instance->direction == USB_DIRECTION_OUT);187 222 /* We are data out, we are supposed to provide data */ 188 memcpy(instance->transport_buffer, instance->buffer, 189 instance->buffer_size); 190 instance->next_step = batch_call_out_and_dispose; 191 /* TODO: implement */ 223 memcpy(instance->data_buffer, instance->buffer, instance->buffer_size); 224 instance->next_step = usb_transfer_batch_call_out_and_dispose; 225 batch_data(instance); 192 226 usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance); 193 227 } … … 196 230 { 197 231 assert(instance); 198 instance->direction = USB_DIRECTION_IN; 199 instance->next_step = batch_call_in_and_dispose; 200 /* TODO: implement */ 232 instance->next_step = usb_transfer_batch_call_in_and_dispose; 233 batch_data(instance); 201 234 usb_log_debug("Batch(%p) BULK IN initialized.\n", instance); 202 235 } … … 205 238 { 206 239 assert(instance); 207 instance->direction = USB_DIRECTION_IN; 208 instance->next_step = batch_call_in_and_dispose; 209 /* TODO: implement */ 240 instance->next_step = usb_transfer_batch_call_in_and_dispose; 241 batch_data(instance); 210 242 usb_log_debug("Batch(%p) BULK IN initialized.\n", instance); 211 243 } … … 214 246 { 215 247 assert(instance); 216 ohci_ batch_t *data = instance->private_data;248 ohci_transfer_batch_t *data = instance->private_data; 217 249 assert(data); 218 250 return data->ed; … … 223 255 { 224 256 assert(instance); 225 ohci_batch_t *data = instance->private_data; 226 assert(data); 227 ed_init(data->ed, instance->ep); 228 ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]); 229 usb_log_debug("Created ED(%p): %x:%x:%x:%x.\n", data->ed, 257 ohci_transfer_batch_t *data = instance->private_data; 258 assert(data); 259 usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed, 230 260 data->ed->status, data->ed->td_tail, data->ed->td_head, 231 261 data->ed->next); 232 262 int toggle = 0; 233 263 /* setup stage */ 234 td_init( &data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,264 td_init(data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer, 235 265 instance->setup_size, toggle); 236 td_set_next( &data->tds[0], &data->tds[1]);237 usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0] .status,238 data->tds[0] .cbp, data->tds[0].next, data->tds[0].be);266 td_set_next(data->tds[0], data->tds[1]); 267 usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0]->status, 268 data->tds[0]->cbp, data->tds[0]->next, data->tds[0]->be); 239 269 240 270 /* data stage */ 241 271 size_t td_current = 1; 242 272 size_t remain_size = instance->buffer_size; 243 char * transfer_buffer = instance->transport_buffer;273 char *buffer = instance->data_buffer; 244 274 while (remain_size > 0) { 245 275 size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ? … … 247 277 toggle = 1 - toggle; 248 278 249 td_init( &data->tds[td_current], data_dir, transfer_buffer,279 td_init(data->tds[td_current], data_dir, buffer, 250 280 transfer_size, toggle); 251 td_set_next( &data->tds[td_current], &data->tds[td_current + 1]);281 td_set_next(data->tds[td_current], data->tds[td_current + 1]); 252 282 usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n", 253 data->tds[td_current] .status, data->tds[td_current].cbp,254 data->tds[td_current] .next, data->tds[td_current].be);255 256 transfer_buffer += transfer_size;283 data->tds[td_current]->status, data->tds[td_current]->cbp, 284 data->tds[td_current]->next, data->tds[td_current]->be); 285 286 buffer += transfer_size; 257 287 remain_size -= transfer_size; 258 assert(td_current < data->td_count - 2);288 assert(td_current < data->td_count - 1); 259 289 ++td_current; 260 290 } 261 291 262 292 /* status stage */ 263 assert(td_current == data->td_count - 2); 264 td_init(&data->tds[td_current], status_dir, NULL, 0, 1); 293 assert(td_current == data->td_count - 1); 294 td_init(data->tds[td_current], status_dir, NULL, 0, 1); 295 td_set_next(data->tds[td_current], data->tds[td_current + 1]); 265 296 usb_log_debug("Created STATUS TD: %x:%x:%x:%x.\n", 266 data->tds[td_current].status, data->tds[td_current].cbp, 267 data->tds[td_current].next, data->tds[td_current].be); 268 } 269 /*----------------------------------------------------------------------------*/ 270 /** Helper function calls callback and correctly disposes of batch structure. 271 * 272 * @param[in] instance Batch structure to use. 273 */ 274 void batch_call_in_and_dispose(usb_transfer_batch_t *instance) 275 { 276 assert(instance); 277 usb_transfer_batch_call_in(instance); 278 batch_dispose(instance); 279 } 280 /*----------------------------------------------------------------------------*/ 281 /** Helper function calls callback and correctly disposes of batch structure. 282 * 283 * @param[in] instance Batch structure to use. 284 */ 285 void batch_call_out_and_dispose(usb_transfer_batch_t *instance) 286 { 287 assert(instance); 288 usb_transfer_batch_call_out(instance); 289 batch_dispose(instance); 297 data->tds[td_current]->status, data->tds[td_current]->cbp, 298 data->tds[td_current]->next, data->tds[td_current]->be); 299 } 300 /*----------------------------------------------------------------------------*/ 301 void batch_data(usb_transfer_batch_t *instance) 302 { 303 assert(instance); 304 ohci_transfer_batch_t *data = instance->private_data; 305 assert(data); 306 usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed, 307 data->ed->status, data->ed->td_tail, data->ed->td_head, 308 data->ed->next); 309 310 size_t td_current = 0; 311 size_t remain_size = instance->buffer_size; 312 char *buffer = instance->data_buffer; 313 while (remain_size > 0) { 314 size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ? 315 OHCI_TD_MAX_TRANSFER : remain_size; 316 317 td_init(data->tds[td_current], instance->ep->direction, 318 buffer, transfer_size, -1); 319 td_set_next(data->tds[td_current], data->tds[td_current + 1]); 320 usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n", 321 data->tds[td_current]->status, data->tds[td_current]->cbp, 322 data->tds[td_current]->next, data->tds[td_current]->be); 323 324 buffer += transfer_size; 325 remain_size -= transfer_size; 326 assert(td_current < data->td_count); 327 ++td_current; 328 } 290 329 } 291 330 /** -
uspace/drv/ohci/batch.h
re3b5129 rc7dd69d 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
re3b5129 rc7dd69d 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); 80 77 assert(next); 81 /* Set both queue_head.next to point to the follower */82 78 ed_append_ed(instance->list_head, next->list_head); 83 79 } 84 80 /*----------------------------------------------------------------------------*/ 85 /** Submit transfer batchto the list and queue.86 * 87 * @param[in] instance List to use. 88 * @param[in] batch Transfer batchto submit.89 * @return Error code 90 * 91 * The batchis added to the end of the list and queue.92 */ 93 void transfer_list_add_batch(94 transfer_list_t *instance, usb_transfer_batch_t *batch) 95 { 96 assert( instance);97 assert(batch);98 usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch);81 /** Submit transfer endpoint to the list and queue. 82 * 83 * @param[in] instance List to use. 84 * @param[in] endpoint Transfer endpoint to submit. 85 * @return Error code 86 * 87 * The endpoint is added to the end of the list and queue. 88 */ 89 void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep) 90 { 91 assert(instance); 92 assert(hcd_ep); 93 usb_log_debug2("Queue %s: Adding endpoint(%p).\n", 94 instance->name, hcd_ep); 99 95 100 96 fibril_mutex_lock(&instance->guard); … … 102 98 ed_t *last_ed = NULL; 103 99 /* Add to the hardware queue. */ 104 if (list_empty(&instance-> batch_list)) {100 if (list_empty(&instance->endpoint_list)) { 105 101 /* There is nothing scheduled */ 106 102 last_ed = instance->list_head; 107 103 } else { 108 104 /* There is something scheduled */ 109 usb_transfer_batch_t *last = list_get_instance(110 instance-> batch_list.prev, usb_transfer_batch_t, link);111 last_ed = batch_ed(last);105 hcd_endpoint_t *last = list_get_instance( 106 instance->endpoint_list.prev, hcd_endpoint_t, link); 107 last_ed = last->ed; 112 108 } 113 109 /* keep link */ 114 batch_ed(batch)->next = last_ed->next;115 ed_append_ed(last_ed, batch_ed(batch));110 hcd_ep->ed->next = last_ed->next; 111 ed_append_ed(last_ed, hcd_ep->ed); 116 112 117 113 asm volatile ("": : :"memory"); 118 114 119 115 /* Add to the driver list */ 120 list_append(& batch->link, &instance->batch_list);121 122 usb_transfer_batch_t *first = list_get_instance(123 instance-> batch_list.next, usb_transfer_batch_t, link);124 usb_log_debug(" Batch(%p) added to list %s, first is %p(%p).\n",125 batch, instance->name, first, batch_ed(first));116 list_append(&hcd_ep->link, &instance->endpoint_list); 117 118 hcd_endpoint_t *first = list_get_instance( 119 instance->endpoint_list.next, hcd_endpoint_t, link); 120 usb_log_debug("HCD EP(%p) added to list %s, first is %p(%p).\n", 121 hcd_ep, instance->name, first, first->ed); 126 122 if (last_ed == instance->list_head) { 127 usb_log_debug2("%s head ED: %x:%x:%x:%x.\n", instance->name, 128 last_ed->status, last_ed->td_tail, last_ed->td_head, 129 last_ed->next); 130 } 131 fibril_mutex_unlock(&instance->guard); 132 } 133 /*----------------------------------------------------------------------------*/ 134 /** Create list for finished batches. 123 usb_log_debug2("%s head ED(%p-%p): %x:%x:%x:%x.\n", 124 instance->name, last_ed, instance->list_head_pa, 125 last_ed->status, last_ed->td_tail, last_ed->td_head, 126 last_ed->next); 127 } 128 fibril_mutex_unlock(&instance->guard); 129 } 130 /*----------------------------------------------------------------------------*/ 131 #if 0 132 /** Create list for finished endpoints. 135 133 * 136 134 * @param[in] instance List to use. 137 135 * @param[in] done list to fill 138 136 */ 139 void transfer_list_remove_finished(transfer_list_t *instance, link_t *done)137 void endpoint_list_remove_finished(endpoint_list_t *instance, link_t *done) 140 138 { 141 139 assert(instance); … … 143 141 144 142 fibril_mutex_lock(&instance->guard); 145 link_t *current = instance->batch_list.next; 146 while (current != &instance->batch_list) { 143 usb_log_debug2("Checking list %s for completed endpointes(%d).\n", 144 instance->name, list_count(&instance->endpoint_list)); 145 link_t *current = instance->endpoint_list.next; 146 while (current != &instance->endpoint_list) { 147 147 link_t *next = current->next; 148 usb_transfer_batch_t *batch=149 list_get_instance(current, usb_transfer_batch_t, link);150 151 if ( batch_is_complete(batch)) {148 hcd_endpoint_t *endpoint = 149 list_get_instance(current, hcd_endpoint_t, link); 150 151 if (endpoint_is_complete(endpoint)) { 152 152 /* Save for post-processing */ 153 transfer_list_remove_batch(instance, batch);153 endpoint_list_remove_endpoint(instance, endpoint); 154 154 list_append(current, done); 155 155 } … … 159 159 } 160 160 /*----------------------------------------------------------------------------*/ 161 /** Walk the list and abort all batches. 162 * 163 * @param[in] instance List to use. 164 */ 165 void transfer_list_abort_all(transfer_list_t *instance) 166 { 167 fibril_mutex_lock(&instance->guard); 168 while (!list_empty(&instance->batch_list)) { 169 link_t *current = instance->batch_list.next; 170 usb_transfer_batch_t *batch = 171 list_get_instance(current, usb_transfer_batch_t, link); 172 transfer_list_remove_batch(instance, batch); 173 usb_transfer_batch_finish_error(batch, EIO); 174 } 175 fibril_mutex_unlock(&instance->guard); 176 } 177 /*----------------------------------------------------------------------------*/ 178 /** Remove a transfer batch from the list and queue. 179 * 180 * @param[in] instance List to use. 181 * @param[in] batch Transfer batch to remove. 161 /** Walk the list and abort all endpointes. 162 * 163 * @param[in] instance List to use. 164 */ 165 void endpoint_list_abort_all(endpoint_list_t *instance) 166 { 167 fibril_mutex_lock(&instance->guard); 168 while (!list_empty(&instance->endpoint_list)) { 169 link_t *current = instance->endpoint_list.next; 170 hcd_endpoint_t *endpoint = 171 list_get_instance(current, hcd_endpoint_t, link); 172 endpoint_list_remove_endpoint(instance, endpoint); 173 hcd_endpoint_finish_error(endpoint, EIO); 174 } 175 fibril_mutex_unlock(&instance->guard); 176 } 177 #endif 178 /*----------------------------------------------------------------------------*/ 179 /** Remove a transfer endpoint from the list and queue. 180 * 181 * @param[in] instance List to use. 182 * @param[in] endpoint Transfer endpoint to remove. 182 183 * @return Error code 183 184 * 184 185 * Does not lock the transfer list, caller is responsible for that. 185 186 */ 186 void transfer_list_remove_batch( 187 transfer_list_t *instance, usb_transfer_batch_t *batch) 187 void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep) 188 188 { 189 189 assert(instance); 190 190 assert(instance->list_head); 191 assert(batch); 192 assert(batch_ed(batch)); 193 assert(fibril_mutex_is_locked(&instance->guard)); 191 assert(hcd_ep); 192 assert(hcd_ep->ed); 193 194 fibril_mutex_lock(&instance->guard); 194 195 195 196 usb_log_debug2( 196 "Queue %s: removing batch(%p).\n", instance->name, batch);197 "Queue %s: removing endpoint(%p).\n", instance->name, hcd_ep); 197 198 198 199 const char *qpos = NULL; 200 ed_t *prev_ed; 199 201 /* Remove from the hardware queue */ 200 if (instance-> batch_list.next == &batch->link) {202 if (instance->endpoint_list.next == &hcd_ep->link) { 201 203 /* I'm the first one here */ 202 assert((instance->list_head->next & ED_NEXT_PTR_MASK) 203 == addr_to_phys(batch_ed(batch))); 204 instance->list_head->next = batch_ed(batch)->next; 204 prev_ed = instance->list_head; 205 205 qpos = "FIRST"; 206 206 } else { 207 usb_transfer_batch_t *prev = 208 list_get_instance( 209 batch->link.prev, usb_transfer_batch_t, link); 210 assert((batch_ed(prev)->next & ED_NEXT_PTR_MASK) 211 == addr_to_phys(batch_ed(batch))); 212 batch_ed(prev)->next = batch_ed(batch)->next; 207 hcd_endpoint_t *prev = 208 list_get_instance(hcd_ep->link.prev, hcd_endpoint_t, link); 209 prev_ed = prev->ed; 213 210 qpos = "NOT FIRST"; 214 211 } 212 assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(hcd_ep->ed)); 213 prev_ed->next = hcd_ep->ed->next; 214 215 215 asm volatile ("": : :"memory"); 216 usb_log_debug("Batch(%p) removed (%s) from %s, next %x.\n", 217 batch, qpos, instance->name, batch_ed(batch)->next); 218 219 /* Remove from the batch list */ 220 list_remove(&batch->link); 216 usb_log_debug("HCD EP(%p) removed (%s) from %s, next %x.\n", 217 hcd_ep, qpos, instance->name, hcd_ep->ed->next); 218 219 /* Remove from the endpoint list */ 220 list_remove(&hcd_ep->link); 221 fibril_mutex_unlock(&instance->guard); 221 222 } 222 223 /** -
uspace/drv/ohci/endpoint_list.h
re3b5129 rc7dd69d 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
re3b5129 rc7dd69d 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, … … 113 120 ret, str_error(ret)); 114 121 hc_init_hw(instance); 115 116 rh_init(&instance->rh, dev, instance->registers); 122 fibril_mutex_initialize(&instance->guard); 123 124 rh_init(&instance->rh, instance->registers); 117 125 118 126 if (!interrupts) { … … 122 130 } 123 131 124 return EOK; 125 } 126 /*----------------------------------------------------------------------------*/ 127 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch) 128 { 129 assert(instance); 130 assert(batch); 131 132 /* check for root hub communication */ 133 if (batch->target.address == instance->rh.address) { 134 return rh_request(&instance->rh, batch); 135 } 136 137 transfer_list_add_batch( 138 instance->transfers[batch->transfer_type], batch); 139 140 switch (batch->transfer_type) { 132 list_initialize(&instance->pending_batches); 133 #undef CHECK_RET_RETURN 134 return EOK; 135 } 136 /*----------------------------------------------------------------------------*/ 137 int hc_add_endpoint( 138 hc_t *instance, usb_address_t address, usb_endpoint_t endpoint, 139 usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction, 140 size_t mps, size_t size, unsigned interval) 141 { 142 endpoint_t *ep = malloc(sizeof(endpoint_t)); 143 if (ep == NULL) 144 return ENOMEM; 145 int ret = 146 endpoint_init(ep, address, endpoint, direction, type, speed, mps); 147 if (ret != EOK) { 148 free(ep); 149 return ret; 150 } 151 152 hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep); 153 if (hcd_ep == NULL) { 154 endpoint_destroy(ep); 155 return ENOMEM; 156 } 157 158 ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size); 159 if (ret != EOK) { 160 hcd_endpoint_clear(ep); 161 endpoint_destroy(ep); 162 return ret; 163 } 164 165 /* Enqueue hcd_ep */ 166 switch (ep->transfer_type) { 141 167 case USB_TRANSFER_CONTROL: 142 168 instance->registers->control &= ~C_CLE; 169 endpoint_list_add_ep( 170 &instance->lists[ep->transfer_type], hcd_ep); 171 instance->registers->control_current = 0; 172 instance->registers->control |= C_CLE; 173 break; 174 case USB_TRANSFER_BULK: 175 instance->registers->control &= ~C_BLE; 176 endpoint_list_add_ep( 177 &instance->lists[ep->transfer_type], hcd_ep); 178 instance->registers->control |= C_BLE; 179 break; 180 case USB_TRANSFER_ISOCHRONOUS: 181 case USB_TRANSFER_INTERRUPT: 182 instance->registers->control &= (~C_PLE & ~C_IE); 183 endpoint_list_add_ep( 184 &instance->lists[ep->transfer_type], hcd_ep); 185 instance->registers->control |= C_PLE | C_IE; 186 break; 187 default: 188 break; 189 } 190 191 return EOK; 192 } 193 /*----------------------------------------------------------------------------*/ 194 int hc_remove_endpoint(hc_t *instance, usb_address_t address, 195 usb_endpoint_t endpoint, usb_direction_t direction) 196 { 197 assert(instance); 198 fibril_mutex_lock(&instance->guard); 199 endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager, 200 address, endpoint, direction, NULL); 201 if (ep == NULL) { 202 usb_log_error("Endpoint unregister failed: No such EP.\n"); 203 fibril_mutex_unlock(&instance->guard); 204 return ENOENT; 205 } 206 207 hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep); 208 if (hcd_ep) { 209 /* Dequeue hcd_ep */ 210 switch (ep->transfer_type) { 211 case USB_TRANSFER_CONTROL: 212 instance->registers->control &= ~C_CLE; 213 endpoint_list_remove_ep( 214 &instance->lists[ep->transfer_type], hcd_ep); 215 instance->registers->control_current = 0; 216 instance->registers->control |= C_CLE; 217 break; 218 case USB_TRANSFER_BULK: 219 instance->registers->control &= ~C_BLE; 220 endpoint_list_remove_ep( 221 &instance->lists[ep->transfer_type], hcd_ep); 222 instance->registers->control |= C_BLE; 223 break; 224 case USB_TRANSFER_ISOCHRONOUS: 225 case USB_TRANSFER_INTERRUPT: 226 instance->registers->control &= (~C_PLE & ~C_IE); 227 endpoint_list_remove_ep( 228 &instance->lists[ep->transfer_type], hcd_ep); 229 instance->registers->control |= C_PLE | C_IE; 230 break; 231 default: 232 break; 233 } 234 hcd_endpoint_clear(ep); 235 } else { 236 usb_log_warning("Endpoint without hcd equivalent structure.\n"); 237 } 238 int ret = usb_endpoint_manager_unregister_ep(&instance->ep_manager, 239 address, endpoint, direction); 240 fibril_mutex_unlock(&instance->guard); 241 return ret; 242 } 243 /*----------------------------------------------------------------------------*/ 244 endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address, 245 usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw) 246 { 247 assert(instance); 248 fibril_mutex_lock(&instance->guard); 249 endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager, 250 address, endpoint, direction, bw); 251 fibril_mutex_unlock(&instance->guard); 252 return ep; 253 } 254 /*----------------------------------------------------------------------------*/ 255 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch) 256 { 257 assert(instance); 258 assert(batch); 259 assert(batch->ep); 260 261 /* check for root hub communication */ 262 if (batch->ep->address == instance->rh.address) { 263 return rh_request(&instance->rh, batch); 264 } 265 266 fibril_mutex_lock(&instance->guard); 267 list_append(&batch->link, &instance->pending_batches); 268 batch_commit(batch); 269 switch (batch->ep->transfer_type) { 270 case USB_TRANSFER_CONTROL: 143 271 instance->registers->command_status |= CS_CLF; 144 usb_log_debug2("Set control transfer filled: %x.\n",145 instance->registers->command_status);146 instance->registers->control |= C_CLE;147 272 break; 148 273 case USB_TRANSFER_BULK: 149 274 instance->registers->command_status |= CS_BLF; 150 usb_log_debug2("Set bulk transfer filled: %x.\n",151 instance->registers->command_status);152 275 break; 153 276 default: 154 277 break; 155 278 } 279 280 fibril_mutex_unlock(&instance->guard); 156 281 return EOK; 157 282 } … … 165 290 rh_interrupt(&instance->rh); 166 291 167 usb_log_info("OHCI interrupt: %x.\n", status); 168 169 170 LIST_INITIALIZE(done); 171 transfer_list_remove_finished(&instance->transfers_interrupt, &done); 172 transfer_list_remove_finished(&instance->transfers_isochronous, &done); 173 transfer_list_remove_finished(&instance->transfers_control, &done); 174 transfer_list_remove_finished(&instance->transfers_bulk, &done); 175 176 while (!list_empty(&done)) { 177 link_t *item = done.next; 178 list_remove(item); 179 usb_transfer_batch_t *batch = 180 list_get_instance(item, usb_transfer_batch_t, link); 181 usb_transfer_batch_finish(batch); 292 usb_log_debug("OHCI interrupt: %x.\n", status); 293 294 if (status & IS_WDH) { 295 fibril_mutex_lock(&instance->guard); 296 usb_log_debug2("HCCA: %p-%p(%p).\n", instance->hcca, 297 instance->registers->hcca, addr_to_phys(instance->hcca)); 298 usb_log_debug2("Periodic current: %p.\n", 299 instance->registers->periodic_current); 300 301 link_t *current = instance->pending_batches.next; 302 while (current != &instance->pending_batches) { 303 link_t *next = current->next; 304 usb_transfer_batch_t *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; 312 } 313 fibril_mutex_unlock(&instance->guard); 182 314 } 183 315 } … … 191 323 instance->registers->interrupt_status = status; 192 324 hc_interrupt(instance, status); 193 async_usleep( 1000);325 async_usleep(50000); 194 326 } 195 327 return EOK; … … 267 399 instance->registers->control); 268 400 401 /* Use HCCA */ 402 instance->registers->hcca = addr_to_phys(instance->hcca); 403 404 /* Use queues */ 405 instance->registers->bulk_head = 406 instance->lists[USB_TRANSFER_BULK].list_head_pa; 407 usb_log_debug2("Bulk HEAD set to: %p(%p).\n", 408 instance->lists[USB_TRANSFER_BULK].list_head, 409 instance->lists[USB_TRANSFER_BULK].list_head_pa); 410 411 instance->registers->control_head = 412 instance->lists[USB_TRANSFER_CONTROL].list_head_pa; 413 usb_log_debug2("Control HEAD set to: %p(%p).\n", 414 instance->lists[USB_TRANSFER_CONTROL].list_head, 415 instance->lists[USB_TRANSFER_CONTROL].list_head_pa); 416 269 417 /* Enable queues */ 270 418 instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE); … … 296 444 assert(instance); 297 445 298 #define SETUP_ TRANSFER_LIST(type, name) \446 #define SETUP_ENDPOINT_LIST(type) \ 299 447 do { \ 300 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); \ 301 450 if (ret != EOK) { \ 302 usb_log_error("Failed(%d) to setup %s transferlist.\n", \451 usb_log_error("Failed(%d) to setup %s endpoint list.\n", \ 303 452 ret, name); \ 304 transfer_list_fini(&instance->transfers_isochronous); \305 transfer_list_fini(&instance->transfers_interrupt); \306 transfer_list_fini(&instance->transfers_control); \307 transfer_list_fini(&instance->transfers_bulk); \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]); \ 308 457 } \ 309 458 } while (0) 310 459 311 SETUP_TRANSFER_LIST(transfers_isochronous, "ISOCHRONOUS"); 312 SETUP_TRANSFER_LIST(transfers_interrupt, "INTERRUPT"); 313 SETUP_TRANSFER_LIST(transfers_control, "CONTROL"); 314 SETUP_TRANSFER_LIST(transfers_bulk, "BULK"); 315 316 transfer_list_set_next(&instance->transfers_interrupt, 317 &instance->transfers_isochronous); 318 319 /* Assign pointers to be used during scheduling */ 320 instance->transfers[USB_TRANSFER_INTERRUPT] = 321 &instance->transfers_interrupt; 322 instance->transfers[USB_TRANSFER_ISOCHRONOUS] = 323 &instance->transfers_interrupt; 324 instance->transfers[USB_TRANSFER_CONTROL] = 325 &instance->transfers_control; 326 instance->transfers[USB_TRANSFER_BULK] = 327 &instance->transfers_bulk; 328 329 return EOK; 330 #undef CHECK_RET_CLEAR_RETURN 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]); 467 468 return EOK; 331 469 } 332 470 /*----------------------------------------------------------------------------*/ … … 342 480 return ENOMEM; 343 481 bzero(instance->hcca, sizeof(hcca_t)); 344 instance->registers->hcca = addr_to_phys(instance->hcca); 345 usb_log_debug2("OHCI HCCA initialized at %p(%p).\n", 346 instance->hcca, instance->registers->hcca); 347 348 /* Use queues */ 349 instance->registers->bulk_head = instance->transfers_bulk.list_head_pa; 350 usb_log_debug2("Bulk HEAD set to: %p(%p).\n", 351 instance->transfers_bulk.list_head, 352 instance->transfers_bulk.list_head_pa); 353 354 instance->registers->control_head = 355 instance->transfers_control.list_head_pa; 356 usb_log_debug2("Control HEAD set to: %p(%p).\n", 357 instance->transfers_control.list_head, 358 instance->transfers_control.list_head_pa); 482 usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca); 359 483 360 484 unsigned i = 0; 361 485 for (; i < 32; ++i) { 362 486 instance->hcca->int_ep[i] = 363 instance-> transfers_interrupt.list_head_pa;487 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa; 364 488 } 365 489 usb_log_debug2("Interrupt HEADs set to: %p(%p).\n", 366 instance-> transfers_interrupt.list_head,367 instance-> transfers_interrupt.list_head_pa);490 instance->lists[USB_TRANSFER_INTERRUPT].list_head, 491 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa); 368 492 369 493 return EOK; -
uspace/drv/ohci/hc.h
re3b5129 rc7dd69d 48 48 #include "ohci_regs.h" 49 49 #include "root_hub.h" 50 #include " transfer_list.h"50 #include "endpoint_list.h" 51 51 #include "hw_struct/hcca.h" 52 52 53 53 typedef struct hc { 54 54 ohci_regs_t *registers; 55 hcca_t *hcca; 56 55 57 usb_address_t rh_address; 56 58 rh_t rh; 57 59 58 hcca_t *hcca; 60 endpoint_list_t lists[4]; 61 link_t pending_batches; 59 62 60 transfer_list_t transfers_isochronous;61 transfer_list_t transfers_interrupt;62 transfer_list_t transfers_control;63 transfer_list_t transfers_bulk;64 65 transfer_list_t *transfers[4];66 67 ddf_fun_t *ddf_instance;68 63 usb_device_keeper_t manager; 69 64 usb_endpoint_manager_t ep_manager; 70 65 fid_t interrupt_emulator; 66 fibril_mutex_t guard; 71 67 } hc_t; 72 68 … … 76 72 uintptr_t regs, size_t reg_size, bool interrupts); 77 73 78 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);79 80 void hc_interrupt(hc_t *instance, uint32_t status);81 82 74 /** Safely dispose host controller internal structures 83 75 * … … 85 77 */ 86 78 static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ }; 79 80 int hc_add_endpoint(hc_t *instance, usb_address_t address, usb_endpoint_t ep, 81 usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction, 82 size_t max_packet_size, size_t size, unsigned interval); 83 84 int hc_remove_endpoint(hc_t *instance, usb_address_t address, 85 usb_endpoint_t endpoint, usb_direction_t direction); 86 87 endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address, 88 usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw); 89 90 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch); 91 92 void hc_interrupt(hc_t *instance, uint32_t status); 87 93 88 94 /** Get and cast pointer to the driver data -
uspace/drv/ohci/hcd_endpoint.h
re3b5129 rc7dd69d 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.c
re3b5129 rc7dd69d 53 53 << ED_STATUS_MPS_SHIFT); 54 54 55 55 56 if (ep->speed == USB_SPEED_LOW) 56 57 instance->status |= ED_STATUS_S_FLAG; 57 58 if (ep->transfer_type == USB_TRANSFER_ISOCHRONOUS) 58 59 instance->status |= ED_STATUS_F_FLAG; 60 61 if (ep->toggle) 62 instance->td_head |= ED_TDHEAD_TOGGLE_CARRY; 59 63 } 60 64 /** -
uspace/drv/ohci/hw_struct/endpoint_descriptor.h
re3b5129 rc7dd69d 53 53 #define ED_STATUS_D_MASK (0x3) /* direction */ 54 54 #define ED_STATUS_D_SHIFT (11) 55 #define ED_STATUS_D_ IN(0x1)56 #define ED_STATUS_D_ OUT(0x2)55 #define ED_STATUS_D_OUT (0x1) 56 #define ED_STATUS_D_IN (0x2) 57 57 #define ED_STATUS_D_TRANSFER (0x3) 58 58 … … 73 73 #define ED_TDHEAD_ZERO_SHIFT (2) 74 74 #define ED_TDHEAD_TOGGLE_CARRY (0x2) 75 #define ED_TDHEAD_HALTED_FLAG (0x1) 75 76 76 77 volatile uint32_t next; … … 81 82 void ed_init(ed_t *instance, endpoint_t *ep); 82 83 83 static inline void ed_ add_tds(ed_t *instance, td_t *head, td_t *tail)84 static inline void ed_set_td(ed_t *instance, td_t *td) 84 85 { 85 86 assert(instance); 86 instance->td_head = addr_to_phys(head) & ED_TDHEAD_PTR_MASK; 87 instance->td_tail = addr_to_phys(tail) & ED_TDTAIL_PTR_MASK; 87 uintptr_t pa = addr_to_phys(td); 88 instance->td_head = 89 ((pa & ED_TDHEAD_PTR_MASK) 90 | (instance->td_head & ~ED_TDHEAD_PTR_MASK)); 91 instance->td_tail = pa & ED_TDTAIL_PTR_MASK; 92 } 93 94 static inline void ed_set_end_td(ed_t *instance, td_t *td) 95 { 96 assert(instance); 97 uintptr_t pa = addr_to_phys(td); 98 instance->td_tail = pa & ED_TDTAIL_PTR_MASK; 88 99 } 89 100 … … 97 108 } 98 109 110 static inline int ed_toggle_get(ed_t *instance) 111 { 112 assert(instance); 113 return (instance->td_head & ED_TDHEAD_TOGGLE_CARRY) ? 1 : 0; 114 } 115 116 static inline void ed_toggle_set(ed_t *instance, int toggle) 117 { 118 assert(instance); 119 assert(toggle == 0 || toggle == 1); 120 if (toggle == 1) { 121 instance->td_head |= ED_TDHEAD_TOGGLE_CARRY; 122 } else { 123 /* clear halted flag when reseting toggle */ 124 instance->td_head &= ~ED_TDHEAD_TOGGLE_CARRY; 125 instance->td_head &= ~ED_TDHEAD_HALTED_FLAG; 126 } 127 } 99 128 #endif 100 129 /** -
uspace/drv/ohci/hw_struct/hcca.h
re3b5129 rc7dd69d 43 43 uint32_t done_head; 44 44 uint32_t reserved[29]; 45 } __attribute__((packed )) hcca_t;45 } __attribute__((packed, aligned)) hcca_t; 46 46 47 47 #endif -
uspace/drv/ohci/hw_struct/transfer_descriptor.c
re3b5129 rc7dd69d 53 53 } 54 54 if (buffer != NULL) { 55 assert(size != 0); 55 56 instance->cbp = addr_to_phys(buffer); 56 57 instance->be = addr_to_phys(buffer + size - 1); -
uspace/drv/ohci/hw_struct/transfer_descriptor.h
re3b5129 rc7dd69d 50 50 #define TD_STATUS_DP_SHIFT (19) 51 51 #define TD_STATUS_DP_SETUP (0x0) 52 #define TD_STATUS_DP_ IN(0x1)53 #define TD_STATUS_DP_ OUT(0x2)52 #define TD_STATUS_DP_OUT (0x1) 53 #define TD_STATUS_DP_IN (0x2) 54 54 #define TD_STATUS_DI_MASK (0x7) /* delay interrupt, wait DI frames before int */ 55 55 #define TD_STATUS_DI_SHIFT (21) … … 86 86 int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK; 87 87 /* something went wrong, error code is set */ 88 if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2 && cc != CC_NOERROR) {88 if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2) { 89 89 return true; 90 90 } -
uspace/drv/ohci/iface.c
re3b5129 rc7dd69d 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/ohci.ma
re3b5129 rc7dd69d 1 1 10 pci/ven=106b&dev=003f 2 10 pci/ven=10de&dev=0aa5 3 10 pci/ven=10de&dev=0aa5 -
uspace/drv/ohci/ohci_regs.h
re3b5129 rc7dd69d 55 55 #define C_HCFS_MASK (0x3) /* Host controller functional state */ 56 56 #define C_HCFS_RESET (0x0) 57 #define C_HCFS_ OPERATIONAL(0x1)58 #define C_HCFS_ RESUME(0x2)57 #define C_HCFS_RESUME (0x1) 58 #define C_HCFS_OPERATIONAL (0x2) 59 59 #define C_HCFS_SUSPEND (0x3) 60 60 #define C_HCFS_SHIFT (6) … … 100 100 #define HCCA_PTR_MASK 0xffffff00 /* HCCA is 256B aligned */ 101 101 102 /** Currently executed period endpoint */103 const volatile uint32_t period _current;102 /** Currently executed periodic endpoint */ 103 const volatile uint32_t periodic_current; 104 104 105 105 /** The first control endpoint */ -
uspace/drv/ohci/root_hub.c
re3b5129 rc7dd69d 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
re3b5129 rc7dd69d 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/ohci/utils/malloc32.h
re3b5129 rc7dd69d 41 41 #include <as.h> 42 42 43 #define UHCI_STRCUTURES_ALIGNMENT 1644 43 #define UHCI_REQUIRED_PAGE_SIZE 4096 45 44 … … 65 64 */ 66 65 static inline void * malloc32(size_t size) 67 { return memalign( UHCI_STRCUTURES_ALIGNMENT, size); }66 { return memalign(size, size); } 68 67 /*----------------------------------------------------------------------------*/ 69 68 /** Physical mallocator simulator -
uspace/drv/uhci-hcd/batch.c
re3b5129 rc7dd69d 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
re3b5129 rc7dd69d 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
re3b5129 rc7dd69d 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"); … … 260 247 { 261 248 assert(instance); 262 #define CHECK_RET_CLEAR_RETURN(ret, message...) \ 249 #define SETUP_TRANSFER_LIST(type, name) \ 250 do { \ 251 int ret = transfer_list_init(&instance->transfers_##type, name); \ 263 252 if (ret != EOK) { \ 264 usb_log_error(message); \ 253 usb_log_error("Failed(%d) to setup %s transfer list: %s.\n", \ 254 ret, name, str_error(ret)); \ 265 255 transfer_list_fini(&instance->transfers_bulk_full); \ 266 256 transfer_list_fini(&instance->transfers_control_full); \ … … 268 258 transfer_list_fini(&instance->transfers_interrupt); \ 269 259 return ret; \ 270 } else (void) 0 271 272 /* initialize TODO: check errors */ 273 int ret; 274 ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL"); 275 CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list."); 276 277 ret = transfer_list_init( 278 &instance->transfers_control_full, "CONTROL_FULL"); 279 CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list."); 280 281 ret = transfer_list_init( 282 &instance->transfers_control_slow, "CONTROL_SLOW"); 283 CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list."); 284 285 ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT"); 286 CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list."); 287 260 } \ 261 } while (0) 262 263 SETUP_TRANSFER_LIST(bulk_full, "BULK FULL"); 264 SETUP_TRANSFER_LIST(control_full, "CONTROL FULL"); 265 SETUP_TRANSFER_LIST(control_slow, "CONTROL LOW"); 266 SETUP_TRANSFER_LIST(interrupt, "INTERRUPT"); 267 #undef SETUP_TRANSFER_LIST 268 /* Connect lists into one schedule */ 288 269 transfer_list_set_next(&instance->transfers_control_full, 289 270 &instance->transfers_bulk_full); … … 329 310 330 311 transfer_list_t *list = 331 instance->transfers[batch-> speed][batch->transfer_type];312 instance->transfers[batch->ep->speed][batch->ep->transfer_type]; 332 313 assert(list); 333 314 transfer_list_add_batch(list, batch); … … 350 331 assert(instance); 351 332 // status |= 1; //Uncomment to work around qemu hang 352 /* TODO: Resume interrupts are not supported */353 333 /* Lower 2 bits are transaction error and transaction complete */ 354 if (status & 0x3) {334 if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) { 355 335 LIST_INITIALIZE(done); 356 336 transfer_list_remove_finished( … … 371 351 } 372 352 } 373 /* bits 4 and 5 indicate hc error */ 374 if (status & 0x18) { 353 /* Resume interrupts are not supported */ 354 355 /* Bits 4 and 5 indicate hc error */ 356 if (status & (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)) { 375 357 usb_log_error("UHCI hardware failure!.\n"); 376 358 ++instance->hw_failures; … … 402 384 403 385 while (1) { 404 /* read and ack interrupts*/386 /* Readd and clear status register */ 405 387 uint16_t status = pio_read_16(&instance->registers->usbsts); 406 pio_write_16(&instance->registers->usbsts, 0x1f);388 pio_write_16(&instance->registers->usbsts, status); 407 389 if (status != 0) 408 390 usb_log_debug2("UHCI status: %x.\n", status); 409 391 hc_interrupt(instance, status); 410 async_usleep(UHCI_ CLEANER_TIMEOUT);392 async_usleep(UHCI_INT_EMULATOR_TIMEOUT); 411 393 } 412 394 return EOK; … … 479 461 #undef QH 480 462 } 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 463 /** 509 464 * @} -
uspace/drv/uhci-hcd/hc.h
re3b5129 rc7dd69d 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; 79 88 80 89 #define UHCI_FRAME_LIST_COUNT 1024 81 #define UHCI_ CLEANER_TIMEOUT 1000090 #define UHCI_INT_EMULATOR_TIMEOUT 10000 82 91 #define UHCI_DEBUGER_TIMEOUT 5000000 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
re3b5129 rc7dd69d 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
re3b5129 rc7dd69d 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
re3b5129 rc7dd69d 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
re3b5129 rc7dd69d 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
re3b5129 rc7dd69d 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 } 78 78 device->driver_data = uhci; 79 79 80 usb_log_info("Controlling new UHCI device `%s'.\n", device->name);80 usb_log_info("Controlling new UHCI device '%s'.\n", device->name); 81 81 82 82 return EOK; … … 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
re3b5129 rc7dd69d 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
re3b5129 rc7dd69d 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
re3b5129 rc7dd69d 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
re3b5129 rc7dd69d 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
re3b5129 rc7dd69d 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
re3b5129 rc7dd69d 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
re3b5129 rc7dd69d 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 /** -
uspace/drv/uhci-rhd/port.c
re3b5129 rc7dd69d 68 68 * @return Error code. (Always EOK) 69 69 */ 70 static inline void uhci_port_write_status( 71 uhci_port_t *port, port_status_t value) 72 { 73 assert(port); 74 pio_write_16(port->address, value); 70 static inline void uhci_port_write_status(uhci_port_t *port, port_status_t val) 71 { 72 assert(port); 73 pio_write_16(port->address, val); 75 74 } 76 75 /*----------------------------------------------------------------------------*/ … … 101 100 port->rh = rh; 102 101 103 int r c = usb_hc_connection_initialize_from_device(104 &port->hc_connection, rh);105 if (r c!= EOK) {102 int ret = 103 usb_hc_connection_initialize_from_device(&port->hc_connection, rh); 104 if (ret != EOK) { 106 105 usb_log_error("Failed to initialize connection to HC."); 107 return r c;106 return ret; 108 107 } 109 108 … … 238 237 /* Enable the port. */ 239 238 uhci_port_set_enabled(port, true); 240 241 239 return EOK; 242 240 } … … 271 269 usb_log_info("New device at port %u, address %d (handle %llu).\n", 272 270 port->number, dev_addr, port->attached_device); 273 274 271 return EOK; 275 272 } … … 313 310 /* Write new value. */ 314 311 uhci_port_write_status(port, port_status); 312 313 /* Wait for port to become enabled */ 314 do { 315 async_usleep(1000); 316 port_status = uhci_port_read_status(port); 317 } while ((port_status & STATUS_CONNECTED) && 318 !(port_status & STATUS_ENABLED)); 315 319 316 320 usb_log_debug("%s: %sabled port.\n", -
uspace/drv/uhci-rhd/port.h
re3b5129 rc7dd69d 54 54 #define STATUS_SUSPEND (1 << 12) 55 55 56 /** UHCI port structure */ 56 57 typedef struct uhci_port 57 58 { -
uspace/drv/uhci-rhd/root_hub.c
re3b5129 rc7dd69d 33 33 */ 34 34 #include <errno.h> 35 #include <str_error.h> 35 36 #include <ddi.h> 36 37 #include <usb/debug.h> … … 43 44 * @param[in] addr Address of I/O registers. 44 45 * @param[in] size Size of available I/O space. 45 * @param[in] rh Pointer to ddfinstance of the root hub driver.46 * @param[in] rh Pointer to DDF instance of the root hub driver. 46 47 * @return Error code. 47 48 */ … … 58 59 if (ret < 0) { 59 60 usb_log_error( 60 "Failed(%d) to gain access to port registers at %p \n",61 ret, regs );61 "Failed(%d) to gain access to port registers at %p: %s.\n", 62 ret, regs, str_error(ret)); 62 63 return ret; 63 64 } … … 66 67 unsigned i = 0; 67 68 for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) { 68 /* NOTE: mind pointer arithmetics here */69 69 ret = uhci_port_init( 70 &instance->ports[i], regs + i, i, ROOT_HUB_WAIT_USEC, rh);70 &instance->ports[i], ®s[i], i, ROOT_HUB_WAIT_USEC, rh); 71 71 if (ret != EOK) { 72 72 unsigned j = 0; -
uspace/drv/uhci-rhd/root_hub.h
re3b5129 rc7dd69d 42 42 #define ROOT_HUB_WAIT_USEC 250000 /* 250 miliseconds */ 43 43 44 /** UHCI root hub drvier structure */ 44 45 typedef struct root_hub { 46 /** Ports provided by the hub */ 45 47 uhci_port_t ports[UHCI_ROOT_HUB_PORT_COUNT]; 46 devman_handle_t hc_handle;47 48 } uhci_root_hub_t; 48 49 49 50 int uhci_root_hub_init( 50 uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh);51 uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh); 51 52 52 53 void uhci_root_hub_fini(uhci_root_hub_t *instance); -
uspace/drv/usbhid/main.c
re3b5129 rc7dd69d 42 42 43 43 #include <usb/devdrv.h> 44 #include <usb/devpoll.h> 44 45 45 46 #include "usbhid.h" -
uspace/drv/usbhid/usbhid.c
re3b5129 rc7dd69d 379 379 rc = usb_hid_check_pipes(hid_dev, dev); 380 380 if (rc != EOK) { 381 usb_hid_free(&hid_dev);381 //usb_hid_free(&hid_dev); 382 382 return rc; 383 383 } … … 387 387 if (rc != EOK) { 388 388 usb_log_error("Failed to initialize report parser.\n"); 389 usb_hid_free(&hid_dev);389 //usb_hid_free(&hid_dev); 390 390 return rc; 391 391 } … … 405 405 " device.\n"); 406 406 fallback = true; 407 assert(hid_dev->subdrivers == NULL); 408 assert(hid_dev->subdriver_count == 0); 407 409 } 408 410 } else { … … 445 447 usb_log_error("No subdriver for handling this device could be" 446 448 " initialized: %s.\n", str_error(rc)); 447 usb_hid_free(&hid_dev); 449 usb_log_debug("Subdriver count: %d\n", 450 hid_dev->subdriver_count); 451 //usb_hid_free(&hid_dev); 448 452 } else { 449 453 bool ok = false; … … 569 573 } 570 574 575 usb_log_debug("Subdrivers: %p, subdriver count: %d\n", 576 (*hid_dev)->subdrivers, (*hid_dev)->subdriver_count); 577 571 578 assert((*hid_dev)->subdrivers != NULL 572 579 || (*hid_dev)->subdriver_count == 0); -
uspace/drv/usbhub/usbhub.c
re3b5129 rc7dd69d 45 45 #include <usb/request.h> 46 46 #include <usb/classes/hub.h> 47 #include <usb/devpoll.h> 47 48 #include <stdio.h> 48 49 … … 247 248 for (port = 0; port < hub_info->port_count + 1; port++) { 248 249 usb_hub_port_init(&hub_info->ports[port]); 250 } 251 for (port = 0; port < hub_info->port_count; port++) { 252 opResult = usb_hub_set_port_feature(hub_info->control_pipe, 253 port+1, USB_HUB_FEATURE_PORT_POWER); 254 if (opResult != EOK) { 255 usb_log_error("cannot power on port %d; %d\n", 256 port+1, opResult); 257 } 249 258 } 250 259 usb_log_debug2("freeing data\n"); -
uspace/drv/usbkbd/main.c
re3b5129 rc7dd69d 42 42 43 43 #include <usb/devdrv.h> 44 #include <usb/devpoll.h> 44 45 45 46 #include "kbddev.h" -
uspace/drv/usbmast/mast.h
re3b5129 rc7dd69d 1 1 /* 2 * Copyright (c) 2007 Jan Hudecek 3 * Copyright (c) 2008 Martin Decky 2 * Copyright (c) 2011 Vojtech Horky 4 3 * All rights reserved. 5 4 * … … 28 27 */ 29 28 30 /** @addtogroup genericproc29 /** @addtogroup drvusbmast 31 30 * @{ 32 31 */ 33 /** @file tasklet.c34 * @brief Tasklet implementation32 /** @file 33 * Generic functions for USB mass storage. 35 34 */ 36 35 37 #include <proc/tasklet.h> 38 #include <synch/spinlock.h> 39 #include <mm/slab.h> 40 #include <config.h> 36 #ifndef USB_USBMAST_MAST_H_ 37 #define USB_USBMAST_MAST_H_ 41 38 42 /** Spinlock protecting list of tasklets */ 43 SPINLOCK_INITIALIZE(tasklet_lock); 39 #include <sys/types.h> 40 #include <usb/usb.h> 41 #include <usb/pipes.h> 44 42 45 /** Array of tasklet lists for every CPU */ 46 tasklet_descriptor_t **tasklet_list;43 int usb_massstor_data_in(usb_pipe_t *, usb_pipe_t *, uint32_t, uint8_t, 44 void *, size_t, void *, size_t, size_t *); 47 45 48 void tasklet_init(void) 49 { 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"); 60 } 46 #endif 61 47 62 63 /** @}48 /** 49 * @} 64 50 */ -
uspace/drv/usbmouse/main.c
re3b5129 rc7dd69d 36 36 #include "mouse.h" 37 37 #include <usb/debug.h> 38 #include <usb/devpoll.h> 38 39 #include <errno.h> 39 40 #include <str_error.h>
Note:
See TracChangeset
for help on using the changeset viewer.
