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 "qmp-commands.h" 30#include "sysemu/arch_init.h" 31#include "qemu/config-file.h" 32 33#include "qemu/etrace.h" 34 35#ifndef CONFIG_USER_ONLY 36#include "hw/qdev.h" 37#include "hw/sysbus.h" 38 39typedef struct { 40 DeviceState *dev; 41 const char *devname; 42 char *name; 43 unsigned int level; 44 bool set; 45} IRQInterceptState; 46 47// static void trace_irq_handler(void *opaque, int n, int level) 48// { 49// IRQInterceptState *iis = opaque; 50// uint32_t flags = ETRACE_EVU64_F_NONE; 51 52// if (iis->set && (iis->level == level)) { 53// return; 54// } 55 56// if (iis->set) { 57// flags = ETRACE_EVU64_F_PREV_VAL; 58// } 59// etrace_event_u64(&qemu_etracer, -1, flags, iis->devname, 60// iis->name, level, iis->level); 61// iis->set = true; 62// iis->level = level; 63// } 64 65// static void intercept_irq(DeviceState *dev, char *irq_name, int i, char *name) 66// { 67// IRQInterceptState *iis; 68// qemu_irq new; 69 70// iis = g_new0(IRQInterceptState, 1); 71// iis->devname = object_get_canonical_path(OBJECT(dev)); 72// iis->name = name; 73// new = qemu_allocate_irq(trace_irq_handler, iis, 0); 74// object_property_add_child(OBJECT(dev), name, OBJECT(new), NULL); 75// qdev_connect_gpio_out_named(dev, irq_name, i, new); 76// } 77 78static void sysbus_init(SysBusDevice *dev) 79{ 80 /* FIXME: restore service */ 81 // unsigned int i = 0; 82 83 // for (i = 0; i < dev->num_irq; i++) { 84 // char *name; 85 // int r; 86 // /* Unfortunately there is no sysbus_get_irq() :( */ 87 // char *irq_name = g_strdup_printf(SYSBUS_DEVICE_GPIO_IRQ "-%d", i); 88 // qemu_irq irq = qdev_get_gpio_out_named(DEVICE(dev), irq_name, 0); 89 90 // if (!irq) { 91 // g_free(irq_name); 92 // continue; 93 // } 94 95 // r = asprintf(&name, "irq[%u]", i); 96 // assert(r > 0); 97 // intercept_irq(DEVICE(dev), irq_name, i, name); 98 // g_free(irq_name); 99 // } 100} 101 102static void dev_named_init(DeviceState *dev, NamedGPIOList *l) 103{ 104 // unsigned int i = 0; 105 106 // if (!l->num_out) { 107 // return; 108 // } 109 110 // for (i = 0; i < l->num_out; i++) { 111 // char *name; 112 // int r; 113 114 // if (!l->out[i]) { 115 // continue; 116 // } 117 118 // r = asprintf(&name, "%s[%u]", l->name ? l->name : "gpio-out", i); 119 // assert(r > 0); 120 // intercept_irq(DEVICE(dev), l->name, i, name); 121 // } 122} 123 124static int dev_init(Object *obj, void *opaque) 125{ 126 SysBusDevice *sbd = 127 (SysBusDevice *)object_dynamic_cast(obj, TYPE_SYS_BUS_DEVICE); 128 DeviceState *dev = (DeviceState *)object_dynamic_cast(obj, TYPE_DEVICE); 129 NamedGPIOList *l; 130 131 if (sbd) { 132 sysbus_init(sbd); 133 } 134 135 if (dev) { 136 QLIST_FOREACH(l, &dev->gpios, node) { 137 dev_named_init(dev, l); 138 } 139 } 140 return 0; 141} 142 143void qemu_etrace_gpio_init(void) 144{ 145 object_child_foreach_recursive(object_get_root(), dev_init, NULL); 146} 147 148#endif 149