Changeset df6ded8 in mainline for uspace/drv/bus/usb/uhci/uhci_batch.c
- Timestamp:
- 2018-02-28T16:37:50Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1b20da0
- Parents:
- f5e5f73 (diff), b2dca8de (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. - git-author:
- Jakub Jermar <jakub@…> (2018-02-28 16:06:42)
- git-committer:
- Jakub Jermar <jakub@…> (2018-02-28 16:37:50)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/uhci/uhci_batch.c
rf5e5f73 rdf6ded8 1 1 /* 2 2 * Copyright (c) 2011 Jan Vesely 3 * Copyright (c) 2018 Ondrej Hlavaty 3 4 * All rights reserved. 4 5 * … … 46 47 47 48 #include "uhci_batch.h" 49 #include "hc.h" 48 50 #include "hw_struct/transfer_descriptor.h" 49 51 50 52 #define DEFAULT_ERROR_COUNT 3 51 53 52 /** Safely destructs uhci_transfer_batch_t structure. 54 /** Transfer batch setup table. */ 55 static void (*const batch_setup[])(uhci_transfer_batch_t*); 56 57 /** Destroys uhci_transfer_batch_t structure. 53 58 * 54 59 * @param[in] uhci_batch Instance to destroy. 55 60 */ 56 static void uhci_transfer_batch_dispose(uhci_transfer_batch_t *uhci_batch) 57 { 58 if (uhci_batch) { 59 usb_transfer_batch_destroy(uhci_batch->usb_batch); 60 free32(uhci_batch->device_buffer); 61 free(uhci_batch); 62 } 63 } 64 65 /** Finishes usb_transfer_batch and destroys the structure. 66 * 67 * @param[in] uhci_batch Instance to finish and destroy. 68 */ 69 void uhci_transfer_batch_finish_dispose(uhci_transfer_batch_t *uhci_batch) 61 void uhci_transfer_batch_destroy(uhci_transfer_batch_t *uhci_batch) 70 62 { 71 63 assert(uhci_batch); 72 assert(uhci_batch->usb_batch); 73 assert(!link_in_use(&uhci_batch->link)); 74 usb_transfer_batch_finish(uhci_batch->usb_batch, 75 uhci_transfer_batch_data_buffer(uhci_batch)); 76 uhci_transfer_batch_dispose(uhci_batch); 77 } 78 79 /** Transfer batch setup table. */ 80 static void (*const batch_setup[])(uhci_transfer_batch_t*, usb_direction_t); 64 dma_buffer_free(&uhci_batch->uhci_dma_buffer); 65 free(uhci_batch); 66 } 81 67 82 68 /** Allocate memory and initialize internal data structure. … … 85 71 * @return Valid pointer if all structures were successfully created, 86 72 * NULL otherwise. 73 */ 74 uhci_transfer_batch_t * uhci_transfer_batch_create(endpoint_t *ep) 75 { 76 uhci_transfer_batch_t *uhci_batch = 77 calloc(1, sizeof(uhci_transfer_batch_t)); 78 if (!uhci_batch) { 79 usb_log_error("Failed to allocate UHCI batch."); 80 return NULL; 81 } 82 83 usb_transfer_batch_init(&uhci_batch->base, ep); 84 85 link_initialize(&uhci_batch->link); 86 return uhci_batch; 87 } 88 89 /* Prepares batch for commiting. 87 90 * 88 91 * Determines the number of needed transfer descriptors (TDs). … … 90 93 * Initializes parameters needed for the transfer and callback. 91 94 */ 92 uhci_transfer_batch_t * uhci_transfer_batch_get(usb_transfer_batch_t *usb_batch)95 int uhci_transfer_batch_prepare(uhci_transfer_batch_t *uhci_batch) 93 96 { 94 97 static_assert((sizeof(td_t) % 16) == 0); 95 #define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \ 96 if (ptr == NULL) { \ 97 usb_log_error(message); \ 98 uhci_transfer_batch_dispose(uhci_batch); \ 99 return NULL; \ 100 } else (void)0 101 102 uhci_transfer_batch_t *uhci_batch = 103 calloc(1, sizeof(uhci_transfer_batch_t)); 104 CHECK_NULL_DISPOSE_RETURN(uhci_batch, 105 "Failed to allocate UHCI batch.\n"); 106 link_initialize(&uhci_batch->link); 107 uhci_batch->td_count = 108 (usb_batch->buffer_size + usb_batch->ep->max_packet_size - 1) 109 / usb_batch->ep->max_packet_size; 98 99 usb_transfer_batch_t *usb_batch = &uhci_batch->base; 100 101 uhci_batch->td_count = (usb_batch->size + usb_batch->ep->max_packet_size - 1) 102 / usb_batch->ep->max_packet_size; 103 110 104 if (usb_batch->ep->transfer_type == USB_TRANSFER_CONTROL) { 111 105 uhci_batch->td_count += 2; 112 106 } 113 107 108 const size_t setup_size = (usb_batch->ep->transfer_type == USB_TRANSFER_CONTROL) 109 ? USB_SETUP_PACKET_SIZE 110 : 0; 111 114 112 const size_t total_size = (sizeof(td_t) * uhci_batch->td_count) 115 + sizeof(qh_t) + usb_batch->setup_size + usb_batch->buffer_size; 116 uhci_batch->device_buffer = malloc32(total_size); 117 CHECK_NULL_DISPOSE_RETURN(uhci_batch->device_buffer, 118 "Failed to allocate UHCI buffer.\n"); 119 memset(uhci_batch->device_buffer, 0, total_size); 120 121 uhci_batch->tds = uhci_batch->device_buffer; 122 uhci_batch->qh = 123 (uhci_batch->device_buffer + (sizeof(td_t) * uhci_batch->td_count)); 113 + sizeof(qh_t) + setup_size; 114 115 if (dma_buffer_alloc(&uhci_batch->uhci_dma_buffer, total_size)) { 116 usb_log_error("Failed to allocate UHCI buffer."); 117 return ENOMEM; 118 } 119 memset(uhci_batch->uhci_dma_buffer.virt, 0, total_size); 120 121 uhci_batch->tds = uhci_batch->uhci_dma_buffer.virt; 122 uhci_batch->qh = (qh_t *) &uhci_batch->tds[uhci_batch->td_count]; 124 123 125 124 qh_init(uhci_batch->qh); 126 125 qh_set_element_td(uhci_batch->qh, &uhci_batch->tds[0]); 127 126 128 void *dest = 129 uhci_batch->device_buffer + (sizeof(td_t) * uhci_batch->td_count) 130 + sizeof(qh_t); 127 void *setup_buffer = uhci_transfer_batch_setup_buffer(uhci_batch); 128 assert(setup_buffer == (void *) (uhci_batch->qh + 1)); 131 129 /* Copy SETUP packet data to the device buffer */ 132 memcpy(dest, usb_batch->setup_buffer, usb_batch->setup_size); 133 dest += usb_batch->setup_size; 134 /* Copy generic data unless they are provided by the device */ 135 if (usb_batch->ep->direction != USB_DIRECTION_IN) { 136 memcpy(dest, usb_batch->buffer, usb_batch->buffer_size); 137 } 138 uhci_batch->usb_batch = usb_batch; 130 memcpy(setup_buffer, usb_batch->setup.buffer, setup_size); 131 139 132 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT 140 " memory structures ready. \n", usb_batch,133 " memory structures ready.", usb_batch, 141 134 USB_TRANSFER_BATCH_ARGS(*usb_batch)); 142 135 143 const usb_direction_t dir = usb_transfer_batch_direction(usb_batch);144 145 136 assert(batch_setup[usb_batch->ep->transfer_type]); 146 batch_setup[usb_batch->ep->transfer_type](uhci_batch , dir);147 148 return uhci_batch;137 batch_setup[usb_batch->ep->transfer_type](uhci_batch); 138 139 return EOK; 149 140 } 150 141 … … 158 149 * is reached. 159 150 */ 160 bool uhci_transfer_batch_ is_complete(constuhci_transfer_batch_t *uhci_batch)151 bool uhci_transfer_batch_check_completed(uhci_transfer_batch_t *uhci_batch) 161 152 { 162 153 assert(uhci_batch); 163 assert(uhci_batch->usb_batch);154 usb_transfer_batch_t *batch = &uhci_batch->base; 164 155 165 156 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT 166 " checking %zu transfer(s) for completion.\n", 167 uhci_batch->usb_batch, 168 USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch), 157 " checking %zu transfer(s) for completion.", 158 uhci_batch, USB_TRANSFER_BATCH_ARGS(*batch), 169 159 uhci_batch->td_count); 170 uhci_batch->usb_batch->transfered_size = 0; 160 batch->transferred_size = 0; 161 162 uhci_endpoint_t *uhci_ep = (uhci_endpoint_t *) batch->ep; 171 163 172 164 for (size_t i = 0;i < uhci_batch->td_count; ++i) { … … 175 167 } 176 168 177 uhci_batch->usb_batch->error = td_status(&uhci_batch->tds[i]);178 if ( uhci_batch->usb_batch->error != EOK) {179 assert( uhci_batch->usb_batch->ep != NULL);169 batch->error = td_status(&uhci_batch->tds[i]); 170 if (batch->error != EOK) { 171 assert(batch->ep != NULL); 180 172 181 173 usb_log_debug("Batch %p found error TD(%zu->%p):%" 182 PRIx32 ". \n", uhci_batch->usb_batch, i,174 PRIx32 ".", uhci_batch, i, 183 175 &uhci_batch->tds[i], uhci_batch->tds[i].status); 184 176 td_print_status(&uhci_batch->tds[i]); 185 177 186 endpoint_toggle_set(uhci_batch->usb_batch->ep, 187 td_toggle(&uhci_batch->tds[i])); 188 if (i > 0) 189 goto substract_ret; 190 return true; 178 uhci_ep->toggle = td_toggle(&uhci_batch->tds[i]); 179 goto substract_ret; 191 180 } 192 181 193 uhci_batch->usb_batch->transfered_size182 batch->transferred_size 194 183 += td_act_size(&uhci_batch->tds[i]); 195 184 if (td_is_short(&uhci_batch->tds[i])) … … 197 186 } 198 187 substract_ret: 199 uhci_batch->usb_batch->transfered_size 200 -= uhci_batch->usb_batch->setup_size; 188 if (batch->transferred_size > 0 && batch->ep->transfer_type == USB_TRANSFER_CONTROL) { 189 assert(batch->transferred_size >= USB_SETUP_PACKET_SIZE); 190 batch->transferred_size -= USB_SETUP_PACKET_SIZE; 191 } 192 193 assert(batch->transferred_size <= batch->size); 194 201 195 return true; 202 196 } … … 216 210 * The last transfer is marked with IOC flag. 217 211 */ 218 static void batch_data(uhci_transfer_batch_t *uhci_batch , usb_direction_t dir)212 static void batch_data(uhci_transfer_batch_t *uhci_batch) 219 213 { 220 214 assert(uhci_batch); 221 assert(uhci_batch->usb_batch); 222 assert(uhci_batch->usb_batch->ep);215 216 usb_direction_t dir = uhci_batch->base.dir; 223 217 assert(dir == USB_DIRECTION_OUT || dir == USB_DIRECTION_IN); 224 218 … … 226 220 const usb_packet_id pid = direction_pids[dir]; 227 221 const bool low_speed = 228 uhci_batch->usb_batch->ep->speed == USB_SPEED_LOW; 229 const size_t mps = uhci_batch->usb_batch->ep->max_packet_size; 230 const usb_target_t target = {{ 231 uhci_batch->usb_batch->ep->address, 232 uhci_batch->usb_batch->ep->endpoint }}; 233 234 int toggle = endpoint_toggle_get(uhci_batch->usb_batch->ep); 222 uhci_batch->base.ep->device->speed == USB_SPEED_LOW; 223 const size_t mps = uhci_batch->base.ep->max_packet_size; 224 225 uhci_endpoint_t *uhci_ep = (uhci_endpoint_t *) uhci_batch->base.ep; 226 227 int toggle = uhci_ep->toggle; 235 228 assert(toggle == 0 || toggle == 1); 236 229 237 230 size_t td = 0; 238 size_t remain_size = uhci_batch-> usb_batch->buffer_size;231 size_t remain_size = uhci_batch->base.size; 239 232 char *buffer = uhci_transfer_batch_data_buffer(uhci_batch); 240 233 … … 248 241 td_init( 249 242 &uhci_batch->tds[td], DEFAULT_ERROR_COUNT, packet_size, 250 toggle, false, low_speed, target, pid, buffer, next_td);243 toggle, false, low_speed, uhci_batch->base.target, pid, buffer, next_td); 251 244 252 245 ++td; … … 256 249 } 257 250 td_set_ioc(&uhci_batch->tds[td - 1]); 258 endpoint_toggle_set(uhci_batch->usb_batch->ep, toggle);251 uhci_ep->toggle = toggle; 259 252 usb_log_debug2( 260 "Batch %p %s %s " USB_TRANSFER_BATCH_FMT " initialized. \n", \261 uhci_batch ->usb_batch,262 usb_str_transfer_type(uhci_batch-> usb_batch->ep->transfer_type),263 usb_str_direction(uhci_batch-> usb_batch->ep->direction),264 USB_TRANSFER_BATCH_ARGS( *uhci_batch->usb_batch));253 "Batch %p %s %s " USB_TRANSFER_BATCH_FMT " initialized.", \ 254 uhci_batch, 255 usb_str_transfer_type(uhci_batch->base.ep->transfer_type), 256 usb_str_direction(uhci_batch->base.ep->direction), 257 USB_TRANSFER_BATCH_ARGS(uhci_batch->base)); 265 258 } 266 259 … … 276 269 * The last transfer is marked with IOC. 277 270 */ 278 static void batch_control(uhci_transfer_batch_t *uhci_batch , usb_direction_t dir)271 static void batch_control(uhci_transfer_batch_t *uhci_batch) 279 272 { 280 273 assert(uhci_batch); 281 assert(uhci_batch->usb_batch); 282 assert(uhci_batch->usb_batch->ep);274 275 usb_direction_t dir = uhci_batch->base.dir; 283 276 assert(dir == USB_DIRECTION_OUT || dir == USB_DIRECTION_IN); 284 277 assert(uhci_batch->td_count >= 2); … … 291 284 const usb_packet_id status_stage_pid = status_stage_pids[dir]; 292 285 const bool low_speed = 293 uhci_batch->usb_batch->ep->speed == USB_SPEED_LOW; 294 const size_t mps = uhci_batch->usb_batch->ep->max_packet_size; 295 const usb_target_t target = {{ 296 uhci_batch->usb_batch->ep->address, 297 uhci_batch->usb_batch->ep->endpoint }}; 286 uhci_batch->base.ep->device->speed == USB_SPEED_LOW; 287 const size_t mps = uhci_batch->base.ep->max_packet_size; 288 const usb_target_t target = uhci_batch->base.target; 298 289 299 290 /* setup stage */ 300 291 td_init( 301 292 &uhci_batch->tds[0], DEFAULT_ERROR_COUNT, 302 uhci_batch->usb_batch->setup_size, 0, false,293 USB_SETUP_PACKET_SIZE, 0, false, 303 294 low_speed, target, USB_PID_SETUP, 304 295 uhci_transfer_batch_setup_buffer(uhci_batch), &uhci_batch->tds[1]); … … 307 298 size_t td = 1; 308 299 unsigned toggle = 1; 309 size_t remain_size = uhci_batch-> usb_batch->buffer_size;300 size_t remain_size = uhci_batch->base.size; 310 301 char *buffer = uhci_transfer_batch_data_buffer(uhci_batch); 311 302 … … 333 324 td_set_ioc(&uhci_batch->tds[td]); 334 325 335 usb_log_debug2("Control last TD status: %x. \n",326 usb_log_debug2("Control last TD status: %x.", 336 327 uhci_batch->tds[td].status); 337 328 } 338 329 339 static void (*const batch_setup[])(uhci_transfer_batch_t* , usb_direction_t) =330 static void (*const batch_setup[])(uhci_transfer_batch_t*) = 340 331 { 341 332 [USB_TRANSFER_CONTROL] = batch_control,
Note:
See TracChangeset
for help on using the changeset viewer.