[PATCH 011/111] DRVMGR: added drvmgr shell command

Daniel Hellstrom daniel at gaisler.com
Thu Feb 26 16:38:13 UTC 2015


---
 cpukit/libmisc/Makefile.am         |    2 +-
 cpukit/libmisc/shell/main_drvmgr.c |  426 ++++++++++++++++++++++++++++++++++++
 cpukit/libmisc/shell/shellconfig.h |    9 +
 3 files changed, 436 insertions(+), 1 deletions(-)
 create mode 100644 cpukit/libmisc/shell/main_drvmgr.c

diff --git a/cpukit/libmisc/Makefile.am b/cpukit/libmisc/Makefile.am
index 217b13e..ac7b0ad 100644
--- a/cpukit/libmisc/Makefile.am
+++ b/cpukit/libmisc/Makefile.am
@@ -110,7 +110,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/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 0000000..a93f6e0
--- /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 3024ac1..f360fae 100644
--- a/cpukit/libmisc/shell/shellconfig.h
+++ b/cpukit/libmisc/shell/shellconfig.h
@@ -96,6 +96,7 @@ extern rtems_shell_cmd_t rtems_shell_MALLOC_INFO_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[];
@@ -501,6 +502,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)) || \
-- 
1.7.0.4




More information about the devel mailing list