From patchwork Mon May 12 01:03:21 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Crosthwaite X-Patchwork-Id: 347845 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id E40C2140082 for ; Mon, 12 May 2014 11:06:06 +1000 (EST) Received: from localhost ([::1]:34819 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Wjegu-00026r-Qu for incoming@patchwork.ozlabs.org; Sun, 11 May 2014 21:06:04 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58685) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WjegM-0001KL-9u for qemu-devel@nongnu.org; Sun, 11 May 2014 21:05:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WjegE-0001iu-Fu for qemu-devel@nongnu.org; Sun, 11 May 2014 21:05:30 -0400 Received: from mail-qa0-f53.google.com ([209.85.216.53]:63139) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WjegE-0001iD-Bn for qemu-devel@nongnu.org; Sun, 11 May 2014 21:05:22 -0400 Received: by mail-qa0-f53.google.com with SMTP id ih12so6322933qab.40 for ; Sun, 11 May 2014 18:05:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=QzDetxKFHlf5B1WT/ttFoaL43Y0Z8KPgWhE8lT4XpJk=; b=PJMzI7z86WPWpCsf/BmiGW6z2A9nK6qJvPGHV0rhnL8MRILHFo9PFUabTMkxrYUCFW 1cR804gq52DWyIkuDFY9ARs0MpZO4bD11hH5GxmRPtH73azEGOfIF1LNVnVMxQL9j8Nq DsSOzMAJNCYTBReAHucMqhv1binyRpMxbWaS6rPzC2x2IBaThwDYX/DfCxp+2BDonk1d cW9Vm4+WvvF+Zwkrj6PZIhcBpEyLhAuxK0FGv35FrIRZzuzfwMxDzhFdAx0Vy9Ni5IFY Ft174fibk2GbuwoqiguoUm5wjjml5AEakG38ORQs//+uuZOff1F/L5/w8MWdReiAY+kM Zj/A== X-Gm-Message-State: ALoCoQm3QBbqwvtzJCtyT878lw9/GU3Lv+svztZ059GsP92lrzAZBNQA07Lgo2UnIQ3BeekWD4zT X-Received: by 10.140.109.70 with SMTP id k64mr32434271qgf.92.1399856722074; Sun, 11 May 2014 18:05:22 -0700 (PDT) Received: from localhost ([149.199.62.254]) by mx.google.com with ESMTPSA id q16sm6244385qga.42.2014.05.11.18.05.21 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Sun, 11 May 2014 18:05:21 -0700 (PDT) From: Peter Crosthwaite To: qemu-devel@nongnu.org Date: Sun, 11 May 2014 18:03:21 -0700 Message-Id: X-Mailer: git-send-email 1.9.2.1.g06c4abd In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.85.216.53 Cc: peter.maydell@linaro.org, edgari@xilinx.com, alistai@xilinx.com, afaerber@suse.de Subject: [Qemu-devel] [PATCH v4 1/2] qdev: Implement named GPIOs X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Implement named GPIOs on the Device layer. Listifies the existing GPIOs stuff using string keys. Legacy un-named GPIOs are preserved by using a NULL name string - they are just a single matchable element in the name list. Signed-off-by: Peter Crosthwaite Reviewed-by: Peter Maydell --- Changed since v3 (PMM review): Added finalize() cleanup of all allocated mem Remove %s printf of NULL in info qtree Restricted Qtest to unnamed GPIOs only Changed since v2: Reordered fn args to be name-before-number (PMM review) changed since v1: Use QLIST instead of RYO list implementation (AF review) Reorder struct fields for consistency hw/core/qdev.c | 82 ++++++++++++++++++++++++++++++++++++++++++++------ include/hw/qdev-core.h | 24 ++++++++++++--- qdev-monitor.c | 16 +++++++--- qtest.c | 19 +++++++++--- 4 files changed, 117 insertions(+), 24 deletions(-) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 936eae6..8efeb04 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -312,30 +312,82 @@ BusState *qdev_get_parent_bus(DeviceState *dev) return dev->parent_bus; } +static NamedGPIOList *qdev_get_named_gpio_list(DeviceState *dev, + const char *name) +{ + NamedGPIOList *ngl; + + QLIST_FOREACH(ngl, &dev->gpios, node) { + /* NULL is a valid and matchable name, otherwise do a normal + * strcmp match. + */ + if ((!ngl->name && !name) || + (name && ngl->name && !strcmp(name, ngl->name))) { + return ngl; + } + } + + ngl = g_malloc0(sizeof(*ngl)); + ngl->name = g_strdup(name); + QLIST_INSERT_HEAD(&dev->gpios, ngl, node); + return ngl; +} + +void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler, + const char *name, int n) +{ + NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name); + + gpio_list->in = qemu_extend_irqs(gpio_list->in, gpio_list->num_in, handler, + dev, n); + gpio_list->num_in += n; +} + void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) { - dev->gpio_in = qemu_extend_irqs(dev->gpio_in, dev->num_gpio_in, handler, - dev, n); - dev->num_gpio_in += n; + qdev_init_gpio_in_named(dev, handler, NULL, n); +} + +void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins, + const char *name, int n) +{ + NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name); + + assert(gpio_list->num_out == 0); + gpio_list->num_out = n; + gpio_list->out = pins; } void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n) { - assert(dev->num_gpio_out == 0); - dev->num_gpio_out = n; - dev->gpio_out = pins; + qdev_init_gpio_out_named(dev, pins, NULL, n); +} + +qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n) +{ + NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name); + + assert(n >= 0 && n < gpio_list->num_in); + return gpio_list->in[n]; } qemu_irq qdev_get_gpio_in(DeviceState *dev, int n) { - assert(n >= 0 && n < dev->num_gpio_in); - return dev->gpio_in[n]; + return qdev_get_gpio_in_named(dev, NULL, n); +} + +void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, + qemu_irq pin) +{ + NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name); + + assert(n >= 0 && n < gpio_list->num_out); + gpio_list->out[n] = pin; } void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin) { - assert(n >= 0 && n < dev->num_gpio_out); - dev->gpio_out[n] = pin; + qdev_connect_gpio_out_named(dev, NULL, n, pin); } BusState *qdev_get_child_bus(DeviceState *dev, const char *name) @@ -844,6 +896,7 @@ static void device_initfn(Object *obj) object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS, (Object **)&dev->parent_bus, NULL, 0, &error_abort); + QLIST_INIT(&dev->gpios); } static void device_post_init(Object *obj) @@ -854,10 +907,19 @@ static void device_post_init(Object *obj) /* Unlink device from bus and free the structure. */ static void device_finalize(Object *obj) { + NamedGPIOList *ngl, *next; + DeviceState *dev = DEVICE(obj); if (dev->opts) { qemu_opts_del(dev->opts); } + + QLIST_FOREACH_SAFE(ngl, &dev->gpios, node, next) { + QLIST_REMOVE(ngl, node); + qemu_free_irqs(ngl->in); + g_free(ngl->name); + g_free(ngl); + } } static void device_class_base_init(ObjectClass *class, void *data) diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index dbe473c..ae31575 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -131,6 +131,17 @@ typedef struct DeviceClass { const char *bus_type; } DeviceClass; +typedef struct NamedGPIOList NamedGPIOList; + +struct NamedGPIOList { + char *name; + qemu_irq *in; + int num_in; + qemu_irq *out; + int num_out; + QLIST_ENTRY(NamedGPIOList) node; +}; + /** * DeviceState: * @realized: Indicates whether the device has been fully constructed. @@ -148,10 +159,7 @@ struct DeviceState { QemuOpts *opts; int hotplugged; BusState *parent_bus; - int num_gpio_out; - qemu_irq *gpio_out; - int num_gpio_in; - qemu_irq *gpio_in; + QLIST_HEAD(, NamedGPIOList) gpios; QLIST_HEAD(, BusState) child_bus; int num_child_bus; int instance_id_alias; @@ -252,7 +260,11 @@ void qdev_machine_creation_done(void); bool qdev_machine_modified(void); qemu_irq qdev_get_gpio_in(DeviceState *dev, int n); +qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n); + void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin); +void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, + qemu_irq pin); BusState *qdev_get_child_bus(DeviceState *dev, const char *name); @@ -262,6 +274,10 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name); /* GPIO inputs also double as IRQ sinks. */ void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n); void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n); +void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler, + const char *name, int n); +void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins, + const char *name, int n); BusState *qdev_get_parent_bus(DeviceState *dev); diff --git a/qdev-monitor.c b/qdev-monitor.c index 02cbe43..f87f3d8 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -613,14 +613,20 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent) { ObjectClass *class; BusState *child; + NamedGPIOList *ngl; + qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)), dev->id ? dev->id : ""); indent += 2; - if (dev->num_gpio_in) { - qdev_printf("gpio-in %d\n", dev->num_gpio_in); - } - if (dev->num_gpio_out) { - qdev_printf("gpio-out %d\n", dev->num_gpio_out); + QLIST_FOREACH(ngl, &dev->gpios, node) { + if (ngl->num_in) { + qdev_printf("gpio-in \"%s\" %d\n", ngl->name ? ngl->name : "", + ngl->num_in); + } + if (ngl->num_out) { + qdev_printf("gpio-out \"%s\" %d\n", ngl->name ? ngl->name : "", + ngl->num_out); + } } class = object_get_class(OBJECT(dev)); do { diff --git a/qtest.c b/qtest.c index 2aba20d..b6b60d5 100644 --- a/qtest.c +++ b/qtest.c @@ -233,7 +233,8 @@ static void qtest_process_command(CharDriverState *chr, gchar **words) g_assert(command); if (strcmp(words[0], "irq_intercept_out") == 0 || strcmp(words[0], "irq_intercept_in") == 0) { - DeviceState *dev; + DeviceState *dev; + NamedGPIOList *ngl; g_assert(words[1]); dev = DEVICE(object_resolve_path(words[1], NULL)); @@ -253,10 +254,18 @@ static void qtest_process_command(CharDriverState *chr, gchar **words) return; } - if (words[0][14] == 'o') { - qemu_irq_intercept_out(&dev->gpio_out, qtest_irq_handler, dev->num_gpio_out); - } else { - qemu_irq_intercept_in(dev->gpio_in, qtest_irq_handler, dev->num_gpio_in); + QLIST_FOREACH(ngl, &dev->gpios, node) { + /* We dont support intercept of named GPIOs yet */ + if (ngl->name) { + continue; + } + if (words[0][14] == 'o') { + qemu_irq_intercept_out(&ngl->out, qtest_irq_handler, + ngl->num_out); + } else { + qemu_irq_intercept_in(ngl->in, qtest_irq_handler, + ngl->num_in); + } } irq_intercept_dev = dev; qtest_send_prefix(chr);