]>
Commit | Line | Data |
---|---|---|
cc900d34 AF |
1 | /* |
2 | * QTest testcase for USB EHCI | |
3 | * | |
4 | * Copyright (c) 2014 SUSE LINUX Products GmbH | |
5 | * | |
6 | * This work is licensed under the terms of the GNU GPL, version 2 or later. | |
7 | * See the COPYING file in the top-level directory. | |
8 | */ | |
9 | ||
e532b2e0 | 10 | #include "qemu/osdep.h" |
cc900d34 | 11 | #include "libqtest.h" |
d81d4106 | 12 | #include "libqos/pci-pc.h" |
d81d4106 GH |
13 | #include "hw/usb/uhci-regs.h" |
14 | #include "hw/usb/ehci-regs.h" | |
b0354ec5 | 15 | #include "libqos/usb.h" |
d81d4106 GH |
16 | |
17 | static QPCIBus *pcibus; | |
18 | static struct qhc uhci1; | |
19 | static struct qhc uhci2; | |
20 | static struct qhc uhci3; | |
21 | static struct qhc ehci1; | |
22 | ||
23 | /* helpers */ | |
24 | ||
d81d4106 GH |
25 | #if 0 |
26 | static void uhci_port_update(struct qhc *hc, int port, | |
27 | uint16_t set, uint16_t clear) | |
cc900d34 | 28 | { |
d81d4106 GH |
29 | void *addr = hc->base + 0x10 + 2 * port; |
30 | uint16_t value; | |
31 | ||
32 | value = qpci_io_readw(hc->dev, addr); | |
33 | value |= set; | |
34 | value &= ~clear; | |
35 | qpci_io_writew(hc->dev, addr, value); | |
36 | } | |
37 | #endif | |
38 | ||
d81d4106 GH |
39 | static void ehci_port_test(struct qhc *hc, int port, uint32_t expect) |
40 | { | |
b4ba67d9 | 41 | uint32_t value = qpci_io_readl(hc->dev, hc->bar, 0x64 + 4 * port); |
d81d4106 GH |
42 | uint16_t mask = ~(PORTSC_CSC | PORTSC_PEDC | PORTSC_OCC); |
43 | ||
44 | #if 0 | |
45 | fprintf(stderr, "%s: %d, have 0x%08x, want 0x%08x\n", | |
46 | __func__, port, value & mask, expect & mask); | |
47 | #endif | |
48 | g_assert((value & mask) == (expect & mask)); | |
49 | } | |
50 | ||
51 | /* tests */ | |
52 | ||
d3510ff9 | 53 | static void test_init(void) |
d81d4106 | 54 | { |
143e6db6 | 55 | pcibus = qpci_new_pc(global_qtest, NULL); |
d81d4106 GH |
56 | g_assert(pcibus != NULL); |
57 | ||
b0354ec5 IM |
58 | qusb_pci_init_one(pcibus, &uhci1, QPCI_DEVFN(0x1d, 0), 4); |
59 | qusb_pci_init_one(pcibus, &uhci2, QPCI_DEVFN(0x1d, 1), 4); | |
60 | qusb_pci_init_one(pcibus, &uhci3, QPCI_DEVFN(0x1d, 2), 4); | |
61 | qusb_pci_init_one(pcibus, &ehci1, QPCI_DEVFN(0x1d, 7), 0); | |
d81d4106 GH |
62 | } |
63 | ||
62030ed1 MAL |
64 | static void test_deinit(void) |
65 | { | |
66 | uhci_deinit(&uhci1); | |
67 | uhci_deinit(&uhci2); | |
68 | uhci_deinit(&uhci3); | |
69 | uhci_deinit(&ehci1); | |
70 | qpci_free_pc(pcibus); | |
71 | } | |
72 | ||
d81d4106 GH |
73 | static void pci_uhci_port_1(void) |
74 | { | |
75 | g_assert(pcibus != NULL); | |
76 | ||
77 | uhci_port_test(&uhci1, 0, UHCI_PORT_CCS); /* usb-tablet */ | |
78 | uhci_port_test(&uhci1, 1, UHCI_PORT_CCS); /* usb-storage */ | |
79 | uhci_port_test(&uhci2, 0, 0); | |
80 | uhci_port_test(&uhci2, 1, 0); | |
81 | uhci_port_test(&uhci3, 0, 0); | |
82 | uhci_port_test(&uhci3, 1, 0); | |
83 | } | |
84 | ||
85 | static void pci_ehci_port_1(void) | |
86 | { | |
87 | int i; | |
88 | ||
89 | g_assert(pcibus != NULL); | |
90 | ||
91 | for (i = 0; i < 6; i++) { | |
92 | ehci_port_test(&ehci1, i, PORTSC_POWNER | PORTSC_PPOWER); | |
93 | } | |
94 | } | |
95 | ||
96 | static void pci_ehci_config(void) | |
97 | { | |
98 | /* hands over all ports from companion uhci to ehci */ | |
b4ba67d9 | 99 | qpci_io_writew(ehci1.dev, ehci1.bar, 0x60, 1); |
d81d4106 GH |
100 | } |
101 | ||
102 | static void pci_uhci_port_2(void) | |
103 | { | |
104 | g_assert(pcibus != NULL); | |
105 | ||
106 | uhci_port_test(&uhci1, 0, 0); /* usb-tablet, @ehci */ | |
107 | uhci_port_test(&uhci1, 1, 0); /* usb-storage, @ehci */ | |
108 | uhci_port_test(&uhci2, 0, 0); | |
109 | uhci_port_test(&uhci2, 1, 0); | |
110 | uhci_port_test(&uhci3, 0, 0); | |
111 | uhci_port_test(&uhci3, 1, 0); | |
112 | } | |
113 | ||
114 | static void pci_ehci_port_2(void) | |
115 | { | |
116 | static uint32_t expect[] = { | |
117 | PORTSC_PPOWER | PORTSC_CONNECT, /* usb-tablet */ | |
118 | PORTSC_PPOWER | PORTSC_CONNECT, /* usb-storage */ | |
119 | PORTSC_PPOWER, | |
120 | PORTSC_PPOWER, | |
121 | PORTSC_PPOWER, | |
122 | PORTSC_PPOWER, | |
123 | }; | |
124 | int i; | |
125 | ||
126 | g_assert(pcibus != NULL); | |
127 | ||
128 | for (i = 0; i < 6; i++) { | |
129 | ehci_port_test(&ehci1, i, expect[i]); | |
130 | } | |
cc900d34 AF |
131 | } |
132 | ||
b3937683 IM |
133 | static void pci_ehci_port_3_hotplug(void) |
134 | { | |
135 | /* check for presence of hotplugged usb-tablet */ | |
136 | g_assert(pcibus != NULL); | |
137 | ehci_port_test(&ehci1, 2, PORTSC_PPOWER | PORTSC_CONNECT); | |
138 | } | |
139 | ||
140 | static void pci_ehci_port_hotplug(void) | |
141 | { | |
82cab70b | 142 | usb_test_hotplug("ich9-ehci-1", "3", pci_ehci_port_3_hotplug); |
b3937683 IM |
143 | } |
144 | ||
145 | ||
cc900d34 AF |
146 | int main(int argc, char **argv) |
147 | { | |
148 | int ret; | |
149 | ||
150 | g_test_init(&argc, &argv, NULL); | |
d3510ff9 | 151 | |
d81d4106 GH |
152 | qtest_add_func("/ehci/pci/uhci-port-1", pci_uhci_port_1); |
153 | qtest_add_func("/ehci/pci/ehci-port-1", pci_ehci_port_1); | |
154 | qtest_add_func("/ehci/pci/ehci-config", pci_ehci_config); | |
155 | qtest_add_func("/ehci/pci/uhci-port-2", pci_uhci_port_2); | |
156 | qtest_add_func("/ehci/pci/ehci-port-2", pci_ehci_port_2); | |
b3937683 | 157 | qtest_add_func("/ehci/pci/ehci-port-3-hotplug", pci_ehci_port_hotplug); |
cc900d34 AF |
158 | |
159 | qtest_start("-machine q35 -device ich9-usb-ehci1,bus=pcie.0,addr=1d.7," | |
160 | "multifunction=on,id=ich9-ehci-1 " | |
161 | "-device ich9-usb-uhci1,bus=pcie.0,addr=1d.0," | |
162 | "multifunction=on,masterbus=ich9-ehci-1.0,firstport=0 " | |
163 | "-device ich9-usb-uhci2,bus=pcie.0,addr=1d.1," | |
164 | "multifunction=on,masterbus=ich9-ehci-1.0,firstport=2 " | |
165 | "-device ich9-usb-uhci3,bus=pcie.0,addr=1d.2," | |
d81d4106 GH |
166 | "multifunction=on,masterbus=ich9-ehci-1.0,firstport=4 " |
167 | "-drive if=none,id=usbcdrom,media=cdrom " | |
168 | "-device usb-tablet,bus=ich9-ehci-1.0,port=1,usb_version=1 " | |
169 | "-device usb-storage,bus=ich9-ehci-1.0,port=2,drive=usbcdrom "); | |
d3510ff9 MAL |
170 | |
171 | test_init(); | |
cc900d34 | 172 | ret = g_test_run(); |
62030ed1 | 173 | test_deinit(); |
cc900d34 AF |
174 | |
175 | qtest_end(); | |
176 | ||
177 | return ret; | |
178 | } |