Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:19

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * DRVMGR Command Implementation
0005  *
0006  * COPYRIGHT (c) 2010.
0007  * Cobham Gaisler AB.
0008  *
0009  * Redistribution and use in source and binary forms, with or without
0010  * modification, are permitted provided that the following conditions
0011  * are met:
0012  * 1. Redistributions of source code must retain the above copyright
0013  *    notice, this list of conditions and the following disclaimer.
0014  * 2. Redistributions in binary form must reproduce the above copyright
0015  *    notice, this list of conditions and the following disclaimer in the
0016  *    documentation and/or other materials provided with the distribution.
0017  *
0018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0022  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0026  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0028  * POSSIBILITY OF SUCH DAMAGE.
0029  */
0030 
0031 #ifdef HAVE_CONFIG_H
0032 #include "config.h"
0033 #endif
0034 
0035 #include <inttypes.h>
0036 #include <limits.h>
0037 #include <stdlib.h>
0038 #include <stdio.h>
0039 #include <string.h>
0040 #include <errno.h>
0041 #include <drvmgr/drvmgr.h>
0042 
0043 #include <rtems.h>
0044 #include <rtems/shell.h>
0045 #include "internal.h"
0046 
0047 static void usage(void);
0048 
0049 static void *get_obj_adr(char *arg)
0050 {
0051   unsigned long obj_adr;
0052 
0053   obj_adr = strtoul(arg, NULL, 16);
0054   if (obj_adr == ULONG_MAX || obj_adr == 0) {
0055     puts(" Not a valid ID");
0056     return NULL;
0057   }
0058 
0059   return (void *)obj_adr;
0060 }
0061 
0062 /* General info, root bus, number of devices etc. */
0063 static void show_drvmgr_info(void)
0064 {
0065   drvmgr_summary();
0066   drvmgr_print_devs(PRINT_DEVS_ALL);
0067 }
0068 
0069 static int shell_drvmgr_topo(int argc, char *argv[])
0070 {
0071   drvmgr_print_topo();
0072   return 0;
0073 }
0074 
0075 static int shell_drvmgr_short(int argc, char *argv[])
0076 {
0077   void *obj;
0078 
0079   if (argc < 2)
0080     return -1;
0081   if (argc < 3) {
0082     /* All Devices */
0083     drvmgr_info_drvs(0);
0084     drvmgr_info_buses(0);
0085     drvmgr_info_devs(OPTION_DEV_GENINFO);
0086     return 0;
0087   }
0088 
0089   /* Get ID from string */
0090   obj = get_obj_adr(argv[2]);
0091   if (!obj)
0092     return -3;
0093 
0094   drvmgr_info(obj, OPTION_DEV_GENINFO);
0095 
0096   return 0;
0097 }
0098 
0099 static int shell_drvmgr_info(int argc, char *argv[])
0100 {
0101   void *obj;
0102 
0103   if (argc < 2)
0104     return -1;
0105   if (argc < 3) {
0106     /* All Drivers, Buses and Devices */
0107     drvmgr_info_drvs(OPTION_INFO_ALL);
0108     drvmgr_info_buses(OPTION_INFO_ALL);
0109     drvmgr_info_devs(OPTION_INFO_ALL);
0110     return 0;
0111   }
0112 
0113   /* Get ID from string */
0114   obj = get_obj_adr(argv[2]);
0115   if (!obj)
0116     return -3;
0117 
0118   drvmgr_info(obj, OPTION_INFO_ALL);
0119 
0120   return 0;
0121 }
0122 
0123 static int shell_drvmgr_remove(int argc, char *argv[])
0124 {
0125   puts(" Not implemented");
0126   return 0;
0127 }
0128 
0129 static int shell_drvmgr_parent(int argc, char *argv[])
0130 {
0131   void *obj;
0132   int obj_type;
0133   struct drvmgr_dev *dev;
0134   struct drvmgr_bus *bus;
0135 
0136   /* Get ID from string */
0137   if (argc < 3)
0138     return -2;
0139   obj = get_obj_adr(argv[2]);
0140   if (!obj)
0141     return -3;
0142 
0143   obj_type = *(int *)obj;
0144   if (obj_type == DRVMGR_OBJ_BUS) {
0145     bus = obj;
0146     if (!bus->dev) {
0147       puts(" bus has no bridge device");
0148     } else if(!bus->dev->parent) {
0149       puts(" bridge device has no parent");
0150     } else {
0151       dev = bus->dev;
0152       printf(" BUSID=%p\n", dev->parent);
0153     }
0154   } else if (obj_type == DRVMGR_OBJ_DEV) {
0155     dev = obj;
0156     if (!dev->parent) {
0157       puts(" device has no parent bus");
0158     } else {
0159       printf(" BUSID=%p\n", dev->parent);
0160     }
0161   } else {
0162     puts(" ID is not a device or bus");
0163     return 1;
0164   }
0165 
0166   return 0;
0167 }
0168 
0169 static void shell_drvmgr_print_key_array(struct drvmgr_key *keys)
0170 {
0171   struct drvmgr_key *key;
0172   static char *type_strs[4] = {"UNKNOWN","INTEGER","STRING ","POINTER"};
0173   enum drvmgr_kt type;
0174   union drvmgr_key_value *val;
0175 
0176   if (keys == NULL) {
0177     printf("  DEV HAS NO KEYS\n");
0178     return;
0179   }
0180 
0181   key = &keys[0];
0182   while (key->key_type != DRVMGR_KT_NONE) {
0183     if (key->key_type > DRVMGR_KT_POINTER)
0184       type = DRVMGR_KT_NONE;
0185     else
0186       type = key->key_type;
0187     printf("  NAME=%-14s TYPE=%s  VALUE=", key->key_name, type_strs[type]);
0188     val = &key->key_value;
0189     switch (type) {
0190       default:
0191       case DRVMGR_KT_NONE:
0192       case DRVMGR_KT_INT:
0193         printf("0x%x (%d)\n", val->i, val->i);
0194         break;
0195       case DRVMGR_KT_STRING:
0196         printf("%s\n", val->str);
0197         break;
0198       case DRVMGR_KT_POINTER:
0199         printf("%p\n", val->ptr);
0200         break;
0201     }
0202     key++;
0203   }
0204 }
0205 
0206 static void shell_drvmgr_print_res_array(struct drvmgr_drv_res *resources)
0207 {
0208   struct drvmgr_drv_res *res = &resources[0];
0209   struct drvmgr_drv *drv;
0210   char *drv_name;
0211 
0212   while (res->drv_id) {
0213     /* Find Driver in order to print name of driver */
0214     drv = drvmgr_drv_by_id(res->drv_id);
0215     if (drv && drv->name)
0216       drv_name = drv->name;
0217     else
0218       drv_name = "UNKNOWN";
0219     printf(" RESOURCES FOR DEVICE[%02d] DRIVER[0x%" PRIu64 " (%s)]\n",
0220             res->minor_bus, res->drv_id, drv_name);
0221     shell_drvmgr_print_key_array(res->keys);
0222     res++;
0223   }
0224 }
0225 
0226 static int shell_drvmgr_res(int argc, char *argv[])
0227 {
0228   void *obj;
0229   int obj_type;
0230   struct drvmgr_dev *dev;
0231   struct drvmgr_bus *bus;
0232   struct drvmgr_key *keys;
0233   struct drvmgr_bus_res *lst;
0234   int i;
0235 
0236   /* Get ID from string */
0237   if (argc < 3)
0238     return -2;
0239   obj = get_obj_adr(argv[2]);
0240   if (!obj)
0241     return -3;
0242 
0243   obj_type = *(int *)obj;
0244   if (obj_type == DRVMGR_OBJ_BUS) {
0245     bus = obj;
0246     lst = bus->reslist;
0247     if (lst == NULL) {
0248       puts(" BUS does not have resources\n");
0249       return 0;
0250     }
0251     i = 0;
0252     while (lst) {
0253       printf(" -- RESOURCES ARRAY %d --\n", i);
0254       shell_drvmgr_print_res_array(lst->resource);
0255       puts("");
0256       i++;
0257       lst = lst->next;
0258     }
0259   } else if (obj_type == DRVMGR_OBJ_DEV) {
0260     dev = obj;
0261     if (dev->drv == NULL) {
0262       puts(" DEVICE has no driver ==> resources not available\n");
0263       return 0;
0264     }
0265     drvmgr_keys_get(dev, &keys);
0266     if (keys == NULL) {
0267       puts(" DEVICE does not have resources\n");
0268       return 0;
0269     }
0270     shell_drvmgr_print_key_array(keys);
0271   } else {
0272     puts(" ID is not a device or bus");
0273     return 1;
0274   }
0275 
0276   return 0;
0277 }
0278 
0279 static int shell_drvmgr_buses(int argc, char *argv[])
0280 {
0281   drvmgr_info_buses(OPTION_INFO_ALL);
0282   return 0;
0283 }
0284 
0285 static int shell_drvmgr_devs(int argc, char *argv[])
0286 {
0287   drvmgr_info_devs(OPTION_INFO_ALL);
0288   return 0;
0289 }
0290 
0291 static int shell_drvmgr_drvs(int argc, char *argv[])
0292 {
0293   drvmgr_info_drvs(OPTION_INFO_ALL);
0294   return 0;
0295 }
0296 
0297 static int shell_drvmgr_mem(int argc, char *argv[])
0298 {
0299   drvmgr_print_mem();
0300   return 0;
0301 }
0302 
0303 static int shell_drvmgr_translate(int argc, char *argv[])
0304 {
0305   int rc, rev, up, obj_type;
0306   void *obj, *dst;
0307   unsigned long src, tmp;
0308 
0309   if (argc != 5)
0310     return -1;
0311 
0312   obj = get_obj_adr(argv[2]);
0313   if (!obj)
0314     return -3;
0315 
0316   obj_type = *(int *)obj;
0317   if (obj_type != DRVMGR_OBJ_DEV) {
0318     puts(" ID is not a device\n");
0319     return 0;
0320   }
0321 
0322   tmp = strtoul(argv[3], NULL, 0);
0323   if (tmp > 3) {
0324     puts(" Not a valid option OPT, only [0..3] is valid");
0325     return 0;
0326   }
0327   rev = tmp & DRVMGR_TR_REVERSE;
0328   up = tmp & DRVMGR_TR_PATH;
0329 
0330   src = strtoul(argv[4], NULL, 0);
0331   if (src == ULONG_MAX && errno == ERANGE) {
0332     puts(" Not a valid source address");
0333     return 0;
0334   }
0335 
0336   rc = drvmgr_translate((struct drvmgr_dev *)obj, up | rev, (void *)src, &dst);
0337   if (rc == 0)
0338     printf(" Address %p could not be translated\n", (void *)src);
0339   else if (rc == 0xffffffff)
0340     printf(" %p => %p  (no translation required)\n", (void *)src, dst);
0341   else
0342     printf(" %p => %p  (map size 0x%x)\n", (void *)src, dst, rc);
0343 
0344   return 0;
0345 }
0346 
0347 static const char drvmgr_usage_str[] =
0348  " usage:\n"
0349  "  drvmgr buses         List bus specfic information on all buses\n"
0350  "  drvmgr devs          List general and driver specfic information\n"
0351  "                       about all devices\n"
0352  "  drvmgr drvs          List driver specfic information on all drivers\n"
0353  "  drvmgr info [ID]     List general and driver specfic information\n"
0354  "                       about all devices or one device, bus or driver\n"
0355  "  drvmgr mem           Dynamically memory usage\n"
0356  "  drvmgr parent ID     Short info about parent bus of a device\n"
0357  "  drvmgr remove ID     Remove a device or a bus\n"
0358  "  drvmgr res ID        List Resources of a device or bus\n"
0359  "  drvmgr short [ID]    Short info about all devices/buses or one\n"
0360  "                       device/bus\n"
0361  "  drvmgr topo          Show bus topology with all devices\n"
0362  "  drvmgr tr ID OPT ADR Translate ADR down(0)/up(1) -streams (OPT bit 1) in\n"
0363  "                       std(0)/reverse(1) (OPT bit 0) direction for device\n"
0364  "  drvmgr --help\n";
0365 
0366 static void usage(void)
0367 {
0368   puts(drvmgr_usage_str);
0369 }
0370 
0371 static int shell_drvmgr_usage(int argc, char *argv[])
0372 {
0373   usage();
0374   return 0;
0375 }
0376 
0377 struct shell_drvmgr_modifier {
0378   char *name;
0379   int (*func)(int argc, char *argv[]);
0380 };
0381 
0382 #define MODIFIER_NUM 12
0383 static struct shell_drvmgr_modifier shell_drvmgr_modifiers[MODIFIER_NUM] =
0384 {
0385   {"buses", shell_drvmgr_buses},
0386   {"devs", shell_drvmgr_devs},
0387   {"drvs", shell_drvmgr_drvs},
0388   {"info", shell_drvmgr_info},
0389   {"mem", shell_drvmgr_mem},
0390   {"parent", shell_drvmgr_parent},
0391   {"remove", shell_drvmgr_remove},
0392   {"res", shell_drvmgr_res},
0393   {"short", shell_drvmgr_short},
0394   {"topo", shell_drvmgr_topo},
0395   {"tr", shell_drvmgr_translate},
0396   {"--help", shell_drvmgr_usage},
0397 };
0398 
0399 static struct shell_drvmgr_modifier *shell_drvmgr_find_modifier(char *name)
0400 {
0401   struct shell_drvmgr_modifier *mod;
0402   int i;
0403 
0404   if (name == NULL)
0405     return NULL;
0406 
0407   for (i=0, mod=&shell_drvmgr_modifiers[0]; i<MODIFIER_NUM; i++, mod++) {
0408     if (strcmp(name, mod->name) == 0)
0409       return mod;
0410   }
0411 
0412   return NULL;
0413 }
0414 
0415 static int rtems_shell_main_drvmgr(
0416   int   argc,
0417   char *argv[]
0418 )
0419 {
0420   struct shell_drvmgr_modifier *mod;
0421   int rc;
0422 
0423   if (argc < 2) {
0424     show_drvmgr_info();
0425     rc = 0;
0426   } else if ((mod=shell_drvmgr_find_modifier(argv[1])) != NULL) {
0427     rc = mod->func(argc, argv);
0428   } else {
0429     rc = -1;
0430   }
0431 
0432   if (rc < 0) {
0433     printf(" invalid argument\n");
0434     usage();
0435   }
0436 
0437   return rc;
0438 }
0439 
0440 rtems_shell_cmd_t rtems_shell_DRVMGR_Command = {
0441   "drvmgr",                      /* name */
0442   drvmgr_usage_str,              /* usage */
0443   "system",                      /* topic */
0444   rtems_shell_main_drvmgr,       /* command */
0445   NULL,                          /* alias */
0446   NULL                           /* next */
0447 };