1/* 2 * etrace gpio 3 * 4 * Copyright (c) 2014 Xilinx 5 * Written by Edgar E. Iglesias 6 * 7 * FIXME: Clean up. Can probably be done more effiently and without 8 * touch all the internals of sysbus and devices. 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 22 */ 23 24#include "qemu/osdep.h" 25#include "qemu-common.h" 26#include "cpu.h" 27#include "monitor/monitor.h" 28#include "monitor/qdev.h" 29#include "qapi/qapi-commands-ui.h" 30#include "qapi/qapi-events-ui.h" 31#include "sysemu/arch_init.h" 32#include "qemu/config-file.h" 33 34#include "qemu/etrace.h" 35 36#ifndef CONFIG_USER_ONLY 37#include "hw/qdev-core.h" 38#include "hw/sysbus.h" 39 40typedef struct { 41 DeviceState *dev; 42 const char *devname; 43 char *name; 44 unsigned int level; 45 bool set; 46} IRQInterceptState; 47 48// static void trace_irq_handler(void *opaque, int n, int level) 49// { 50// IRQInterceptState *iis = opaque; 51// uint32_t flags = ETRACE_EVU64_F_NONE; 52 53// if (iis->set && (iis->level == level)) { 54// return; 55// } 56 57// if (iis->set) { 58// flags = ETRACE_EVU64_F_PREV_VAL; 59// } 60// etrace_event_u64(&qemu_etracer, -1, flags, iis->devname, 61// iis->name, level, iis->level); 62// iis->set = true; 63// iis->level = level; 64// } 65 66// static void intercept_irq(DeviceState *dev, char *irq_name, int i, char *name) 67// { 68// IRQInterceptState *iis; 69// qemu_irq new; 70 71// iis = g_new0(IRQInterceptState, 1); 72// iis->devname = object_get_canonical_path(OBJECT(dev)); 73// iis->name = name; 74// new = qemu_allocate_irq(trace_irq_handler, iis, 0); 75// object_property_add_child(OBJECT(dev), name, OBJECT(new), NULL); 76// qdev_connect_gpio_out_named(dev, irq_name, i, new); 77// } 78 79static void sysbus_init(SysBusDevice *dev) 80{ 81 /* FIXME: restore service */ 82 // unsigned int i = 0; 83 84 // for (i = 0; i < dev->num_irq; i++) { 85 // char *name; 86 // int r; 87 // /* Unfortunately there is no sysbus_get_irq() :( */ 88 // char *irq_name = g_strdup_printf(SYSBUS_DEVICE_GPIO_IRQ "-%d", i); 89 // qemu_irq irq = qdev_get_gpio_out_named(DEVICE(dev), irq_name, 0); 90 91 // if (!irq) { 92 // g_free(irq_name); 93 // continue; 94 // } 95 96 // r = asprintf(&name, "irq[%u]", i); 97 // assert(r > 0); 98 // intercept_irq(DEVICE(dev), irq_name, i, name); 99 // g_free(irq_name); 100 // } 101} 102 103static void dev_named_init(DeviceState *dev, NamedGPIOList *l) 104{ 105 // unsigned int i = 0; 106 107 // if (!l->num_out) { 108 // return; 109 // } 110 111 // for (i = 0; i < l->num_out; i++) { 112 // char *name; 113 // int r; 114 115 // if (!l->out[i]) { 116 // continue; 117 // } 118 119 // r = asprintf(&name, "%s[%u]", l->name ? l->name : "gpio-out", i); 120 // assert(r > 0); 121 // intercept_irq(DEVICE(dev), l->name, i, name); 122 // } 123} 124 125static int dev_init(Object *obj, void *opaque) 126{ 127 SysBusDevice *sbd = 128 (SysBusDevice *)object_dynamic_cast(obj, TYPE_SYS_BUS_DEVICE); 129 DeviceState *dev = (DeviceState *)object_dynamic_cast(obj, TYPE_DEVICE); 130 NamedGPIOList *l; 131 132 if (sbd) { 133 sysbus_init(sbd); 134 } 135 136 if (dev) { 137 QLIST_FOREACH(l, &dev->gpios, node) { 138 dev_named_init(dev, l); 139 } 140 } 141 return 0; 142} 143 144void qemu_etrace_gpio_init(void) 145{ 146 object_child_foreach_recursive(object_get_root(), dev_init, NULL); 147} 148 149#endif 150