1/* 2 * Copyright (c) 2007-2013 ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#include <stdlib.h> 11#include <stdio.h> 12#include <string.h> 13#include <barrelfish/barrelfish.h> 14 15#include <usb/usb.h> 16 17 18#include <usb_device.h> 19#include <usb_controller.h> 20#include <usb_xfer.h> 21#include "usb_ohci.h" 22#include "usb_ohci_xfer.h" 23#include "usb_ohci_memory.h" 24#include "usb_ohci_queue.h" 25 26 27 28 29static void usb_ohci_xfer_short_frames(struct usb_xfer *xfer) 30{ 31 usb_ohci_td_t *td; 32 usb_ohci_ed_t *ed; 33 34 usb_ohci_td_ctrl_t *td_ctrl; 35 uint16_t cc; 36 usb_paddr_t td_next; 37 usb_paddr_t current_buffer; 38 39 td = xfer->hcd_td_cache; 40 41 /* 42 * loop over the frame, a frame may contain more than one short 43 * packets, we have to make sure that we reached the last one 44 */ 45 while (1) { 46 47 current_buffer = td->td_current_buffer; 48 td_ctrl = &td->td_control; 49 td_next = td->td_nextTD; 50 51 /* 52 * check if we have reached the last transfer descriptor 53 * if so we are done 54 */ 55 56 if (((void *) td) == xfer->hcd_td_last) { 57 td = NULL; 58 break; 59 } 60 61 /* 62 * check the condition codes, if it is USB_OHCI_STATUS_OK then 63 * the transfer is finished 64 */ 65 cc = td_ctrl->condition_code; 66 if (cc) { 67 td = NULL; 68 break; 69 } 70 71 /* 72 * check if we have reached the last packet i.e. the td_nextTD is 73 * NULL, but hwe have to mask out the last four bits, since these may 74 * be used otherwise. 75 * If we have a current buffer then there is something else in the 76 * frame we follow the alternative and stop processing. 77 */ 78 if (((td_next & (~0xF)) == 0) || current_buffer) { 79 td = td->alt_next; 80 break; 81 } 82 83 // go to next transfer descriptor 84 td = td->obj_next; 85 } 86 87 // update of the cache 88 xfer->hcd_td_cache = td; 89 90 /* 91 * we have found a non completed short transfer for this endpoint 92 * this means we have to update the head pointer of the endpoint 93 * descriptor to this one 94 */ 95 if (td) { 96 // get the associated endpoint 97 ed = xfer->hcd_qh_start[xfer->flags_internal.curr_dma_set]; 98 99 ed->ed_headP = td->td_self; 100 101 // TODO: invalideate cache? 102 103 /* 104 * we need to make sure that the OHCI takes up this remaining 105 * transfer descriptor for processing. 106 */ 107 if (xfer->type == USB_TYPE_BULK) { 108 /* TODO: write register BLF 109 * OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF); 110 */ 111 } 112 113 if (xfer->type == USB_TYPE_CTRL) { 114 /* TODO: write register CLF 115 * OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); 116 */ 117 } 118 } 119} 120 121/** 122 * \brief this function checks if a USB transfer is already finished or not 123 * 124 * \param xfer the usb transfer to check for completition 125 * 126 * \return 0 if the usb transfer is not finished 127 * else if the usb transfer is finished 128 */ 129uint8_t usb_ohci_xfer_is_finished(struct usb_xfer *xfer) 130{ 131 usb_ohci_ed_t *ed; 132 usb_paddr_t ed_headP; 133 usb_paddr_t ed_tailP; 134 135 // getting the endpoint from the queue head list 136 ed = xfer->hcd_qh_start[xfer->flags_internal.curr_dma_set]; 137 138 /* TODO: invalidate cache ? */ 139 140 // get the transfer descriptor pointers 141 ed_headP = ed->ed_headP; 142 ed_tailP = ed->ed_tailP; 143 144 /* 145 * if the endpoint is halted or there are no transfer descriptors 146 * then there is no activitiy 147 */ 148 if (USB_OHCI_EP_HALTED(ed) || !USB_OHCI_EP_HAS_TD(ed_headP, ed_tailP)) { 149 if (xfer->type == USB_TYPE_ISOC) { 150 // isochronus endponts have to be treated differently; 151 usb_ohci_xfer_done_isoc(xfer); 152 153 // transfer completed 154 return 1; 155 } 156 157 if (xfer->flags_internal.short_frames_ok) { 158 usb_ohci_xfer_short_frames(xfer); 159 160 if (xfer->hcd_td_cache) { 161 return 0; 162 } 163 } 164 165 // handle the data toggle flag 166 if (USB_OHCI_EP_CARRY(ed)) { 167 xfer->endpoint->data_toggle = 1; 168 } else { 169 xfer->endpoint->data_toggle = 0; 170 } 171 172 // handle the completition of the xfer 173 usb_ohci_xfer_done(xfer); 174 175 // transfers completed 176 return 1; 177 } 178 179 // transfer is not completed yet 180 return 0; 181} 182 183/** 184 * \brief This function updates the frame_lengths of the usb transfer 185 * 186 * \param xfer the current USB transfer 187 * 188 * \return USB_ERR_OK on success 189 * USB_ERR_IO 190 * USB_ERR_STALLED 191 */ 192static usb_error_t usb_ohci_xfer_update_frame_lengths(struct usb_xfer *xfer) 193{ 194 usb_ohci_td_t *td; 195 usb_ohci_td_t *td_alt_next; 196 uint32_t temp; 197 usb_paddr_t phy_start; 198 usb_paddr_t phy_end; 199 usb_ohci_td_ctrl_t td_flags; 200 201 uint16_t cc; 202 203 td = xfer->hcd_td_cache; 204 td_alt_next = td->alt_next; 205 206 usb_ohci_td_ctrl_t td_flags_zero = {0,0,0,0,0,0,0}; 207 208 td_flags = td_flags_zero; 209 210 if (xfer->actual_frames != xfer->num_frames) { 211 if (xfer->actual_frames < xfer->max_frame_count) { 212 xfer->frame_lengths[xfer->actual_frames] = 0; 213 } else { 214 // TODO: error handling if actual frame is bigger than max frames 215 assert(!"Frame overflow"); 216 } 217 } 218 219 while (1) { 220 phy_start = td->td_current_buffer; 221 td_flags = td->td_control; 222 cc = td_flags.condition_code; 223 224 if (phy_start) { 225 /* 226 * the current buffer pointer is non zero, this means we 227 * have some data in the buffer, but buffer is not full. 228 * i.e. we have to deal with short transfers 229 */ 230 phy_end = td->td_buffer_end; 231 232 /* 233 * calculate the remaining bytes in the buffer. 234 * Basically end-start + 1 235 */ 236 temp = (USB_OHCI_PAGE(phy_start ^ phy_end) ? 237 (USB_OHCI_PAGE_SIZE + 1) : 0x0001); 238 temp += USB_OHCI_PAGE_OFFSET(phy_end); 239 temp -= USB_OHCI_PAGE_OFFSET(phy_start); 240 241 /* 242 * we may have more data in the buffer left as the transfer 243 * size indicates. That case we stall the transfer. 244 */ 245 if (temp > td->len) { 246 cc = USB_OHCI_STATUS_STALL; 247 } else if (xfer->actual_frames != xfer->num_frames) { 248 /* 249 * set the frame_length of the actual frame 250 */ 251 xfer->frame_lengths[xfer->actual_frames] += td->len - temp; 252 } 253 } else { 254 /* 255 * the transfer was complete one frame before, so we 256 * set the frame length of the actual frame to be the 257 * total transfer length 258 */ 259 if (xfer->actual_frames != xfer->num_frames) { 260 xfer->frame_lengths[xfer->actual_frames] += td->len; 261 } 262 } 263 264 /* 265 * if this TD was the last of USB the transfer, we are done and 266 * can go out of the loop (tranfer finished). 267 */ 268 if (((void *) td) == xfer->hcd_td_last) { 269 td = NULL; 270 break; 271 } 272 273 /* 274 * if we have a condition flag other than USB_OHCI_STATUS_OK then 275 * we treat this as completed and go out of the loop. 276 * (transfer finished). 277 */ 278 if (cc) { 279 td = NULL; 280 break; 281 } 282 283 /* 284 * we encountered a short transfer, we have to check now if 285 * short transfers are acceptable or not by checking the 286 * short_frames_ok flag. If this is the case, we follow the 287 * alternative next pointer to the TD filling up the remainder of 288 * this frame. If short frames are not acceptable this means 289 * we have reached the end of the transfer 290 */ 291 if (phy_start) { 292 if (xfer->flags_internal.short_frames_ok) { 293 td = td->alt_next; 294 } else { 295 td = NULL; 296 } 297 break; 298 } 299 300 // take the next TD in the list 301 td = td->obj_next; 302 303 /* 304 * we have a new alternative next pointer this belongs 305 * to another transfer thus this transfer is complete 306 */ 307 if (td->alt_next != td_alt_next) { 308 break; 309 } 310 } 311 312 /* update transfer cache */ 313 314 xfer->hcd_td_cache = td; 315 316 return ((cc == USB_OHCI_STATUS_OK) ? USB_ERR_OK : 317 (cc == USB_OHCI_STATUS_STALL) ? USB_ERR_STALLED : USB_ERR_IOERROR); 318} 319 320/** 321 * \brief this function handles the completion of a transfer 322 * 323 * \param xfer the usb transfer to handle completion 324 */ 325void usb_ohci_xfer_done(struct usb_xfer *xfer) 326{ 327 usb_error_t err = USB_ERR_OK; 328 329 /* 330 * go over the td list and handle the competition 331 */ 332 xfer->hcd_td_cache = xfer->hcd_td_first; 333 334 /* 335 * check if it is a control transfer. If this is the case 336 * we may need to do some extra work, because control headers 337 * could be requested 338 */ 339 if (xfer->flags_internal.ctrl_xfer) { 340 if (xfer->flags_internal.ctrl_header) { 341 err = usb_ohci_xfer_update_frame_lengths(xfer); 342 } 343 xfer->actual_frames = 1; 344 345 if (xfer->hcd_td_cache == NULL) { 346 usb_ohci_xfer_remove(xfer, err); 347 return; 348 } 349 } 350 351 /* 352 * process the remaining frames till all is complete 353 */ 354 while (xfer->actual_frames < xfer->num_frames) { 355 err = usb_ohci_xfer_update_frame_lengths(xfer); 356 xfer->actual_frames++; 357 358 if (xfer->hcd_td_cache == NULL) { 359 usb_ohci_xfer_remove(xfer, err); 360 return; 361 } 362 } 363 364 /* 365 * check if there is a control transfer active at the moment 366 */ 367 if (xfer->flags_internal.ctrl_xfer && !xfer->flags_internal.ctrl_active) { 368 err = usb_ohci_xfer_update_frame_lengths(xfer); 369 } 370 371 usb_ohci_xfer_remove(xfer, err); 372 373} 374 375/** 376 * \brief 377 * 378 * \param xfer the usb transfer to check for completion 379 * 380 * \return 0 if the usb transfer is not finished 381 * else if the usb transfer is finished 382 */ 383void usb_ohci_xfer_done_isoc(struct usb_xfer *xfer) 384{ 385 assert(!"NYI: need to check isochronus transfer competition"); 386} 387 388/** 389 * \brief This function is called by the specific pipe functions when a 390 * usb transfer is finished. The transfer descriptors are removed 391 * from the endpoint lists. 392 * 393 * \param xfer the usb transfer request that is finished 394 * \param error status code of the finished transfer request 395 */ 396void usb_ohci_xfer_remove(struct usb_xfer *xfer, usb_error_t error) 397{ 398 usb_ohci_ed_t *ed; 399 400 // get the host controller 401 usb_ohci_hc_t *hc = (usb_ohci_hc_t *) xfer->host_controller->hc_control; 402 403 // get the endpoint associated with the usb transfer 404 ed = xfer->hcd_qh_start[xfer->flags_internal.curr_dma_set]; 405 406 // TODO: invalidate page cache of endpoint 407 408 switch (xfer->type) { 409 case USB_TYPE_ISOC: 410 usb_ohci_remove_qh(ed, hc->qh_isoc_last); 411 break; 412 case USB_TYPE_INTR: 413 usb_ohci_remove_qh(ed, hc->qh_intr_last[xfer->intr_qh_pos]); 414 break; 415 case USB_TYPE_CTRL: 416 usb_ohci_remove_qh(ed, hc->qh_ctrl_last); 417 break; 418 case USB_TYPE_BULK: 419 usb_ohci_remove_qh(ed, hc->qh_bulk_last); 420 break; 421 default: 422 assert(!"Invalid Transfer Type"); 423 break; 424 } 425 426 // set the transfer descriptor pointers to null 427 xfer->hcd_td_first = NULL; 428 xfer->hcd_td_last = NULL; 429 430 /* 431 * remove from interrupt queue and enqueue to done queue 432 */ 433 usb_xfer_done(xfer, error); 434} 435 436/* 437 * \brief enqueues the transfer on the controller's interrupt queue to 438 * handle the completed transfers 439 * 440 * \param xfer the transfer to enqueue 441 */ 442void usb_ohci_xfer_enqueue(struct usb_xfer *xfer) 443{ 444 /* check for early completion */ 445 if (usb_ohci_xfer_is_finished(xfer)) { 446 return; 447 } 448 /* put transfer on interrupt queue */ 449 usb_xfer_enqueue(&xfer->host_controller->intr_queue, xfer); 450 451 /* start timeout, if any */ 452 /* TODO: handle time out 453 if (xfer->timeout != 0) { 454 usbd_transfer_timeout_ms(xfer, &ohci_timeout, xfer->timeout); 455 }*/ 456} 457 458struct usb_ohci_setup_td { 459 usb_ohci_td_t *td; 460 usb_ohci_td_t *td_next; 461 uint32_t average; 462 usb_ohci_td_ctrl_t td_flags; 463 uint32_t len; 464 uint16_t max_frame_size; 465 uint8_t shortpkt; 466 uint8_t setup_alt_next; 467 uint8_t last_frame; 468}; 469 470/** 471 * \brief this function is used to setup the transfer descriptors 472 * and allocating buffers for the transfers 473 * 474 * \param temp setup information for the transfer descriptors 475 */ 476static void usb_ohci_xfer_setup_td(struct usb_ohci_setup_td *temp) 477{ 478 usb_ohci_td_t *td; 479 usb_ohci_td_t *td_next; 480 usb_ohci_td_t *td_alt_next = NULL; 481 482 uint32_t average = 0; 483 uint8_t old_shortpkt = temp->shortpkt; 484 uint32_t old_len = temp->len; 485 486 /* 487 * this is used to precompute the length of the transfer 488 */ 489 uint8_t precompute = 1; 490 uint8_t restart = 1; 491 492 /* 493 * we are using software to detect short packets thus we allow 494 * buffer rounding i.e. the buffer does not have to be filled 495 * completely 496 */ 497 if (temp->td_flags.direction_pid == USB_OHCI_PID_IN) { 498 temp->td_flags.rounding = 1; 499 } else { 500 temp->td_flags.rounding = 0; 501 } 502 503 td = temp->td; 504 td_next = temp->td_next; 505 506 while (restart) { 507 508 while (1) { 509 if (temp->len == 0) { 510 /* 511 * handling of zero length packets. these packets are sent last 512 * thus we stop processing if we see the short packet flag 513 */ 514 if (temp->shortpkt) { 515 break; 516 } 517 518 temp->shortpkt = 1; 519 average = 0; 520 521 } else { 522 average = temp->average; 523 524 /* 525 * check if the length of the transfer is smaller than the 526 * average i.e. if we have a short packet not using the whole 527 * USB frame 528 */ 529 if (temp->len < average) { 530 if (temp->len % temp->max_frame_size) { 531 temp->shortpkt = 1; 532 } 533 average = temp->len; 534 } 535 } 536 537 if (td_next == NULL) { 538 /* 539 * TODO: PANIC: not enough transport descriptors 540 */ 541 assert(!"ran out of transfer descriptors!"); 542 } 543 544 /* 545 * get the next td to process 546 */ 547 td = td_next; 548 td_next = td->obj_next; 549 550 /* 551 * check if we are pre-computing the lengths. 552 * update the remaining length and continue with the loop 553 */ 554 if (precompute) { 555 temp->len -= average; 556 557 continue; 558 } 559 560 /* fill in the current TD with the data */ 561 td->td_control = temp->td_flags; 562 563 /* the next td uses the toggle carry */ 564 temp->td_flags.data_toggle = 1; 565 566 /* 567 * setup the fields in the transfer descriptor depending on the 568 * packet size, zero length packets do not need a buffer 569 * buffer but other wise we need 570 */ 571 if (average == 0) { 572 td->td_current_buffer = 0; 573 td->td_buffer_end = 0; 574 td->len = 0; 575 } else { 576 // buffer size is bigger than the td internal buffer 577 if (average > USB_OHCI_TD_BUFFER_SIZE) { 578 /* 579 * TODO: allocate a bigger buffer here 580 */ 581 assert(!"NYI: handling of biger buffers "); 582 } else { 583 td->td_current_buffer = td->td_self 584 + USB_OHCI_TD_BUFFER_OFFSET; 585 td->td_buffer_end = td->td_current_buffer + average; 586 } 587 588 /* set the length of this transfer descriptor */ 589 td->len = average; 590 591 /* update the remaining length of the transfer */ 592 temp->len -= average; 593 } 594 595 if ((td_next == td_alt_next) && temp->setup_alt_next) { 596 /* 597 * we have to setup the alternative transfer descriptors 598 * because we need to receive these frames one by one 599 * 600 * - delay interrupts must be 1 601 * - last td in the list 602 */ 603 td->td_control.delay_interrupt = 1; 604 td->td_nextTD = 0; 605 606 } else { 607 /* 608 * do the linking of the transfer descriptors using 609 * their physical addresses if there is another 610 * td in the list 611 */ 612 if (td_next) { 613 td->td_nextTD = td_next->td_self; 614 } 615 } 616 617 td->alt_next = td_alt_next; 618 } 619 620 if (precompute) { 621 precompute = 0; 622 623 /* the last frame does not have an alternative next td */ 624 if (temp->last_frame) { 625 td_alt_next = NULL; 626 } else { 627 td_alt_next = td_next; 628 } 629 630 /* 631 * we were precomputing so we need to restore the values 632 */ 633 temp->shortpkt = old_shortpkt; 634 temp->len = old_len; 635 } else { 636 restart = 0; 637 } 638 639 } 640 641 temp->td = td; 642 temp->td_next = td_next; 643} 644 645/** 646 * \brief this function sets up the standard chains for the transfer 647 * descriptors for an USB transfer. 648 * 649 * \param xfer the usb transfer to setup the transfer descriptors 650 * \param ed_last the last endpoint descriptor 651 */ 652void usb_ohci_xfer_start(struct usb_xfer *xfer, usb_ohci_ed_t **ed_last) 653{ 654 struct usb_ohci_setup_td temp; 655 struct usb_hcdi_pipe_fn *pipe_fn; 656 657 usb_ohci_ed_t *ed; 658 usb_ohci_td_t *td; 659 usb_ohci_ed_ctrl_t ed_flags; 660 uint32_t x; 661 662 /* 663 * getting the size information out of the xfer 664 */ 665 temp.average = xfer->max_hc_frame_size; 666 temp.max_frame_size = xfer->max_frame_size; 667 668 /* toggle the next DMA set bit and get the next set */ 669 xfer->flags_internal.curr_dma_set ^= 1; 670 td = xfer->hcd_td_start[xfer->flags_internal.curr_dma_set]; 671 672 /* update the beginning of the td list */ 673 xfer->hcd_td_first = td; 674 xfer->hcd_td_cache = td; 675 676 temp.td = NULL; 677 temp.td_next = td; 678 temp.last_frame = 0; 679 temp.setup_alt_next = xfer->flags_internal.short_frames_ok; 680 681 pipe_fn = xfer->endpoint->pipe_fn; 682 683 /* 684 * check if we have to prepend a setup message, this is the case 685 * if we are handling with control transfers and a header is requested 686 */ 687 if (xfer->flags_internal.ctrl_xfer) { 688 if (xfer->flags_internal.ctrl_header) { 689 temp.td_flags.data_toggle = 0; 690 temp.td_flags.condition_code = 0; 691 temp.td_flags.direction_pid = USB_OHCI_PID_SETUP; 692 temp.td_flags.delay_interrupt = USB_OHCI_TD_DISABLE_IRQ; 693 694 temp.len = xfer->frame_lengths[0]; 695 temp.shortpkt = temp.len ? 1 : 0; 696 697 /* check if this is the last frame, i.e. there is no data stage */ 698 if (xfer->num_frames == 1) { 699 if (xfer->flags_internal.ctrl_active) { 700 temp.last_frame = 1; 701 temp.setup_alt_next = 0; 702 } 703 } 704 usb_ohci_xfer_setup_td(&temp); 705 706 xfer->endpoint->data_toggle = 1; 707 } 708 x = 1; 709 } else { 710 x = 0; 711 } 712 713 temp.td_flags.condition_code = 0; 714 temp.td_flags.delay_interrupt = USB_OHCI_TD_DISABLE_IRQ; 715 716 if (xfer->endpoint->data_toggle) { 717 temp.td_flags.data_toggle = 1; 718 } else { 719 temp.td_flags.data_toggle = 0; 720 } 721 722 if (xfer->ed_direction == USB_OHCI_ED_DIRECTION_IN) { 723 temp.td_flags.direction_pid = USB_OHCI_PID_IN; 724 } else { 725 temp.td_flags.direction_pid = USB_OHCI_PID_OUT; 726 } 727 728 while (x != xfer->num_frames) { 729 730 /* 731 * Handling DATA0 and DATA1 packets 732 */ 733 temp.len = xfer->frame_lengths[x++]; 734 735 if (x == xfer->num_frames) { 736 if (xfer->flags_internal.ctrl_xfer) { 737 if (xfer->flags_internal.ctrl_active) { 738 /* no STATUS stage, just DATA */ 739 temp.last_frame = 1; 740 temp.setup_alt_next = 0; 741 } 742 } else { 743 temp.last_frame = 1; 744 temp.setup_alt_next = 0; 745 } 746 747 } 748 749 if (temp.len == 0) { 750 /* this is a short packet but we want to send an USB packet */ 751 temp.shortpkt = 0; 752 } else { 753 temp.shortpkt = (xfer->flags.short_xfer_forced) ? 0 : 1; 754 } 755 756 usb_ohci_xfer_setup_td(&temp); 757 } 758 759 /* 760 * control transfer have a status stage, check if we have to append 761 * such a status stage 762 */ 763 if (xfer->flags_internal.ctrl_xfer && !xfer->flags_internal.ctrl_active) { 764 memset(&temp.td_flags, 0, sizeof(usb_ohci_td_ctrl_t)); 765 temp.td_flags.condition_code = 0; 766 temp.td_flags.data_toggle = 1; 767 temp.td_flags.delay_interrupt = 1; 768 if (xfer->ed_direction == USB_OHCI_ED_DIRECTION_IN) { 769 temp.td_flags.direction_pid = USB_OHCI_ED_DIRECTION_OUT; 770 } else { 771 temp.td_flags.direction_pid = USB_OHCI_ED_DIRECTION_OUT; 772 } 773 774 temp.len = 0; 775 temp.shortpkt = 0; 776 temp.last_frame = 1; 777 temp.setup_alt_next = 0; 778 779 usb_ohci_xfer_setup_td(&temp); 780 } 781 782 td = temp.td; 783 784 /* ensure that the last TD is terminating */ 785 td->td_nextTD = 0; 786 td->td_control.delay_interrupt = 1; 787 788 xfer->hcd_td_last = td; 789 790 ed = xfer->hcd_qh_start[xfer->flags_internal.curr_dma_set]; 791 792 ed_flags.function_address = xfer->device_address; 793 ed_flags.endpoint_number = xfer->endpoint_number; 794 ed_flags.max_packet_size = xfer->max_frame_size; 795 ed_flags.td_format = USB_OHCI_ED_FORMAT_GENERAL; 796 ed_flags.direction = USB_OHCI_ED_DIRECTION_FROM_TD; 797 798 if (xfer->device->speed == USB_SPEED_LOW) { 799 ed_flags.speed = USB_OHCI_ED_LOWSPEED; 800 } 801 802 ed->ed_control = ed_flags; 803 804 td = xfer->hcd_td_first; 805 806 ed->ed_headP = td->td_self; 807 808 /* TODO: self suspended */ 809 if (xfer->device->flags.self_suspended == 0) { 810 811 } 812} 813 814/** 815 * \brief this function sets up a new usb transfer on the host controller 816 * 817 * \param param the parameters to setup the usb transfer 818 * 819 */ 820void usb_ohci_xfer_setup(struct usb_xfer_setup_params *param) 821{ 822 struct usb_xfer *xfer = param->curr_xfer; 823 void *last_obj; 824 /* 825 * variables to track how many descriptors we have to allocate 826 */ 827 uint32_t num_td = 0; 828 uint32_t num_itd = 0; 829 uint32_t num_qh = 0; 830 uint32_t n = 0; 831 832 /* 833 * set the OHCI specific values 834 */ 835 param->hc_max_packet_count = 1; 836 param->hc_max_packet_size = 0x500; 837 param->hc_max_frame_size = USB_OHCI_PAGE_SIZE; 838 839 /* TODO: set BDMA enabled? */ 840 usb_xfer_setup_struct(param); 841 842 switch (param->type) { 843 case USB_TYPE_ISOC: 844 num_itd = ((xfer->max_data_length / USB_OHCI_PAGE_SIZE) 845 + ((xfer->num_frames + USB_OHCI_ISOCHRONUS_TD_OFFSETS - 1) 846 / USB_OHCI_ISOCHRONUS_TD_OFFSETS) + 1); 847 break; 848 case USB_TYPE_INTR: 849 num_td = ((2 * xfer->num_frames) 850 + xfer->max_data_length / xfer->max_hc_frame_size); 851 num_qh = 1; 852 break; 853 case USB_TYPE_CTRL: 854 num_td = ((2 * xfer->num_frames) + 1 /* STATUS stage*/ 855 + (xfer->max_data_length / xfer->max_hc_frame_size)); 856 num_qh = 1; 857 break; 858 case USB_TYPE_BULK: 859 num_qh = 1; 860 num_td = ((2 * xfer->num_frames) 861 + (xfer->max_data_length / xfer->max_hc_frame_size)); 862 break; 863 } 864 uint8_t alloc_dma_set; 865 do { 866 alloc_dma_set = xfer->flags_internal.curr_dma_set; 867 868 /* 869 * check if setting up the usb transfer succeeded 870 */ 871 if (param->err) { 872 return; 873 } 874 875 last_obj = NULL; 876 877 /* 878 * allocate memory for the transfer descriptors 879 */ 880 usb_ohci_td_t *td; 881 for (n = 0; n < num_td; n++) { 882 td = usb_ohci_td_alloc(); 883 if (td == NULL) { 884 param->err = USB_ERR_NOMEM; 885 // free the allocated td's 886 for (td = last_obj; td != NULL; td = td->obj_next) { 887 usb_ohci_td_free(td); 888 } 889 return; 890 } 891 892 td->obj_next = last_obj; 893 last_obj = td; 894 } 895 896 /* 897 * allocate memory for the isochronus transfer descriptors 898 */ 899 usb_ohci_itd_t *itd; 900 for (n = 0; n < num_itd; n++) { 901 itd = usb_ohci_itd_alloc(); 902 if (itd == NULL) { 903 param->err = USB_ERR_NOMEM; 904 // free the allocated iTDs 905 for (uint32_t i = 0; i < n; i++) { 906 itd = last_obj; 907 last_obj = itd->obj_next; 908 usb_ohci_itd_free(itd); 909 } 910 911 // free the allocated TDs 912 for (n = 0; n < num_td; n++) { 913 td = last_obj; 914 last_obj = td->obj_next; 915 usb_ohci_td_free(td); 916 } 917 return; 918 } 919 920 itd->obj_next = last_obj; 921 last_obj = itd; 922 } 923 xfer->hcd_td_start[xfer->flags_internal.curr_dma_set] = last_obj; 924 925 /* 926 * allocate memory for the queue heads 927 */ 928 usb_ohci_ed_t *ed; 929 last_obj = NULL; 930 for (n = 0; n < num_qh; n++) { 931 ed = usb_ohci_ed_alloc(); 932 if (ed == NULL) { 933 for (ed = last_obj; ed != NULL; ed = ed->obj_next) { 934 usb_ohci_ed_free(ed); 935 } 936 last_obj = 937 xfer->hcd_td_start[xfer->flags_internal.curr_dma_set]; 938 for (n = 0; n < num_itd; n++) { 939 itd = last_obj; 940 last_obj = itd->obj_next; 941 usb_ohci_itd_free(itd); 942 } 943 for (n = 0; n < num_td; n++) { 944 td = last_obj; 945 last_obj = td->obj_next; 946 usb_ohci_td_free(td); 947 } 948 } 949 last_obj = ed; 950 } 951 xfer->hcd_qh_start[xfer->flags_internal.curr_dma_set] = last_obj; 952 953 if (!xfer->flags_internal.curr_dma_set) { 954 xfer->flags_internal.curr_dma_set = 1; 955 } 956 } while (!alloc_dma_set); 957} 958 959/** 960 * \brief this function is a stub to unsetup a usb transfer 961 * 962 */ 963void usb_ohci_xfer_unsetup(struct usb_xfer *xfer) 964{ 965 return; 966} 967 968