From 219d4045e76f3de36fca7d67ef79dbe6cca299b5 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Mon, 28 Nov 2011 10:28:23 +0100 Subject: DRVMGR: added drvmgr shell command --- cpukit/libmisc/Makefile.am | 2 +- cpukit/libmisc/shell/main_drvmgr.c | 426 +++++++++++++++++++++++++++++++++++++ cpukit/libmisc/shell/shellconfig.h | 9 + 3 files changed, 436 insertions(+), 1 deletion(-) create mode 100644 cpukit/libmisc/shell/main_drvmgr.c (limited to 'cpukit') 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 +#include +#include +#include +#include + +#include +#include +#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]; iname) == 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)) || \ -- cgit v1.2.3