]> Git Repo - qemu.git/blob - tests/ipmi-kcs-test.c
qapi: Plumb in 'boxed' to qapi generator lower levels
[qemu.git] / tests / ipmi-kcs-test.c
1 /*
2  * IPMI KCS test cases, using the local interface.
3  *
4  * Copyright (c) 2012 Corey Minyard <[email protected]>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24
25 #include "qemu/osdep.h"
26
27
28 #include "libqtest.h"
29
30 #define IPMI_IRQ        5
31
32 #define IPMI_KCS_BASE   0xca2
33
34 #define IPMI_KCS_STATUS_ABORT           0x60
35 #define IPMI_KCS_CMD_WRITE_START        0x61
36 #define IPMI_KCS_CMD_WRITE_END          0x62
37 #define IPMI_KCS_CMD_READ               0x68
38
39 #define IPMI_KCS_ABORTED_BY_CMD         0x01
40
41 #define IPMI_KCS_CMDREG_GET_STATE() ((kcs_get_cmdreg() >> 6) & 3)
42 #define IPMI_KCS_STATE_IDLE     0
43 #define IPMI_KCS_STATE_READ     1
44 #define IPMI_KCS_STATE_WRITE    2
45 #define IPMI_KCS_STATE_ERROR    3
46 #define IPMI_KCS_CMDREG_GET_CD()    ((kcs_get_cmdreg() >> 3) & 1)
47 #define IPMI_KCS_CMDREG_GET_ATN()   ((kcs_get_cmdreg() >> 2) & 1)
48 #define IPMI_KCS_CMDREG_GET_IBF()   ((kcs_get_cmdreg() >> 1) & 1)
49 #define IPMI_KCS_CMDREG_GET_OBF()   ((kcs_get_cmdreg() >> 0) & 1)
50
51 static int kcs_ints_enabled;
52
53 static uint8_t kcs_get_cmdreg(void)
54 {
55     return inb(IPMI_KCS_BASE + 1);
56 }
57
58 static void kcs_write_cmdreg(uint8_t val)
59 {
60     outb(IPMI_KCS_BASE + 1, val);
61 }
62
63 static uint8_t kcs_get_datareg(void)
64 {
65     return inb(IPMI_KCS_BASE);
66 }
67
68 static void kcs_write_datareg(uint8_t val)
69 {
70     outb(IPMI_KCS_BASE, val);
71 }
72
73 static void kcs_wait_ibf(void)
74 {
75     unsigned int count = 1000;
76     while (IPMI_KCS_CMDREG_GET_IBF() != 0) {
77         g_assert(--count != 0);
78     }
79 }
80
81 static void kcs_wait_obf(void)
82 {
83     unsigned int count = 1000;
84     while (IPMI_KCS_CMDREG_GET_OBF() == 0) {
85         g_assert(--count != 0);
86     }
87 }
88
89 static void kcs_clear_obf(void)
90 {
91     if (kcs_ints_enabled) {
92         g_assert(get_irq(IPMI_IRQ));
93     } else {
94         g_assert(!get_irq(IPMI_IRQ));
95     }
96     g_assert(IPMI_KCS_CMDREG_GET_OBF() == 1);
97     kcs_get_datareg();
98     g_assert(IPMI_KCS_CMDREG_GET_OBF() == 0);
99     g_assert(!get_irq(IPMI_IRQ));
100 }
101
102 static void kcs_check_state(uint8_t state)
103 {
104     g_assert(IPMI_KCS_CMDREG_GET_STATE() == state);
105 }
106
107 static void kcs_cmd(uint8_t *cmd, unsigned int cmd_len,
108                     uint8_t *rsp, unsigned int *rsp_len)
109 {
110     unsigned int i, j = 0;
111
112     /* Should be idle */
113     g_assert(kcs_get_cmdreg() == 0);
114
115     kcs_write_cmdreg(IPMI_KCS_CMD_WRITE_START);
116     kcs_wait_ibf();
117     kcs_check_state(IPMI_KCS_STATE_WRITE);
118     kcs_clear_obf();
119     for (i = 0; i < cmd_len; i++) {
120         kcs_write_datareg(cmd[i]);
121         kcs_wait_ibf();
122         kcs_check_state(IPMI_KCS_STATE_WRITE);
123         kcs_clear_obf();
124     }
125     kcs_write_cmdreg(IPMI_KCS_CMD_WRITE_END);
126     kcs_wait_ibf();
127     kcs_check_state(IPMI_KCS_STATE_WRITE);
128     kcs_clear_obf();
129     kcs_write_datareg(0);
130  next_read_byte:
131     kcs_wait_ibf();
132     switch (IPMI_KCS_CMDREG_GET_STATE()) {
133     case IPMI_KCS_STATE_READ:
134         kcs_wait_obf();
135         g_assert(j < *rsp_len);
136         rsp[j++] = kcs_get_datareg();
137         kcs_write_datareg(IPMI_KCS_CMD_READ);
138         goto next_read_byte;
139         break;
140
141     case IPMI_KCS_STATE_IDLE:
142         kcs_wait_obf();
143         kcs_get_datareg();
144         break;
145
146     default:
147         g_assert(0);
148     }
149     *rsp_len = j;
150 }
151
152 static void kcs_abort(uint8_t *cmd, unsigned int cmd_len,
153                       uint8_t *rsp, unsigned int *rsp_len)
154 {
155     unsigned int i, j = 0;
156     unsigned int retries = 4;
157
158     /* Should be idle */
159     g_assert(kcs_get_cmdreg() == 0);
160
161     kcs_write_cmdreg(IPMI_KCS_CMD_WRITE_START);
162     kcs_wait_ibf();
163     kcs_check_state(IPMI_KCS_STATE_WRITE);
164     kcs_clear_obf();
165     for (i = 0; i < cmd_len; i++) {
166         kcs_write_datareg(cmd[i]);
167         kcs_wait_ibf();
168         kcs_check_state(IPMI_KCS_STATE_WRITE);
169         kcs_clear_obf();
170     }
171     kcs_write_cmdreg(IPMI_KCS_CMD_WRITE_END);
172     kcs_wait_ibf();
173     kcs_check_state(IPMI_KCS_STATE_WRITE);
174     kcs_clear_obf();
175     kcs_write_datareg(0);
176     kcs_wait_ibf();
177     switch (IPMI_KCS_CMDREG_GET_STATE()) {
178     case IPMI_KCS_STATE_READ:
179         kcs_wait_obf();
180         g_assert(j < *rsp_len);
181         rsp[j++] = kcs_get_datareg();
182         kcs_write_datareg(IPMI_KCS_CMD_READ);
183         break;
184
185     default:
186         g_assert(0);
187     }
188
189     /* Start the abort here */
190  retry_abort:
191     g_assert(retries > 0);
192
193     kcs_wait_ibf();
194     kcs_write_cmdreg(IPMI_KCS_STATUS_ABORT);
195     kcs_wait_ibf();
196     kcs_clear_obf();
197     kcs_write_datareg(0);
198     kcs_wait_ibf();
199     if (IPMI_KCS_CMDREG_GET_STATE() != IPMI_KCS_STATE_READ) {
200         retries--;
201         goto retry_abort;
202     }
203     kcs_wait_obf();
204     rsp[0] = kcs_get_datareg();
205     kcs_write_datareg(IPMI_KCS_CMD_READ);
206     kcs_wait_ibf();
207     if (IPMI_KCS_CMDREG_GET_STATE() != IPMI_KCS_STATE_IDLE) {
208         retries--;
209         goto retry_abort;
210     }
211     kcs_wait_obf();
212     kcs_clear_obf();
213
214     *rsp_len = j;
215 }
216
217
218 static uint8_t get_dev_id_cmd[] = { 0x18, 0x01 };
219 static uint8_t get_dev_id_rsp[] = { 0x1c, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00,
220                                     0x02, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00 };
221
222 /*
223  * Send a get_device_id to do a basic test.
224  */
225 static void test_kcs_base(void)
226 {
227     uint8_t rsp[20];
228     unsigned int rsplen = sizeof(rsp);
229
230     kcs_cmd(get_dev_id_cmd, sizeof(get_dev_id_cmd), rsp, &rsplen);
231     g_assert(rsplen == sizeof(get_dev_id_rsp));
232     g_assert(memcmp(get_dev_id_rsp, rsp, rsplen) == 0);
233 }
234
235 /*
236  * Abort a kcs operation while reading
237  */
238 static void test_kcs_abort(void)
239 {
240     uint8_t rsp[20];
241     unsigned int rsplen = sizeof(rsp);
242
243     kcs_abort(get_dev_id_cmd, sizeof(get_dev_id_cmd), rsp, &rsplen);
244     g_assert(rsp[0] == IPMI_KCS_ABORTED_BY_CMD);
245 }
246
247 static uint8_t set_bmc_globals_cmd[] = { 0x18, 0x2e, 0x0f };
248 static uint8_t set_bmc_globals_rsp[] = { 0x1c, 0x2e, 0x00 };
249
250 /*
251  * Enable interrupts
252  */
253 static void test_enable_irq(void)
254 {
255     uint8_t rsp[20];
256     unsigned int rsplen = sizeof(rsp);
257
258     kcs_cmd(set_bmc_globals_cmd, sizeof(set_bmc_globals_cmd), rsp, &rsplen);
259     g_assert(rsplen == sizeof(set_bmc_globals_rsp));
260     g_assert(memcmp(set_bmc_globals_rsp, rsp, rsplen) == 0);
261     kcs_ints_enabled = 1;
262 }
263
264 int main(int argc, char **argv)
265 {
266     const char *arch = qtest_get_arch();
267     char *cmdline;
268     int ret;
269
270     /* Check architecture */
271     if (strcmp(arch, "i386") && strcmp(arch, "x86_64")) {
272         g_test_message("Skipping test for non-x86\n");
273         return 0;
274     }
275
276     /* Run the tests */
277     g_test_init(&argc, &argv, NULL);
278
279     cmdline = g_strdup_printf("-vnc none -device ipmi-bmc-sim,id=bmc0"
280                               " -device isa-ipmi-kcs,bmc=bmc0");
281     qtest_start(cmdline);
282     qtest_irq_intercept_in(global_qtest, "ioapic");
283     qtest_add_func("/ipmi/local/kcs_base", test_kcs_base);
284     qtest_add_func("/ipmi/local/kcs_abort", test_kcs_abort);
285     qtest_add_func("/ipmi/local/kcs_enable_irq", test_enable_irq);
286     qtest_add_func("/ipmi/local/kcs_base_irq", test_kcs_base);
287     qtest_add_func("/ipmi/local/kcs_abort_irq", test_kcs_abort);
288     ret = g_test_run();
289     qtest_quit(global_qtest);
290
291     return ret;
292 }
This page took 0.039898 seconds and 4 git commands to generate.