Revision 60e1b2a6 hw/usb/hcd-uhci.c
b/hw/usb/hcd-uhci.c | ||
---|---|---|
77 | 77 |
|
78 | 78 |
#define NB_PORTS 2 |
79 | 79 |
|
80 |
enum { |
|
81 |
TD_RESULT_STOP_FRAME = -1, |
|
82 |
TD_RESULT_COMPLETE = 0, |
|
83 |
TD_RESULT_NEXT_QH = 1, |
|
84 |
TD_RESULT_ASYNC = 2, |
|
85 |
}; |
|
86 |
|
|
80 | 87 |
typedef struct UHCIState UHCIState; |
81 | 88 |
typedef struct UHCIAsync UHCIAsync; |
82 | 89 |
typedef struct UHCIQueue UHCIQueue; |
... | ... | |
721 | 728 |
/* short packet: do not update QH */ |
722 | 729 |
trace_usb_uhci_packet_complete_shortxfer(async->queue->token, |
723 | 730 |
async->td); |
724 |
return 1;
|
|
731 |
return TD_RESULT_NEXT_QH;
|
|
725 | 732 |
} |
726 | 733 |
} |
727 | 734 |
|
728 | 735 |
/* success */ |
729 | 736 |
trace_usb_uhci_packet_complete_success(async->queue->token, async->td); |
730 |
return 0;
|
|
737 |
return TD_RESULT_COMPLETE;
|
|
731 | 738 |
|
732 | 739 |
out: |
733 | 740 |
switch(ret) { |
... | ... | |
740 | 747 |
} |
741 | 748 |
uhci_update_irq(s); |
742 | 749 |
trace_usb_uhci_packet_complete_stall(async->queue->token, async->td); |
743 |
return 1;
|
|
750 |
return TD_RESULT_NEXT_QH;
|
|
744 | 751 |
|
745 | 752 |
case USB_RET_BABBLE: |
746 | 753 |
td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL; |
... | ... | |
752 | 759 |
uhci_update_irq(s); |
753 | 760 |
/* frame interrupted */ |
754 | 761 |
trace_usb_uhci_packet_complete_babble(async->queue->token, async->td); |
755 |
return -1;
|
|
762 |
return TD_RESULT_STOP_FRAME;
|
|
756 | 763 |
|
757 | 764 |
case USB_RET_NAK: |
758 | 765 |
td->ctrl |= TD_CTRL_NAK; |
759 | 766 |
if (pid == USB_TOKEN_SETUP) |
760 | 767 |
break; |
761 |
return 1;
|
|
768 |
return TD_RESULT_NEXT_QH;
|
|
762 | 769 |
|
763 | 770 |
case USB_RET_IOERROR: |
764 | 771 |
case USB_RET_NODEV: |
... | ... | |
784 | 791 |
} |
785 | 792 |
td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) | |
786 | 793 |
(err << TD_CTRL_ERROR_SHIFT); |
787 |
return 1;
|
|
794 |
return TD_RESULT_NEXT_QH;
|
|
788 | 795 |
} |
789 | 796 |
|
790 | 797 |
static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *int_mask) |
... | ... | |
797 | 804 |
|
798 | 805 |
/* Is active ? */ |
799 | 806 |
if (!(td->ctrl & TD_CTRL_ACTIVE)) |
800 |
return 1;
|
|
807 |
return TD_RESULT_NEXT_QH;
|
|
801 | 808 |
|
802 | 809 |
async = uhci_async_find_td(s, addr, td); |
803 | 810 |
if (async) { |
... | ... | |
805 | 812 |
async->queue->valid = 32; |
806 | 813 |
|
807 | 814 |
if (!async->done) |
808 |
return 1;
|
|
815 |
return TD_RESULT_NEXT_QH;
|
|
809 | 816 |
|
810 | 817 |
uhci_async_unlink(async); |
811 | 818 |
goto done; |
... | ... | |
814 | 821 |
/* Allocate new packet */ |
815 | 822 |
async = uhci_async_alloc(uhci_queue_get(s, td), addr); |
816 | 823 |
if (!async) |
817 |
return 1;
|
|
824 |
return TD_RESULT_NEXT_QH;
|
|
818 | 825 |
|
819 | 826 |
/* valid needs to be large enough to handle 10 frame delay |
820 | 827 |
* for initial isochronous requests |
... | ... | |
848 | 855 |
uhci_async_free(async); |
849 | 856 |
s->status |= UHCI_STS_HCPERR; |
850 | 857 |
uhci_update_irq(s); |
851 |
return -1;
|
|
858 |
return TD_RESULT_STOP_FRAME;
|
|
852 | 859 |
} |
853 | 860 |
|
854 | 861 |
if (len == USB_RET_ASYNC) { |
855 | 862 |
uhci_async_link(async); |
856 |
return 2;
|
|
863 |
return TD_RESULT_ASYNC;
|
|
857 | 864 |
} |
858 | 865 |
|
859 | 866 |
async->packet.result = len; |
... | ... | |
959 | 966 |
} |
960 | 967 |
trace_usb_uhci_td_queue(plink & ~0xf, ptd.ctrl, ptd.token); |
961 | 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 | 970 |
assert(int_mask == 0); |
964 | 971 |
plink = ptd.link; |
965 | 972 |
} |
... | ... | |
1047 | 1054 |
} |
1048 | 1055 |
|
1049 | 1056 |
switch (ret) { |
1050 |
case -1: /* interrupted frame */
|
|
1057 |
case TD_RESULT_STOP_FRAME: /* interrupted frame */
|
|
1051 | 1058 |
goto out; |
1052 | 1059 |
|
1053 |
case 1: /* goto next queue */
|
|
1060 |
case TD_RESULT_NEXT_QH:
|
|
1054 | 1061 |
trace_usb_uhci_td_nextqh(curr_qh & ~0xf, link & ~0xf); |
1055 | 1062 |
link = curr_qh ? qh.link : td.link; |
1056 | 1063 |
continue; |
1057 | 1064 |
|
1058 |
case 2: /* got USB_RET_ASYNC */
|
|
1065 |
case TD_RESULT_ASYNC:
|
|
1059 | 1066 |
trace_usb_uhci_td_async(curr_qh & ~0xf, link & ~0xf); |
1060 | 1067 |
if (is_valid(td.link)) { |
1061 | 1068 |
uhci_fill_queue(s, &td); |
... | ... | |
1063 | 1070 |
link = curr_qh ? qh.link : td.link; |
1064 | 1071 |
continue; |
1065 | 1072 |
|
1066 |
case 0: /* completed TD */
|
|
1073 |
case TD_RESULT_COMPLETE:
|
|
1067 | 1074 |
trace_usb_uhci_td_complete(curr_qh & ~0xf, link & ~0xf); |
1068 | 1075 |
link = td.link; |
1069 | 1076 |
td_count++; |
Also available in: Unified diff