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