xref: /openbmc/qemu/hw/ipmi/isa_ipmi_kcs.c (revision 9967e4fec0dc6c0157f37574dd33ddd03ca3bee8)
1 /*
2  * QEMU ISA IPMI KCS emulation
3  *
4  * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
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 #include "hw/hw.h"
25 #include "hw/ipmi/ipmi.h"
26 #include "hw/isa/isa.h"
27 #include "hw/i386/pc.h"
28 
29 #define IPMI_KCS_OBF_BIT        0
30 #define IPMI_KCS_IBF_BIT        1
31 #define IPMI_KCS_SMS_ATN_BIT    2
32 #define IPMI_KCS_CD_BIT         3
33 
34 #define IPMI_KCS_OBF_MASK          (1 << IPMI_KCS_OBF_BIT)
35 #define IPMI_KCS_GET_OBF(d)        (((d) >> IPMI_KCS_OBF_BIT) & 0x1)
36 #define IPMI_KCS_SET_OBF(d, v)     (d) = (((d) & ~IPMI_KCS_OBF_MASK) | \
37                                        (((v) & 1) << IPMI_KCS_OBF_BIT))
38 #define IPMI_KCS_IBF_MASK          (1 << IPMI_KCS_IBF_BIT)
39 #define IPMI_KCS_GET_IBF(d)        (((d) >> IPMI_KCS_IBF_BIT) & 0x1)
40 #define IPMI_KCS_SET_IBF(d, v)     (d) = (((d) & ~IPMI_KCS_IBF_MASK) | \
41                                        (((v) & 1) << IPMI_KCS_IBF_BIT))
42 #define IPMI_KCS_SMS_ATN_MASK      (1 << IPMI_KCS_SMS_ATN_BIT)
43 #define IPMI_KCS_GET_SMS_ATN(d)    (((d) >> IPMI_KCS_SMS_ATN_BIT) & 0x1)
44 #define IPMI_KCS_SET_SMS_ATN(d, v) (d) = (((d) & ~IPMI_KCS_SMS_ATN_MASK) | \
45                                        (((v) & 1) << IPMI_KCS_SMS_ATN_BIT))
46 #define IPMI_KCS_CD_MASK           (1 << IPMI_KCS_CD_BIT)
47 #define IPMI_KCS_GET_CD(d)         (((d) >> IPMI_KCS_CD_BIT) & 0x1)
48 #define IPMI_KCS_SET_CD(d, v)      (d) = (((d) & ~IPMI_KCS_CD_MASK) | \
49                                        (((v) & 1) << IPMI_KCS_CD_BIT))
50 
51 #define IPMI_KCS_IDLE_STATE        0
52 #define IPMI_KCS_READ_STATE        1
53 #define IPMI_KCS_WRITE_STATE       2
54 #define IPMI_KCS_ERROR_STATE       3
55 
56 #define IPMI_KCS_GET_STATE(d)    (((d) >> 6) & 0x3)
57 #define IPMI_KCS_SET_STATE(d, v) ((d) = ((d) & ~0xc0) | (((v) & 0x3) << 6))
58 
59 #define IPMI_KCS_ABORT_STATUS_CMD       0x60
60 #define IPMI_KCS_WRITE_START_CMD        0x61
61 #define IPMI_KCS_WRITE_END_CMD          0x62
62 #define IPMI_KCS_READ_CMD               0x68
63 
64 #define IPMI_KCS_STATUS_NO_ERR          0x00
65 #define IPMI_KCS_STATUS_ABORTED_ERR     0x01
66 #define IPMI_KCS_STATUS_BAD_CC_ERR      0x02
67 #define IPMI_KCS_STATUS_LENGTH_ERR      0x06
68 
69 typedef struct IPMIKCS {
70     IPMIBmc *bmc;
71 
72     bool do_wake;
73 
74     qemu_irq irq;
75 
76     uint32_t io_base;
77     unsigned long io_length;
78     MemoryRegion io;
79 
80     bool obf_irq_set;
81     bool atn_irq_set;
82     bool use_irq;
83     bool irqs_enabled;
84 
85     uint8_t outmsg[MAX_IPMI_MSG_SIZE];
86     uint32_t outpos;
87     uint32_t outlen;
88 
89     uint8_t inmsg[MAX_IPMI_MSG_SIZE];
90     uint32_t inlen;
91     bool write_end;
92 
93     uint8_t status_reg;
94     uint8_t data_out_reg;
95 
96     int16_t data_in_reg; /* -1 means not written */
97     int16_t cmd_reg;
98 
99     /*
100      * This is a response number that we send with the command to make
101      * sure that the response matches the command.
102      */
103     uint8_t waiting_rsp;
104 } IPMIKCS;
105 
106 #define SET_OBF() \
107     do {                                                                      \
108         IPMI_KCS_SET_OBF(ik->status_reg, 1);                                  \
109         if (ik->use_irq && ik->irqs_enabled && !ik->obf_irq_set) {            \
110             ik->obf_irq_set = 1;                                              \
111             if (!ik->atn_irq_set) {                                           \
112                 qemu_irq_raise(ik->irq);                                      \
113             }                                                                 \
114         }                                                                     \
115     } while (0)
116 
117 static void ipmi_kcs_signal(IPMIKCS *ik, IPMIInterface *ii)
118 {
119     IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
120 
121     ik->do_wake = 1;
122     while (ik->do_wake) {
123         ik->do_wake = 0;
124         iic->handle_if_event(ii);
125     }
126 }
127 
128 static void ipmi_kcs_handle_event(IPMIInterface *ii)
129 {
130     IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
131     IPMIKCS *ik = iic->get_backend_data(ii);
132 
133     if (ik->cmd_reg == IPMI_KCS_ABORT_STATUS_CMD) {
134         if (IPMI_KCS_GET_STATE(ik->status_reg) != IPMI_KCS_ERROR_STATE) {
135             ik->waiting_rsp++; /* Invalidate the message */
136             ik->outmsg[0] = IPMI_KCS_STATUS_ABORTED_ERR;
137             ik->outlen = 1;
138             ik->outpos = 0;
139             IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_ERROR_STATE);
140             SET_OBF();
141         }
142         goto out;
143     }
144 
145     switch (IPMI_KCS_GET_STATE(ik->status_reg)) {
146     case IPMI_KCS_IDLE_STATE:
147         if (ik->cmd_reg == IPMI_KCS_WRITE_START_CMD) {
148             IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_WRITE_STATE);
149             ik->cmd_reg = -1;
150             ik->write_end = 0;
151             ik->inlen = 0;
152             SET_OBF();
153         }
154         break;
155 
156     case IPMI_KCS_READ_STATE:
157     handle_read:
158         if (ik->outpos >= ik->outlen) {
159             IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_IDLE_STATE);
160             SET_OBF();
161         } else if (ik->data_in_reg == IPMI_KCS_READ_CMD) {
162             ik->data_out_reg = ik->outmsg[ik->outpos];
163             ik->outpos++;
164             SET_OBF();
165         } else {
166             ik->outmsg[0] = IPMI_KCS_STATUS_BAD_CC_ERR;
167             ik->outlen = 1;
168             ik->outpos = 0;
169             IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_ERROR_STATE);
170             SET_OBF();
171             goto out;
172         }
173         break;
174 
175     case IPMI_KCS_WRITE_STATE:
176         if (ik->data_in_reg != -1) {
177             /*
178              * Don't worry about input overrun here, that will be
179              * handled in the BMC.
180              */
181             if (ik->inlen < sizeof(ik->inmsg)) {
182                 ik->inmsg[ik->inlen] = ik->data_in_reg;
183             }
184             ik->inlen++;
185         }
186         if (ik->write_end) {
187             IPMIBmcClass *bk = IPMI_BMC_GET_CLASS(ik->bmc);
188             ik->outlen = 0;
189             ik->write_end = 0;
190             ik->outpos = 0;
191             bk->handle_command(ik->bmc, ik->inmsg, ik->inlen, sizeof(ik->inmsg),
192                                ik->waiting_rsp);
193             goto out_noibf;
194         } else if (ik->cmd_reg == IPMI_KCS_WRITE_END_CMD) {
195             ik->cmd_reg = -1;
196             ik->write_end = 1;
197         }
198         SET_OBF();
199         break;
200 
201     case IPMI_KCS_ERROR_STATE:
202         if (ik->data_in_reg != -1) {
203             IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_READ_STATE);
204             ik->data_in_reg = IPMI_KCS_READ_CMD;
205             goto handle_read;
206         }
207         break;
208     }
209 
210     if (ik->cmd_reg != -1) {
211         /* Got an invalid command */
212         ik->outmsg[0] = IPMI_KCS_STATUS_BAD_CC_ERR;
213         ik->outlen = 1;
214         ik->outpos = 0;
215         IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_ERROR_STATE);
216     }
217 
218  out:
219     ik->cmd_reg = -1;
220     ik->data_in_reg = -1;
221     IPMI_KCS_SET_IBF(ik->status_reg, 0);
222  out_noibf:
223     return;
224 }
225 
226 static void ipmi_kcs_handle_rsp(IPMIInterface *ii, uint8_t msg_id,
227                                 unsigned char *rsp, unsigned int rsp_len)
228 {
229     IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
230     IPMIKCS *ik = iic->get_backend_data(ii);
231 
232     if (ik->waiting_rsp == msg_id) {
233         ik->waiting_rsp++;
234         if (rsp_len > sizeof(ik->outmsg)) {
235             ik->outmsg[0] = rsp[0];
236             ik->outmsg[1] = rsp[1];
237             ik->outmsg[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES;
238             ik->outlen = 3;
239         } else {
240             memcpy(ik->outmsg, rsp, rsp_len);
241             ik->outlen = rsp_len;
242         }
243         IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_READ_STATE);
244         ik->data_in_reg = IPMI_KCS_READ_CMD;
245         ipmi_kcs_signal(ik, ii);
246     }
247 }
248 
249 
250 static uint64_t ipmi_kcs_ioport_read(void *opaque, hwaddr addr, unsigned size)
251 {
252     IPMIInterface *ii = opaque;
253     IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
254     IPMIKCS *ik = iic->get_backend_data(ii);
255     uint32_t ret;
256 
257     switch (addr & 1) {
258     case 0:
259         ret = ik->data_out_reg;
260         IPMI_KCS_SET_OBF(ik->status_reg, 0);
261         if (ik->obf_irq_set) {
262             ik->obf_irq_set = 0;
263             if (!ik->atn_irq_set) {
264                 qemu_irq_lower(ik->irq);
265             }
266         }
267         break;
268     case 1:
269         ret = ik->status_reg;
270         if (ik->atn_irq_set) {
271             ik->atn_irq_set = 0;
272             if (!ik->obf_irq_set) {
273                 qemu_irq_lower(ik->irq);
274             }
275         }
276         break;
277     }
278     return ret;
279 }
280 
281 static void ipmi_kcs_ioport_write(void *opaque, hwaddr addr, uint64_t val,
282                                   unsigned size)
283 {
284     IPMIInterface *ii = opaque;
285     IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
286     IPMIKCS *ik = iic->get_backend_data(ii);
287 
288     if (IPMI_KCS_GET_IBF(ik->status_reg)) {
289         return;
290     }
291 
292     switch (addr & 1) {
293     case 0:
294         ik->data_in_reg = val;
295         break;
296 
297     case 1:
298         ik->cmd_reg = val;
299         break;
300     }
301     IPMI_KCS_SET_IBF(ik->status_reg, 1);
302     ipmi_kcs_signal(ik, ii);
303 }
304 
305 const MemoryRegionOps ipmi_kcs_io_ops = {
306     .read = ipmi_kcs_ioport_read,
307     .write = ipmi_kcs_ioport_write,
308     .impl = {
309         .min_access_size = 1,
310         .max_access_size = 1,
311     },
312     .endianness = DEVICE_LITTLE_ENDIAN,
313 };
314 
315 static void ipmi_kcs_set_atn(IPMIInterface *ii, int val, int irq)
316 {
317     IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
318     IPMIKCS *ik = iic->get_backend_data(ii);
319 
320     IPMI_KCS_SET_SMS_ATN(ik->status_reg, val);
321     if (val) {
322         if (irq && !ik->atn_irq_set && ik->use_irq && ik->irqs_enabled) {
323             ik->atn_irq_set = 1;
324             if (!ik->obf_irq_set) {
325                 qemu_irq_raise(ik->irq);
326             }
327         }
328     } else {
329         if (ik->atn_irq_set) {
330             ik->atn_irq_set = 0;
331             if (!ik->obf_irq_set) {
332                 qemu_irq_lower(ik->irq);
333             }
334         }
335     }
336 }
337 
338 static void ipmi_kcs_set_irq_enable(IPMIInterface *ii, int val)
339 {
340     IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
341     IPMIKCS *ik = iic->get_backend_data(ii);
342 
343     ik->irqs_enabled = val;
344 }
345 
346 static void ipmi_kcs_init(IPMIInterface *ii, Error **errp)
347 {
348     IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
349     IPMIKCS *ik = iic->get_backend_data(ii);
350 
351     ik->io_length = 2;
352     memory_region_init_io(&ik->io, NULL, &ipmi_kcs_io_ops, ii, "ipmi-kcs", 2);
353 }
354 
355 static void ipmi_kcs_class_init(IPMIInterfaceClass *iic)
356 {
357     iic->init = ipmi_kcs_init;
358     iic->set_atn = ipmi_kcs_set_atn;
359     iic->handle_rsp = ipmi_kcs_handle_rsp;
360     iic->handle_if_event = ipmi_kcs_handle_event;
361     iic->set_irq_enable = ipmi_kcs_set_irq_enable;
362 }
363 
364 
365 #define TYPE_ISA_IPMI_KCS "isa-ipmi-kcs"
366 #define ISA_IPMI_KCS(obj) OBJECT_CHECK(ISAIPMIKCSDevice, (obj), \
367                                        TYPE_ISA_IPMI_KCS)
368 
369 typedef struct ISAIPMIKCSDevice {
370     ISADevice dev;
371     int32 isairq;
372     IPMIKCS kcs;
373     IPMIFwInfo fwinfo;
374 } ISAIPMIKCSDevice;
375 
376 static void ipmi_isa_realize(DeviceState *dev, Error **errp)
377 {
378     ISADevice *isadev = ISA_DEVICE(dev);
379     ISAIPMIKCSDevice *iik = ISA_IPMI_KCS(dev);
380     IPMIInterface *ii = IPMI_INTERFACE(dev);
381     IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
382 
383     if (!iik->kcs.bmc) {
384         error_setg(errp, "IPMI device requires a bmc attribute to be set");
385         return;
386     }
387 
388     iik->kcs.bmc->intf = ii;
389 
390     iic->init(ii, errp);
391     if (*errp)
392         return;
393 
394     if (iik->isairq > 0) {
395         isa_init_irq(isadev, &iik->kcs.irq, iik->isairq);
396         iik->kcs.use_irq = 1;
397     }
398 
399     qdev_set_legacy_instance_id(dev, iik->kcs.io_base, iik->kcs.io_length);
400 
401     isa_register_ioport(isadev, &iik->kcs.io, iik->kcs.io_base);
402 
403     iik->fwinfo.interface_name = "kcs";
404     iik->fwinfo.interface_type = IPMI_SMBIOS_KCS;
405     iik->fwinfo.ipmi_spec_major_revision = 2;
406     iik->fwinfo.ipmi_spec_minor_revision = 0;
407     iik->fwinfo.base_address = iik->kcs.io_base;
408     iik->fwinfo.i2c_slave_address = iik->kcs.bmc->slave_addr;
409     iik->fwinfo.register_length = iik->kcs.io_length;
410     iik->fwinfo.register_spacing = 1;
411     iik->fwinfo.memspace = IPMI_MEMSPACE_IO;
412     iik->fwinfo.irq_type = IPMI_LEVEL_IRQ;
413     iik->fwinfo.interrupt_number = iik->isairq;
414     iik->fwinfo.acpi_parent = "\\_SB.PCI0.ISA";
415     ipmi_add_fwinfo(&iik->fwinfo, errp);
416 }
417 
418 const VMStateDescription vmstate_ISAIPMIKCSDevice = {
419     .name = TYPE_IPMI_INTERFACE,
420     .version_id = 1,
421     .minimum_version_id = 1,
422     .fields      = (VMStateField[]) {
423         VMSTATE_BOOL(kcs.obf_irq_set, ISAIPMIKCSDevice),
424         VMSTATE_BOOL(kcs.atn_irq_set, ISAIPMIKCSDevice),
425         VMSTATE_BOOL(kcs.use_irq, ISAIPMIKCSDevice),
426         VMSTATE_BOOL(kcs.irqs_enabled, ISAIPMIKCSDevice),
427         VMSTATE_UINT32(kcs.outpos, ISAIPMIKCSDevice),
428         VMSTATE_VBUFFER_UINT32(kcs.outmsg, ISAIPMIKCSDevice, 1, NULL, 0,
429                                kcs.outlen),
430         VMSTATE_VBUFFER_UINT32(kcs.inmsg, ISAIPMIKCSDevice, 1, NULL, 0,
431                                kcs.inlen),
432         VMSTATE_BOOL(kcs.write_end, ISAIPMIKCSDevice),
433         VMSTATE_UINT8(kcs.status_reg, ISAIPMIKCSDevice),
434         VMSTATE_UINT8(kcs.data_out_reg, ISAIPMIKCSDevice),
435         VMSTATE_INT16(kcs.data_in_reg, ISAIPMIKCSDevice),
436         VMSTATE_INT16(kcs.cmd_reg, ISAIPMIKCSDevice),
437         VMSTATE_UINT8(kcs.waiting_rsp, ISAIPMIKCSDevice),
438         VMSTATE_END_OF_LIST()
439     }
440 };
441 
442 static void isa_ipmi_kcs_init(Object *obj)
443 {
444     ISAIPMIKCSDevice *iik = ISA_IPMI_KCS(obj);
445 
446     ipmi_bmc_find_and_link(obj, (Object **) &iik->kcs.bmc);
447 
448     vmstate_register(NULL, 0, &vmstate_ISAIPMIKCSDevice, iik);
449 }
450 
451 static void *isa_ipmi_kcs_get_backend_data(IPMIInterface *ii)
452 {
453     ISAIPMIKCSDevice *iik = ISA_IPMI_KCS(ii);
454 
455     return &iik->kcs;
456 }
457 
458 static Property ipmi_isa_properties[] = {
459     DEFINE_PROP_UINT32("ioport", ISAIPMIKCSDevice, kcs.io_base,  0xca2),
460     DEFINE_PROP_INT32("irq",   ISAIPMIKCSDevice, isairq,  5),
461     DEFINE_PROP_END_OF_LIST(),
462 };
463 
464 static void isa_ipmi_kcs_class_init(ObjectClass *oc, void *data)
465 {
466     DeviceClass *dc = DEVICE_CLASS(oc);
467     IPMIInterfaceClass *iic = IPMI_INTERFACE_CLASS(oc);
468 
469     dc->realize = ipmi_isa_realize;
470     dc->props = ipmi_isa_properties;
471 
472     iic->get_backend_data = isa_ipmi_kcs_get_backend_data;
473     ipmi_kcs_class_init(iic);
474 }
475 
476 static const TypeInfo isa_ipmi_kcs_info = {
477     .name          = TYPE_ISA_IPMI_KCS,
478     .parent        = TYPE_ISA_DEVICE,
479     .instance_size = sizeof(ISAIPMIKCSDevice),
480     .instance_init = isa_ipmi_kcs_init,
481     .class_init    = isa_ipmi_kcs_class_init,
482     .interfaces = (InterfaceInfo[]) {
483         { TYPE_IPMI_INTERFACE },
484         { }
485     }
486 };
487 
488 static void ipmi_register_types(void)
489 {
490     type_register_static(&isa_ipmi_kcs_info);
491 }
492 
493 type_init(ipmi_register_types)
494