xref: /openbmc/qemu/hw/char/debugcon.c (revision 41192db338588051f21501abc13743e62b0a5605)
19944d320SPaolo Bonzini /*
29944d320SPaolo Bonzini  * QEMU Bochs-style debug console ("port E9") emulation
39944d320SPaolo Bonzini  *
49944d320SPaolo Bonzini  * Copyright (c) 2003-2004 Fabrice Bellard
59944d320SPaolo Bonzini  * Copyright (c) 2008 Citrix Systems, Inc.
69944d320SPaolo Bonzini  * Copyright (c) Intel Corporation; author: H. Peter Anvin
79944d320SPaolo Bonzini  *
89944d320SPaolo Bonzini  * Permission is hereby granted, free of charge, to any person obtaining a copy
99944d320SPaolo Bonzini  * of this software and associated documentation files (the "Software"), to deal
109944d320SPaolo Bonzini  * in the Software without restriction, including without limitation the rights
119944d320SPaolo Bonzini  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
129944d320SPaolo Bonzini  * copies of the Software, and to permit persons to whom the Software is
139944d320SPaolo Bonzini  * furnished to do so, subject to the following conditions:
149944d320SPaolo Bonzini  *
159944d320SPaolo Bonzini  * The above copyright notice and this permission notice shall be included in
169944d320SPaolo Bonzini  * all copies or substantial portions of the Software.
179944d320SPaolo Bonzini  *
189944d320SPaolo Bonzini  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
199944d320SPaolo Bonzini  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
209944d320SPaolo Bonzini  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
219944d320SPaolo Bonzini  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
229944d320SPaolo Bonzini  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
239944d320SPaolo Bonzini  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
249944d320SPaolo Bonzini  * THE SOFTWARE.
259944d320SPaolo Bonzini  */
269944d320SPaolo Bonzini 
27b6a0aa05SPeter Maydell #include "qemu/osdep.h"
28da34e65cSMarkus Armbruster #include "qapi/error.h"
290b8fa32fSMarkus Armbruster #include "qemu/module.h"
304d43a603SMarc-André Lureau #include "chardev/char-fe.h"
319944d320SPaolo Bonzini #include "hw/isa/isa.h"
32a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
33*ce35e229SEduardo Habkost #include "hw/qdev-properties-system.h"
34db1015e9SEduardo Habkost #include "qom/object.h"
359944d320SPaolo Bonzini 
369944d320SPaolo Bonzini #define TYPE_ISA_DEBUGCON_DEVICE "isa-debugcon"
378063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(ISADebugconState, ISA_DEBUGCON_DEVICE)
389944d320SPaolo Bonzini 
399944d320SPaolo Bonzini //#define DEBUG_DEBUGCON
409944d320SPaolo Bonzini 
419944d320SPaolo Bonzini typedef struct DebugconState {
429944d320SPaolo Bonzini     MemoryRegion io;
43becdfa00SMarc-André Lureau     CharBackend chr;
449944d320SPaolo Bonzini     uint32_t readback;
459944d320SPaolo Bonzini } DebugconState;
469944d320SPaolo Bonzini 
47db1015e9SEduardo Habkost struct ISADebugconState {
489944d320SPaolo Bonzini     ISADevice parent_obj;
499944d320SPaolo Bonzini 
509944d320SPaolo Bonzini     uint32_t iobase;
519944d320SPaolo Bonzini     DebugconState state;
52db1015e9SEduardo Habkost };
539944d320SPaolo Bonzini 
debugcon_ioport_write(void * opaque,hwaddr addr,uint64_t val,unsigned width)549944d320SPaolo Bonzini static void debugcon_ioport_write(void *opaque, hwaddr addr, uint64_t val,
559944d320SPaolo Bonzini                                   unsigned width)
569944d320SPaolo Bonzini {
579944d320SPaolo Bonzini     DebugconState *s = opaque;
589944d320SPaolo Bonzini     unsigned char ch = val;
599944d320SPaolo Bonzini 
609944d320SPaolo Bonzini #ifdef DEBUG_DEBUGCON
61668fca91Sliguang     printf(" [debugcon: write addr=0x%04" HWADDR_PRIx " val=0x%02" PRIx64 "]\n", addr, val);
629944d320SPaolo Bonzini #endif
639944d320SPaolo Bonzini 
646ab3fc32SDaniel P. Berrange     /* XXX this blocks entire thread. Rewrite to use
656ab3fc32SDaniel P. Berrange      * qemu_chr_fe_write and background I/O callbacks */
665345fdb4SMarc-André Lureau     qemu_chr_fe_write_all(&s->chr, &ch, 1);
679944d320SPaolo Bonzini }
689944d320SPaolo Bonzini 
699944d320SPaolo Bonzini 
debugcon_ioport_read(void * opaque,hwaddr addr,unsigned width)709944d320SPaolo Bonzini static uint64_t debugcon_ioport_read(void *opaque, hwaddr addr, unsigned width)
719944d320SPaolo Bonzini {
729944d320SPaolo Bonzini     DebugconState *s = opaque;
739944d320SPaolo Bonzini 
749944d320SPaolo Bonzini #ifdef DEBUG_DEBUGCON
75668fca91Sliguang     printf("debugcon: read addr=0x%04" HWADDR_PRIx "\n", addr);
769944d320SPaolo Bonzini #endif
779944d320SPaolo Bonzini 
789944d320SPaolo Bonzini     return s->readback;
799944d320SPaolo Bonzini }
809944d320SPaolo Bonzini 
819944d320SPaolo Bonzini static const MemoryRegionOps debugcon_ops = {
829944d320SPaolo Bonzini     .read = debugcon_ioport_read,
839944d320SPaolo Bonzini     .write = debugcon_ioport_write,
849944d320SPaolo Bonzini     .valid.min_access_size = 1,
859944d320SPaolo Bonzini     .valid.max_access_size = 1,
869944d320SPaolo Bonzini     .endianness = DEVICE_LITTLE_ENDIAN,
879944d320SPaolo Bonzini };
889944d320SPaolo Bonzini 
debugcon_realize_core(DebugconState * s,Error ** errp)89db895a1eSAndreas Färber static void debugcon_realize_core(DebugconState *s, Error **errp)
909944d320SPaolo Bonzini {
9130650701SAnton Nefedov     if (!qemu_chr_fe_backend_connected(&s->chr)) {
92db895a1eSAndreas Färber         error_setg(errp, "Can't create debugcon device, empty char device");
93db895a1eSAndreas Färber         return;
949944d320SPaolo Bonzini     }
959944d320SPaolo Bonzini 
9681517ba3SAnton Nefedov     qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, NULL, NULL, s, NULL, true);
979944d320SPaolo Bonzini }
989944d320SPaolo Bonzini 
debugcon_isa_realizefn(DeviceState * dev,Error ** errp)99db895a1eSAndreas Färber static void debugcon_isa_realizefn(DeviceState *dev, Error **errp)
1009944d320SPaolo Bonzini {
101db895a1eSAndreas Färber     ISADevice *d = ISA_DEVICE(dev);
1029944d320SPaolo Bonzini     ISADebugconState *isa = ISA_DEBUGCON_DEVICE(dev);
1039944d320SPaolo Bonzini     DebugconState *s = &isa->state;
104db895a1eSAndreas Färber     Error *err = NULL;
1059944d320SPaolo Bonzini 
106db895a1eSAndreas Färber     debugcon_realize_core(s, &err);
107db895a1eSAndreas Färber     if (err != NULL) {
108db895a1eSAndreas Färber         error_propagate(errp, err);
109db895a1eSAndreas Färber         return;
110db895a1eSAndreas Färber     }
111300b1fc6SPaolo Bonzini     memory_region_init_io(&s->io, OBJECT(dev), &debugcon_ops, s,
1129944d320SPaolo Bonzini                           TYPE_ISA_DEBUGCON_DEVICE, 1);
113db895a1eSAndreas Färber     memory_region_add_subregion(isa_address_space_io(d),
1149944d320SPaolo Bonzini                                 isa->iobase, &s->io);
1159944d320SPaolo Bonzini }
1169944d320SPaolo Bonzini 
1179944d320SPaolo Bonzini static Property debugcon_isa_properties[] = {
118c7bcc85dSPaolo Bonzini     DEFINE_PROP_UINT32("iobase", ISADebugconState, iobase, 0xe9),
1199944d320SPaolo Bonzini     DEFINE_PROP_CHR("chardev",  ISADebugconState, state.chr),
120c7bcc85dSPaolo Bonzini     DEFINE_PROP_UINT32("readback", ISADebugconState, state.readback, 0xe9),
1219944d320SPaolo Bonzini     DEFINE_PROP_END_OF_LIST(),
1229944d320SPaolo Bonzini };
1239944d320SPaolo Bonzini 
debugcon_isa_class_initfn(ObjectClass * klass,void * data)1249944d320SPaolo Bonzini static void debugcon_isa_class_initfn(ObjectClass *klass, void *data)
1259944d320SPaolo Bonzini {
1269944d320SPaolo Bonzini     DeviceClass *dc = DEVICE_CLASS(klass);
127db895a1eSAndreas Färber 
128db895a1eSAndreas Färber     dc->realize = debugcon_isa_realizefn;
1294f67d30bSMarc-André Lureau     device_class_set_props(dc, debugcon_isa_properties);
130125ee0edSMarcel Apfelbaum     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
1319944d320SPaolo Bonzini }
1329944d320SPaolo Bonzini 
1339944d320SPaolo Bonzini static const TypeInfo debugcon_isa_info = {
1349944d320SPaolo Bonzini     .name          = TYPE_ISA_DEBUGCON_DEVICE,
1359944d320SPaolo Bonzini     .parent        = TYPE_ISA_DEVICE,
1369944d320SPaolo Bonzini     .instance_size = sizeof(ISADebugconState),
1379944d320SPaolo Bonzini     .class_init    = debugcon_isa_class_initfn,
1389944d320SPaolo Bonzini };
1399944d320SPaolo Bonzini 
debugcon_register_types(void)1409944d320SPaolo Bonzini static void debugcon_register_types(void)
1419944d320SPaolo Bonzini {
1429944d320SPaolo Bonzini     type_register_static(&debugcon_isa_info);
1439944d320SPaolo Bonzini }
1449944d320SPaolo Bonzini 
1459944d320SPaolo Bonzini type_init(debugcon_register_types)
146