summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2011-11-28 10:28:23 +0100
committerDaniel Hellstrom <daniel@gaisler.com>2015-04-17 01:10:16 +0200
commit219d4045e76f3de36fca7d67ef79dbe6cca299b5 (patch)
treead71effa8c5d906e04c1dc8da3b816a2e09397cc /cpukit
parentLIBPCI: added DRVMGR model for PCI bus (diff)
downloadrtems-219d4045e76f3de36fca7d67ef79dbe6cca299b5.tar.bz2
DRVMGR: added drvmgr shell command
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/libmisc/Makefile.am2
-rw-r--r--cpukit/libmisc/shell/main_drvmgr.c426
-rw-r--r--cpukit/libmisc/shell/shellconfig.h9
3 files changed, 436 insertions, 1 deletions
diff --git a/cpukit/libmisc/Makefile.am b/cpukit/libmisc/Makefile.am
index 47db7e96ad..436986a1c5 100644
--- a/cpukit/libmisc/Makefile.am
+++ b/cpukit/libmisc/Makefile.am
@@ -111,7 +111,7 @@ libshell_a_SOURCES = shell/cat_file.c shell/cmds.c shell/internal.h \
shell/main_lsof.c shell/main_edit.c \
shell/main_blkstats.c shell/main_rtrace.c \
shell/shell-wait-for-input.c \
- shell/main_pci.c
+ shell/main_drvmgr.c shell/main_pci.c
libshell_a_SOURCES += shell/main_cmdls.c
libshell_a_SOURCES += shell/main_cmdchown.c
libshell_a_SOURCES += shell/main_cmdchmod.c
diff --git a/cpukit/libmisc/shell/main_drvmgr.c b/cpukit/libmisc/shell/main_drvmgr.c
new file mode 100644
index 0000000000..a93f6e0f58
--- /dev/null
+++ b/cpukit/libmisc/shell/main_drvmgr.c
@@ -0,0 +1,426 @@
+/*
+ * DRVMGR Command Implementation
+ *
+ * COPYRIGHT (c) 2010.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <drvmgr/drvmgr.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+static void usage(void);
+
+static void *get_obj_adr(char *arg)
+{
+ unsigned long obj_adr;
+
+ obj_adr = strtoul(arg, NULL, 16);
+ if (obj_adr == ULONG_MAX || obj_adr == 0) {
+ puts(" Not a valid ID");
+ return NULL;
+ }
+
+ return (void *)obj_adr;
+}
+
+/* General info, root bus, number of devices etc. */
+static void show_drvmgr_info(void)
+{
+ drvmgr_summary();
+ drvmgr_print_devs(PRINT_DEVS_ALL);
+}
+
+static int shell_drvmgr_topo(int argc, char *argv[])
+{
+ drvmgr_print_topo();
+ return 0;
+}
+
+static int shell_drvmgr_short(int argc, char *argv[])
+{
+ void *obj;
+
+ if (argc < 2)
+ return -1;
+ if (argc < 3) {
+ /* All Devices */
+ drvmgr_info_drvs(0);
+ drvmgr_info_buses(0);
+ drvmgr_info_devs(OPTION_DEV_GENINFO);
+ return 0;
+ }
+
+ /* Get ID from string */
+ obj = get_obj_adr(argv[2]);
+ if (!obj)
+ return -3;
+
+ drvmgr_info(obj, OPTION_DEV_GENINFO);
+
+ return 0;
+}
+
+static int shell_drvmgr_info(int argc, char *argv[])
+{
+ void *obj;
+
+ if (argc < 2)
+ return -1;
+ if (argc < 3) {
+ /* All Drivers, Buses and Devices */
+ drvmgr_info_drvs(OPTION_INFO_ALL);
+ drvmgr_info_buses(OPTION_INFO_ALL);
+ drvmgr_info_devs(OPTION_INFO_ALL);
+ return 0;
+ }
+
+ /* Get ID from string */
+ obj = get_obj_adr(argv[2]);
+ if (!obj)
+ return -3;
+
+ drvmgr_info(obj, OPTION_INFO_ALL);
+
+ return 0;
+}
+
+static int shell_drvmgr_remove(int argc, char *argv[])
+{
+ puts(" Not implemented");
+ return 0;
+}
+
+static int shell_drvmgr_parent(int argc, char *argv[])
+{
+ void *obj;
+ int obj_type;
+ struct drvmgr_dev *dev;
+ struct drvmgr_bus *bus;
+
+ /* Get ID from string */
+ if (argc < 3)
+ return -2;
+ obj = get_obj_adr(argv[2]);
+ if (!obj)
+ return -3;
+
+ obj_type = *(int *)obj;
+ if (obj_type == DRVMGR_OBJ_BUS) {
+ bus = obj;
+ if (!bus->dev) {
+ puts(" bus has no bridge device");
+ } else if(!bus->dev->parent) {
+ puts(" bridge device has no parent");
+ } else {
+ dev = bus->dev;
+ printf(" BUSID=%p\n", dev->parent);
+ }
+ } else if (obj_type == DRVMGR_OBJ_DEV) {
+ dev = obj;
+ if (!dev->parent) {
+ puts(" device has no parent bus");
+ } else {
+ printf(" BUSID=%p\n", dev->parent);
+ }
+ } else {
+ puts(" ID is not a device or bus");
+ return 1;
+ }
+
+ return 0;
+}
+
+static void shell_drvmgr_print_key_array(struct drvmgr_key *keys)
+{
+ struct drvmgr_key *key;
+ static char *type_strs[4] = {"UNKNOWN","INTEGER","STRING ","POINTER"};
+ int type;
+ union drvmgr_key_value *val;
+
+ if (keys == NULL) {
+ printf(" DEV HAS NO KEYS\n");
+ return;
+ }
+
+ key = &keys[0];
+ while (key->key_type != KEY_TYPE_NONE) {
+ if (key->key_type > KEY_TYPE_POINTER)
+ type = 0;
+ else
+ type = key->key_type;
+ printf(" NAME=%-14s TYPE=%s VALUE=", key->key_name, type_strs[type]);
+ val = &key->key_value;
+ switch (type) {
+ default:
+ case 0:
+ case KEY_TYPE_INT:
+ printf("0x%x (%d)\n", val->i, val->i);
+ break;
+ case KEY_TYPE_STRING:
+ printf("%s\n", val->str);
+ break;
+ case KEY_TYPE_POINTER:
+ printf("%p\n", val->ptr);
+ break;
+ }
+ key++;
+ }
+}
+
+static void shell_drvmgr_print_res_array(struct drvmgr_drv_res *resources)
+{
+ struct drvmgr_drv_res *res = &resources[0];
+ struct drvmgr_drv *drv;
+ char *drv_name;
+
+ while (res->drv_id) {
+ /* Find Driver in order to print name of driver */
+ drv = drvmgr_drv_by_id(res->drv_id);
+ if (drv && drv->name)
+ drv_name = drv->name;
+ else
+ drv_name = "UNKNOWN";
+ printf(" RESOURCES FOR DEVICE[%02d] DRIVER[0x%llx (%s)]\n",
+ res->minor_bus, res->drv_id, drv_name);
+ shell_drvmgr_print_key_array(res->keys);
+ res++;
+ }
+}
+
+static int shell_drvmgr_res(int argc, char *argv[])
+{
+ void *obj;
+ int obj_type;
+ struct drvmgr_dev *dev;
+ struct drvmgr_bus *bus;
+ struct drvmgr_key *keys;
+ struct drvmgr_bus_res *lst;
+ int i;
+
+ /* Get ID from string */
+ if (argc < 3)
+ return -2;
+ obj = get_obj_adr(argv[2]);
+ if (!obj)
+ return -3;
+
+ obj_type = *(int *)obj;
+ if (obj_type == DRVMGR_OBJ_BUS) {
+ bus = obj;
+ lst = bus->reslist;
+ if (lst == NULL) {
+ puts(" BUS does not have resources\n");
+ return 0;
+ }
+ i = 0;
+ while (lst) {
+ printf(" -- RESOURCES ARRAY %d --\n", i);
+ shell_drvmgr_print_res_array(lst->resource);
+ puts("");
+ i++;
+ lst = lst->next;
+ }
+ } else if (obj_type == DRVMGR_OBJ_DEV) {
+ dev = obj;
+ if (dev->drv == NULL) {
+ puts(" DEVICE has no driver ==> resources not available\n");
+ return 0;
+ }
+ drvmgr_keys_get(dev, &keys);
+ if (keys == NULL) {
+ puts(" DEVICE does not have resources\n");
+ return 0;
+ }
+ shell_drvmgr_print_key_array(keys);
+ } else {
+ puts(" ID is not a device or bus");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int shell_drvmgr_buses(int argc, char *argv[])
+{
+ drvmgr_info_buses(OPTION_INFO_ALL);
+ return 0;
+}
+
+static int shell_drvmgr_devs(int argc, char *argv[])
+{
+ drvmgr_info_devs(OPTION_INFO_ALL);
+ return 0;
+}
+
+static int shell_drvmgr_drvs(int argc, char *argv[])
+{
+ drvmgr_info_drvs(OPTION_INFO_ALL);
+ return 0;
+}
+
+static int shell_drvmgr_mem(int argc, char *argv[])
+{
+ drvmgr_print_mem();
+ return 0;
+}
+
+static int shell_drvmgr_translate(int argc, char *argv[])
+{
+ int rc, rev, up, obj_type;
+ void *obj, *dst;
+ unsigned long src, tmp;
+
+ if (argc != 5)
+ return -1;
+
+ obj = get_obj_adr(argv[2]);
+ if (!obj)
+ return -3;
+
+ obj_type = *(int *)obj;
+ if (obj_type != DRVMGR_OBJ_DEV) {
+ puts(" ID is not a device\n");
+ return 0;
+ }
+
+ tmp = strtoul(argv[3], NULL, 0);
+ if (tmp > 3) {
+ puts(" Not a valid option OPT, only [0..3] is valid");
+ return 0;
+ }
+ rev = tmp & DRVMGR_TR_REVERSE;
+ up = tmp & DRVMGR_TR_PATH;
+
+ src = strtoul(argv[4], NULL, 0);
+ if (src == ULONG_MAX && errno == ERANGE) {
+ puts(" Not a valid source address");
+ return 0;
+ }
+
+ rc = drvmgr_translate((struct drvmgr_dev *)obj, up | rev, (void *)src, &dst);
+ if (rc == 0)
+ printf(" Address %p could not be translated\n", (void *)src);
+ else if (rc == 0xffffffff)
+ printf(" %p => %p (no translation required)\n", (void *)src, dst);
+ else
+ printf(" %p => %p (map size 0x%x)\n", (void *)src, dst, rc);
+
+ return 0;
+}
+
+static const char drvmgr_usage_str[] =
+ " usage:\n"
+ " drvmgr buses List bus specfic information on all buses\n"
+ " drvmgr devs List general and driver specfic information\n"
+ " about all devices\n"
+ " drvmgr drvs List driver specfic information on all drivers\n"
+ " drvmgr info [ID] List general and driver specfic information\n"
+ " about all devices or one device, bus or driver\n"
+ " drvmgr mem Dynamically memory usage\n"
+ " drvmgr parent ID Short info about parent bus of a device\n"
+ " drvmgr remove ID Remove a device or a bus\n"
+ " drvmgr res ID List Resources of a device or bus\n"
+ " drvmgr short [ID] Short info about all devices/buses or one\n"
+ " device/bus\n"
+ " drvmgr topo Show bus topology with all devices\n"
+ " drvmgr tr ID OPT ADR Translate ADR down(0)/up(1) -streams (OPT bit 1) in\n"
+ " std(0)/reverse(1) (OPT bit 0) direction for device\n"
+ " drvmgr --help\n";
+
+static void usage(void)
+{
+ puts(drvmgr_usage_str);
+}
+
+static int shell_drvmgr_usage(int argc, char *argv[])
+{
+ usage();
+ return 0;
+}
+
+struct shell_drvmgr_modifier {
+ char *name;
+ int (*func)(int argc, char *argv[]);
+};
+
+#define MODIFIER_NUM 12
+static struct shell_drvmgr_modifier shell_drvmgr_modifiers[MODIFIER_NUM] =
+{
+ {"buses", shell_drvmgr_buses},
+ {"devs", shell_drvmgr_devs},
+ {"drvs", shell_drvmgr_drvs},
+ {"info", shell_drvmgr_info},
+ {"mem", shell_drvmgr_mem},
+ {"parent", shell_drvmgr_parent},
+ {"remove", shell_drvmgr_remove},
+ {"res", shell_drvmgr_res},
+ {"short", shell_drvmgr_short},
+ {"topo", shell_drvmgr_topo},
+ {"tr", shell_drvmgr_translate},
+ {"--help", shell_drvmgr_usage},
+};
+
+static struct shell_drvmgr_modifier *shell_drvmgr_find_modifier(char *name)
+{
+ struct shell_drvmgr_modifier *mod;
+ int i;
+
+ if (name == NULL)
+ return NULL;
+
+ for (i=0, mod=&shell_drvmgr_modifiers[0]; i<MODIFIER_NUM; i++, mod++) {
+ if (strcmp(name, mod->name) == 0)
+ return mod;
+ }
+
+ return NULL;
+}
+
+static int rtems_shell_main_drvmgr(
+ int argc,
+ char *argv[]
+)
+{
+ struct shell_drvmgr_modifier *mod;
+ int rc;
+
+ if (argc < 2) {
+ show_drvmgr_info();
+ rc = 0;
+ } else if ((mod=shell_drvmgr_find_modifier(argv[1])) != NULL) {
+ rc = mod->func(argc, argv);
+ } else {
+ rc = -1;
+ }
+
+ if (rc < 0) {
+ printf(" invalid argument\n");
+ usage();
+ }
+
+ return rc;
+}
+
+rtems_shell_cmd_t rtems_shell_DRVMGR_Command = {
+ "drvmgr", /* name */
+ drvmgr_usage_str, /* usage */
+ "system", /* topic */
+ rtems_shell_main_drvmgr, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/shellconfig.h b/cpukit/libmisc/shell/shellconfig.h
index c1f361b7be..5e4f03f8fa 100644
--- a/cpukit/libmisc/shell/shellconfig.h
+++ b/cpukit/libmisc/shell/shellconfig.h
@@ -98,6 +98,7 @@ extern rtems_shell_cmd_t rtems_shell_RTRACE_Command;
/*
* Extern for System commands
*/
+extern rtems_shell_cmd_t rtems_shell_DRVMGR_Command;
extern rtems_shell_cmd_t rtems_shell_PCI_Command;
extern rtems_shell_cmd_t * const rtems_shell_Initial_commands[];
@@ -517,6 +518,14 @@ extern rtems_shell_alias_t * const rtems_shell_Initial_aliases[];
/*
* System related commands
*/
+ #if defined(RTEMS_DRVMGR_STARTUP) || defined(CONFIGURE_SHELL_COMMAND_DRVMGR)
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_DRVMGR)) || \
+ defined(CONFIGURE_SHELL_COMMAND_DRVMGR)
+ &rtems_shell_DRVMGR_Command,
+ #endif
+ #endif
+
#if defined(RTEMS_PCI_CONFIG_LIB)
#if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
!defined(CONFIGURE_SHELL_NO_COMMAND_PCI)) || \