hcd-uhci.c (50dcc0f85da5d2a74760af4b67c040c4d0c8b939) hcd-uhci.c (60e1b2a6ddf1fd9cc93ad81d8ba7d8ac4369cc78)
1/*
2 * USB UHCI controller emulation
3 *
4 * Copyright (c) 2005 Fabrice Bellard
5 *
6 * Copyright (c) 2008 Max Krasnyansky
7 * Magor rewrite of the UHCI data structures parser and frame processor
8 * Support for fully async operation and multiple outstanding transactions

--- 63 unchanged lines hidden (view full) ---

72#define UHCI_PORT_WRITE_CLEAR (UHCI_PORT_CSC | UHCI_PORT_ENC)
73
74#define FRAME_TIMER_FREQ 1000
75
76#define FRAME_MAX_LOOPS 256
77
78#define NB_PORTS 2
79
1/*
2 * USB UHCI controller emulation
3 *
4 * Copyright (c) 2005 Fabrice Bellard
5 *
6 * Copyright (c) 2008 Max Krasnyansky
7 * Magor rewrite of the UHCI data structures parser and frame processor
8 * Support for fully async operation and multiple outstanding transactions

--- 63 unchanged lines hidden (view full) ---

72#define UHCI_PORT_WRITE_CLEAR (UHCI_PORT_CSC | UHCI_PORT_ENC)
73
74#define FRAME_TIMER_FREQ 1000
75
76#define FRAME_MAX_LOOPS 256
77
78#define NB_PORTS 2
79
80enum {
81 TD_RESULT_STOP_FRAME = -1,
82 TD_RESULT_COMPLETE = 0,
83 TD_RESULT_NEXT_QH = 1,
84 TD_RESULT_ASYNC = 2,
85};
86
80typedef struct UHCIState UHCIState;
81typedef struct UHCIAsync UHCIAsync;
82typedef struct UHCIQueue UHCIQueue;
83
84/*
85 * Pending async transaction.
86 * 'packet' must be the first field because completion
87 * handler does "(UHCIAsync *) pkt" cast.

--- 628 unchanged lines hidden (view full) ---

716 goto out;
717 }
718
719 if ((td->ctrl & TD_CTRL_SPD) && len < max_len) {
720 *int_mask |= 0x02;
721 /* short packet: do not update QH */
722 trace_usb_uhci_packet_complete_shortxfer(async->queue->token,
723 async->td);
87typedef struct UHCIState UHCIState;
88typedef struct UHCIAsync UHCIAsync;
89typedef struct UHCIQueue UHCIQueue;
90
91/*
92 * Pending async transaction.
93 * 'packet' must be the first field because completion
94 * handler does "(UHCIAsync *) pkt" cast.

--- 628 unchanged lines hidden (view full) ---

723 goto out;
724 }
725
726 if ((td->ctrl & TD_CTRL_SPD) && len < max_len) {
727 *int_mask |= 0x02;
728 /* short packet: do not update QH */
729 trace_usb_uhci_packet_complete_shortxfer(async->queue->token,
730 async->td);
724 return 1;
731 return TD_RESULT_NEXT_QH;
725 }
726 }
727
728 /* success */
729 trace_usb_uhci_packet_complete_success(async->queue->token, async->td);
732 }
733 }
734
735 /* success */
736 trace_usb_uhci_packet_complete_success(async->queue->token, async->td);
730 return 0;
737 return TD_RESULT_COMPLETE;
731
732out:
733 switch(ret) {
734 case USB_RET_STALL:
735 td->ctrl |= TD_CTRL_STALL;
736 td->ctrl &= ~TD_CTRL_ACTIVE;
737 s->status |= UHCI_STS_USBERR;
738 if (td->ctrl & TD_CTRL_IOC) {
739 *int_mask |= 0x01;
740 }
741 uhci_update_irq(s);
742 trace_usb_uhci_packet_complete_stall(async->queue->token, async->td);
738
739out:
740 switch(ret) {
741 case USB_RET_STALL:
742 td->ctrl |= TD_CTRL_STALL;
743 td->ctrl &= ~TD_CTRL_ACTIVE;
744 s->status |= UHCI_STS_USBERR;
745 if (td->ctrl & TD_CTRL_IOC) {
746 *int_mask |= 0x01;
747 }
748 uhci_update_irq(s);
749 trace_usb_uhci_packet_complete_stall(async->queue->token, async->td);
743 return 1;
750 return TD_RESULT_NEXT_QH;
744
745 case USB_RET_BABBLE:
746 td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
747 td->ctrl &= ~TD_CTRL_ACTIVE;
748 s->status |= UHCI_STS_USBERR;
749 if (td->ctrl & TD_CTRL_IOC) {
750 *int_mask |= 0x01;
751 }
752 uhci_update_irq(s);
753 /* frame interrupted */
754 trace_usb_uhci_packet_complete_babble(async->queue->token, async->td);
751
752 case USB_RET_BABBLE:
753 td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
754 td->ctrl &= ~TD_CTRL_ACTIVE;
755 s->status |= UHCI_STS_USBERR;
756 if (td->ctrl & TD_CTRL_IOC) {
757 *int_mask |= 0x01;
758 }
759 uhci_update_irq(s);
760 /* frame interrupted */
761 trace_usb_uhci_packet_complete_babble(async->queue->token, async->td);
755 return -1;
762 return TD_RESULT_STOP_FRAME;
756
757 case USB_RET_NAK:
758 td->ctrl |= TD_CTRL_NAK;
759 if (pid == USB_TOKEN_SETUP)
760 break;
763
764 case USB_RET_NAK:
765 td->ctrl |= TD_CTRL_NAK;
766 if (pid == USB_TOKEN_SETUP)
767 break;
761 return 1;
768 return TD_RESULT_NEXT_QH;
762
763 case USB_RET_IOERROR:
764 case USB_RET_NODEV:
765 default:
766 break;
767 }
768
769 /* Retry the TD if error count is not zero */

--- 9 unchanged lines hidden (view full) ---

779 *int_mask |= 0x01;
780 uhci_update_irq(s);
781 trace_usb_uhci_packet_complete_error(async->queue->token,
782 async->td);
783 }
784 }
785 td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) |
786 (err << TD_CTRL_ERROR_SHIFT);
769
770 case USB_RET_IOERROR:
771 case USB_RET_NODEV:
772 default:
773 break;
774 }
775
776 /* Retry the TD if error count is not zero */

--- 9 unchanged lines hidden (view full) ---

786 *int_mask |= 0x01;
787 uhci_update_irq(s);
788 trace_usb_uhci_packet_complete_error(async->queue->token,
789 async->td);
790 }
791 }
792 td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) |
793 (err << TD_CTRL_ERROR_SHIFT);
787 return 1;
794 return TD_RESULT_NEXT_QH;
788}
789
790static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *int_mask)
791{
792 UHCIAsync *async;
793 int len = 0, max_len;
794 uint8_t pid;
795 USBDevice *dev;
796 USBEndpoint *ep;
797
798 /* Is active ? */
799 if (!(td->ctrl & TD_CTRL_ACTIVE))
795}
796
797static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *int_mask)
798{
799 UHCIAsync *async;
800 int len = 0, max_len;
801 uint8_t pid;
802 USBDevice *dev;
803 USBEndpoint *ep;
804
805 /* Is active ? */
806 if (!(td->ctrl & TD_CTRL_ACTIVE))
800 return 1;
807 return TD_RESULT_NEXT_QH;
801
802 async = uhci_async_find_td(s, addr, td);
803 if (async) {
804 /* Already submitted */
805 async->queue->valid = 32;
806
807 if (!async->done)
808
809 async = uhci_async_find_td(s, addr, td);
810 if (async) {
811 /* Already submitted */
812 async->queue->valid = 32;
813
814 if (!async->done)
808 return 1;
815 return TD_RESULT_NEXT_QH;
809
810 uhci_async_unlink(async);
811 goto done;
812 }
813
814 /* Allocate new packet */
815 async = uhci_async_alloc(uhci_queue_get(s, td), addr);
816 if (!async)
816
817 uhci_async_unlink(async);
818 goto done;
819 }
820
821 /* Allocate new packet */
822 async = uhci_async_alloc(uhci_queue_get(s, td), addr);
823 if (!async)
817 return 1;
824 return TD_RESULT_NEXT_QH;
818
819 /* valid needs to be large enough to handle 10 frame delay
820 * for initial isochronous requests
821 */
822 async->queue->valid = 32;
823 async->isoc = td->ctrl & TD_CTRL_IOS;
824
825 max_len = ((td->token >> 21) + 1) & 0x7ff;

--- 17 unchanged lines hidden (view full) ---

843 len = usb_handle_packet(dev, &async->packet);
844 break;
845
846 default:
847 /* invalid pid : frame interrupted */
848 uhci_async_free(async);
849 s->status |= UHCI_STS_HCPERR;
850 uhci_update_irq(s);
825
826 /* valid needs to be large enough to handle 10 frame delay
827 * for initial isochronous requests
828 */
829 async->queue->valid = 32;
830 async->isoc = td->ctrl & TD_CTRL_IOS;
831
832 max_len = ((td->token >> 21) + 1) & 0x7ff;

--- 17 unchanged lines hidden (view full) ---

850 len = usb_handle_packet(dev, &async->packet);
851 break;
852
853 default:
854 /* invalid pid : frame interrupted */
855 uhci_async_free(async);
856 s->status |= UHCI_STS_HCPERR;
857 uhci_update_irq(s);
851 return -1;
858 return TD_RESULT_STOP_FRAME;
852 }
853
854 if (len == USB_RET_ASYNC) {
855 uhci_async_link(async);
859 }
860
861 if (len == USB_RET_ASYNC) {
862 uhci_async_link(async);
856 return 2;
863 return TD_RESULT_ASYNC;
857 }
858
859 async->packet.result = len;
860
861done:
862 len = uhci_complete_td(s, td, async, int_mask);
863 usb_packet_unmap(&async->packet);
864 uhci_async_free(async);

--- 89 unchanged lines hidden (view full) ---

954 if (!(ptd.ctrl & TD_CTRL_ACTIVE)) {
955 break;
956 }
957 if (uhci_queue_token(&ptd) != token) {
958 break;
959 }
960 trace_usb_uhci_td_queue(plink & ~0xf, ptd.ctrl, ptd.token);
961 ret = uhci_handle_td(s, plink, &ptd, &int_mask);
864 }
865
866 async->packet.result = len;
867
868done:
869 len = uhci_complete_td(s, td, async, int_mask);
870 usb_packet_unmap(&async->packet);
871 uhci_async_free(async);

--- 89 unchanged lines hidden (view full) ---

961 if (!(ptd.ctrl & TD_CTRL_ACTIVE)) {
962 break;
963 }
964 if (uhci_queue_token(&ptd) != token) {
965 break;
966 }
967 trace_usb_uhci_td_queue(plink & ~0xf, ptd.ctrl, ptd.token);
968 ret = uhci_handle_td(s, plink, &ptd, &int_mask);
962 assert(ret == 2); /* got USB_RET_ASYNC */
969 assert(ret == TD_RESULT_ASYNC);
963 assert(int_mask == 0);
964 plink = ptd.link;
965 }
966}
967
968static void uhci_process_frame(UHCIState *s)
969{
970 uint32_t frame_addr, link, old_td_ctrl, val, int_mask;

--- 71 unchanged lines hidden (view full) ---

1042 ret = uhci_handle_td(s, link, &td, &int_mask);
1043 if (old_td_ctrl != td.ctrl) {
1044 /* update the status bits of the TD */
1045 val = cpu_to_le32(td.ctrl);
1046 pci_dma_write(&s->dev, (link & ~0xf) + 4, &val, sizeof(val));
1047 }
1048
1049 switch (ret) {
970 assert(int_mask == 0);
971 plink = ptd.link;
972 }
973}
974
975static void uhci_process_frame(UHCIState *s)
976{
977 uint32_t frame_addr, link, old_td_ctrl, val, int_mask;

--- 71 unchanged lines hidden (view full) ---

1049 ret = uhci_handle_td(s, link, &td, &int_mask);
1050 if (old_td_ctrl != td.ctrl) {
1051 /* update the status bits of the TD */
1052 val = cpu_to_le32(td.ctrl);
1053 pci_dma_write(&s->dev, (link & ~0xf) + 4, &val, sizeof(val));
1054 }
1055
1056 switch (ret) {
1050 case -1: /* interrupted frame */
1057 case TD_RESULT_STOP_FRAME: /* interrupted frame */
1051 goto out;
1052
1058 goto out;
1059
1053 case 1: /* goto next queue */
1060 case TD_RESULT_NEXT_QH:
1054 trace_usb_uhci_td_nextqh(curr_qh & ~0xf, link & ~0xf);
1055 link = curr_qh ? qh.link : td.link;
1056 continue;
1057
1061 trace_usb_uhci_td_nextqh(curr_qh & ~0xf, link & ~0xf);
1062 link = curr_qh ? qh.link : td.link;
1063 continue;
1064
1058 case 2: /* got USB_RET_ASYNC */
1065 case TD_RESULT_ASYNC:
1059 trace_usb_uhci_td_async(curr_qh & ~0xf, link & ~0xf);
1060 if (is_valid(td.link)) {
1061 uhci_fill_queue(s, &td);
1062 }
1063 link = curr_qh ? qh.link : td.link;
1064 continue;
1065
1066 trace_usb_uhci_td_async(curr_qh & ~0xf, link & ~0xf);
1067 if (is_valid(td.link)) {
1068 uhci_fill_queue(s, &td);
1069 }
1070 link = curr_qh ? qh.link : td.link;
1071 continue;
1072
1066 case 0: /* completed TD */
1073 case TD_RESULT_COMPLETE:
1067 trace_usb_uhci_td_complete(curr_qh & ~0xf, link & ~0xf);
1068 link = td.link;
1069 td_count++;
1070 bytes_count += (td.ctrl & 0x7ff) + 1;
1071
1072 if (curr_qh) {
1073 /* update QH element link */
1074 qh.el_link = link;

--- 297 unchanged lines hidden ---
1074 trace_usb_uhci_td_complete(curr_qh & ~0xf, link & ~0xf);
1075 link = td.link;
1076 td_count++;
1077 bytes_count += (td.ctrl & 0x7ff) + 1;
1078
1079 if (curr_qh) {
1080 /* update QH element link */
1081 qh.el_link = link;

--- 297 unchanged lines hidden ---