Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /* Driver Manager Information printing Interface Implementation
0004  *
0005  * COPYRIGHT (c) 2009 Cobham Gaisler AB.
0006  *
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, this list of conditions and the following disclaimer.
0012  * 2. Redistributions in binary form must reproduce the above copyright
0013  *    notice, this list of conditions and the following disclaimer in the
0014  *    documentation and/or other materials provided with the distribution.
0015  *
0016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0017  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0019  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0020  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0021  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0022  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0023  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0024  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0025  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0026  * POSSIBILITY OF SUCH DAMAGE.
0027  */
0028 
0029 /*
0030  *  These functions print stuff about the driver manager, what devices were
0031  *  found and were united with a driver, the Bus topology, memory taken, etc.
0032  *
0033  */
0034 
0035 #include <inttypes.h>
0036 #include <stdio.h>
0037 #include <stdlib.h>
0038 #include <string.h>
0039 
0040 #include <drvmgr/drvmgr.h>
0041 #include "drvmgr_internal.h"
0042 
0043 typedef void (*fun_ptr)(void);
0044 
0045 static int print_dev_found(struct drvmgr_dev *dev, void *arg)
0046 {
0047     char **pparg = arg;
0048 
0049     if (pparg && *pparg) {
0050         printf(*pparg);
0051         *pparg = NULL;
0052     }
0053 
0054     printf(" DEV %p  %s on bus %p\n", dev,
0055         dev->name ? dev->name : "NO_NAME", dev->parent);
0056 
0057     return 0; /* Continue to next device */
0058 }
0059 
0060 void drvmgr_print_devs(unsigned int options)
0061 {
0062     struct drvmgr *mgr = &drvmgr;
0063     char *parg;
0064 
0065     /* Print Drivers */
0066     if (options & PRINT_DEVS_ASSIGNED) {
0067         parg = " --- DEVICES ASSIGNED TO DRIVER ---\n";
0068         drvmgr_for_each_listdev(&mgr->devices[DRVMGR_LEVEL_MAX],
0069                 DEV_STATE_UNITED, 0, print_dev_found, &parg);
0070         if (parg != NULL)
0071             printf("\n NO DEVICES WERE ASSIGNED A DRIVER\n");
0072     }
0073 
0074     if (options & PRINT_DEVS_UNASSIGNED) {
0075         parg = "\n --- DEVICES WITHOUT DRIVER ---\n";
0076         drvmgr_for_each_listdev(&mgr->devices_inactive, 0,
0077             DEV_STATE_UNITED, print_dev_found, &parg);
0078         if (parg != NULL)
0079             printf("\n NO DEVICES WERE WITHOUT DRIVER\n");
0080     }
0081 
0082     if (options & PRINT_DEVS_FAILED) {
0083         parg = "\n --- DEVICES FAILED TO INITIALIZE ---\n";
0084         drvmgr_for_each_listdev(&mgr->devices_inactive,
0085             DEV_STATE_INIT_FAILED, 0, print_dev_found, &parg);
0086         if (parg != NULL)
0087             printf("\n NO DEVICES FAILED TO INITIALIZE\n");
0088     }
0089 
0090     if (options & PRINT_DEVS_IGNORED) {
0091         parg = "\n --- DEVICES IGNORED ---\n";
0092         drvmgr_for_each_listdev(&mgr->devices_inactive,
0093             DEV_STATE_IGNORED, 0, print_dev_found, &parg);
0094         if (parg != NULL)
0095             printf("\n NO DEVICES WERE IGNORED\n");
0096     }
0097 
0098     printf("\n\n");
0099 }
0100 
0101 static intptr_t drvmgr_topo_func(struct drvmgr_dev *dev, void *arg)
0102 {
0103     char prefix[32];
0104     int depth = dev->parent->depth;
0105 
0106     if (depth > 30)
0107         return 0; /* depth more than 30 not supported */
0108     memset(prefix, ' ', depth + 1);
0109     prefix[depth + 1] = '\0';
0110 
0111     printf(" %s|-> DEV  %p  %s\n", prefix, dev,
0112         dev->name ? dev->name :  "NO_NAME");
0113     return 0;
0114 }
0115 
0116 void drvmgr_print_topo(void)
0117 {
0118     /* Print Bus topology */
0119     printf(" --- BUS TOPOLOGY ---\n");
0120     drvmgr_for_each_dev(drvmgr_topo_func, NULL, DRVMGR_FED_DF);
0121     printf("\n\n");
0122 }
0123 
0124 /* Print the memory usage */
0125 void drvmgr_print_mem(void)
0126 {
0127     struct drvmgr *mgr = &drvmgr;
0128     struct drvmgr_bus *bus;
0129     struct drvmgr_dev *dev;
0130     struct drvmgr_drv *drv;
0131 
0132     struct drvmgr_bus_res *node;
0133     struct drvmgr_drv_res *res;
0134     struct drvmgr_key *key;
0135 
0136     unsigned int busmem = 0;
0137     unsigned int devmem = 0;
0138     unsigned int drvmem = 0;
0139     unsigned int resmem = 0;
0140     unsigned int devprivmem = 0;
0141 
0142     DRVMGR_LOCK_READ();
0143 
0144     bus = BUS_LIST_HEAD(&mgr->buses[DRVMGR_LEVEL_MAX]);
0145     while (bus) {
0146         busmem += sizeof(struct drvmgr_bus);
0147 
0148         /* Get size of resources on this bus */
0149         node = bus->reslist;
0150         while (node) {
0151             resmem += sizeof(struct drvmgr_bus_res);
0152 
0153             res = node->resource;
0154             while (res->keys) {
0155                 resmem += sizeof(struct drvmgr_drv_res);
0156 
0157                 key = res->keys;
0158                 while (key->key_type != DRVMGR_KT_NONE) {
0159                     resmem += sizeof
0160                         (struct drvmgr_key);
0161                     key++;
0162                 }
0163                 resmem += sizeof(struct drvmgr_key);
0164                 res++;
0165             }
0166 
0167             node = node->next;
0168         }
0169 
0170         bus = bus->next;
0171     }
0172 
0173     drv = DRV_LIST_HEAD(&mgr->drivers);
0174     while (drv) {
0175         drvmem += sizeof(struct drvmgr_drv);
0176         drv = drv->next;
0177     }
0178 
0179     dev = DEV_LIST_HEAD(&mgr->devices[DRVMGR_LEVEL_MAX]);
0180     while (dev) {
0181         devmem += sizeof(struct drvmgr_dev);
0182         if (dev->drv && dev->drv->dev_priv_size > 0)
0183             devprivmem += dev->drv->dev_priv_size;
0184         dev = dev->next;
0185     }
0186 
0187     DRVMGR_UNLOCK();
0188 
0189     printf(" --- MEMORY USAGE ---\n");
0190     printf(" BUS:          %d bytes\n", busmem);
0191     printf(" DRV:          %d bytes\n", drvmem);
0192     printf(" DEV:          %d bytes\n", devmem);
0193     printf(" DEV private:  %d bytes\n", devprivmem);
0194     printf(" RES:          %d bytes\n", resmem);
0195     printf(" TOTAL:        %d bytes\n",
0196             busmem + drvmem + devmem + devprivmem + resmem);
0197     printf("\n\n");
0198 }
0199 
0200 /* Print the memory usage */
0201 void drvmgr_summary(void)
0202 {
0203     struct drvmgr *mgr = &drvmgr;
0204     struct drvmgr_bus *bus;
0205     struct drvmgr_dev *dev;
0206     struct drvmgr_drv *drv;
0207     int i, buscnt = 0, devcnt = 0, drvcnt = 0;
0208 
0209     printf(" --- SUMMARY ---\n");
0210 
0211     drv = DRV_LIST_HEAD(&mgr->drivers);
0212     while (drv) {
0213         drvcnt++;
0214         drv = drv->next;
0215     }
0216     printf(" NUMBER OF DRIVERS:               %d\n", drvcnt);
0217 
0218     DRVMGR_LOCK_READ();
0219 
0220     for (i = 0; i <= DRVMGR_LEVEL_MAX; i++) {
0221         buscnt = 0;
0222         bus = BUS_LIST_HEAD(&mgr->buses[i]);
0223         while (bus) {
0224             buscnt++;
0225             bus = bus->next;
0226         }
0227         if (buscnt > 0) {
0228             printf(" NUMBER OF BUSES IN LEVEL[%d]:     %d\n",
0229                 i, buscnt);
0230         }
0231     }
0232 
0233     for (i = 0; i <= DRVMGR_LEVEL_MAX; i++) {
0234         devcnt = 0;
0235         dev = DEV_LIST_HEAD(&mgr->devices[i]);
0236         while (dev) {
0237             devcnt++;
0238             dev = dev->next;
0239         }
0240         if (devcnt > 0) {
0241             printf(" NUMBER OF DEVS IN LEVEL[%d]:      %d\n",
0242                 i, devcnt);
0243         }
0244     }
0245 
0246     DRVMGR_UNLOCK();
0247 
0248     printf("\n\n");
0249 }
0250 
0251 static void print_info(void *p, char *str)
0252 {
0253     printf("  ");
0254     puts(str);
0255 }
0256 
0257 void drvmgr_info_dev(struct drvmgr_dev *dev, unsigned int options)
0258 {
0259     if (!dev)
0260         return;
0261 
0262     printf(" -- DEVICE %p --\n", dev);
0263     if (options & OPTION_DEV_GENINFO) {
0264         printf("  PARENT BUS:  %p\n", dev->parent);
0265         printf("  NAME:        %s\n", dev->name ? dev->name : "NO_NAME");
0266         printf("  STATE:       0x%08x\n", dev->state);
0267         if (dev->bus)
0268             printf("  BRIDGE TO:   %p\n", dev->bus);
0269         printf("  INIT LEVEL:  %d\n", dev->level);
0270         printf("  ERROR:       %d\n", dev->error);
0271         printf("  MINOR BUS:   %d\n", dev->minor_bus);
0272         if (dev->drv) {
0273             printf("  MINOR DRV:   %d\n", dev->minor_drv);
0274             printf("  DRIVER:      %p (%s)\n", dev->drv,
0275                 dev->drv->name ? dev->drv->name : "NO_NAME");
0276             printf("  PRIVATE:     %p\n", dev->priv);
0277         }
0278     }
0279 
0280     if (options & OPTION_DEV_BUSINFO) {
0281         printf("  --- DEVICE INFO FROM BUS DRIVER ---\n");
0282         if (!dev->parent)
0283             printf("  !! device has no parent bus !!\n");
0284         else if (dev->parent->ops->get_info_dev)
0285             dev->parent->ops->get_info_dev(dev, print_info, NULL);
0286         else
0287             printf("  Bus doesn't implement get_info_dev func\n");
0288     }
0289 
0290     if (options & OPTION_DEV_DRVINFO) {
0291         if (dev->drv) {
0292             printf("  --- DEVICE INFO FROM DEVICE DRIVER ---\n");
0293             if (dev->drv->ops->info)
0294                 dev->drv->ops->info(dev, print_info, NULL, 0, 0);
0295             else
0296                 printf("  Driver doesn't implement info func\n");
0297         }
0298     }
0299 }
0300 
0301 static void drvmgr_info_bus_map(struct drvmgr_map_entry *map)
0302 {
0303     if (map == NULL)
0304         printf("    Addresses mapped 1:1\n");
0305     else if (map == DRVMGR_TRANSLATE_NO_BRIDGE)
0306         printf("    No bridge in this direction\n");
0307     else {
0308         while (map->size != 0) {
0309             printf("    0x%08lx-0x%08lx => 0x%08lx-0x%08lx  %s\n",
0310                 (unsigned long)map->from_adr,
0311                 (unsigned long)(map->from_adr + map->size - 1),
0312                 (unsigned long)map->to_adr,
0313                 (unsigned long)(map->to_adr + map->size - 1),
0314                 map->name ? map->name : "no label");
0315             map++;
0316         }
0317     }
0318 }
0319 
0320 void drvmgr_info_bus(struct drvmgr_bus *bus, unsigned int options)
0321 {
0322     struct drvmgr_dev *dev;
0323 
0324     /* Print Driver */
0325     printf("-- BUS %p --\n", bus);
0326     printf("  BUS TYPE:    %d\n", bus->bus_type);
0327     printf("  DEVICE:      %p (%s)\n", bus->dev,
0328         bus->dev->name ? bus->dev->name : "NO_NAME");
0329     printf("  OPS:         %p\n", bus->ops);
0330     printf("  CHILDREN:    %d devices\n", bus->dev_cnt);
0331     printf("  LEVEL:       %d\n", bus->level);
0332     printf("  STATE:       0x%08x\n", bus->state);
0333     printf("  ERROR:       %d\n", bus->error);
0334 
0335     /* Print address mappings up- (to parent) and down- (from parent to
0336      * this bus) stream the bridge of this bus
0337      */
0338     printf("  DOWN STREAMS BRIDGE MAPPINGS  (from parent to this bus)\n");
0339     drvmgr_info_bus_map(bus->maps_down);
0340     printf("  UP STREAMS BRIDGE MAPPINGS    (from this bus to parent)\n");
0341     drvmgr_info_bus_map(bus->maps_up);
0342 
0343     /* Print Devices on this bus? */
0344     if (options & OPTION_BUS_DEVS) {
0345         printf("  CHILDREN:\n");
0346         DRVMGR_LOCK_READ();
0347         dev = bus->children;
0348         while (dev) {
0349             printf("   |- DEV[%02d]: %p  %s\n", dev->minor_bus,
0350                 dev, dev->name ? dev->name : "NO_NAME");
0351             dev = dev->next_in_bus;
0352         }
0353         DRVMGR_UNLOCK();
0354     }
0355 }
0356 
0357 void drvmgr_info_drv(struct drvmgr_drv *drv, unsigned int options)
0358 {
0359     struct drvmgr_dev *dev;
0360     int i;
0361 
0362     /* Print Driver */
0363     printf(" -- DRIVER %p --\n", drv);
0364     printf("  DRIVER ID:   0x%" PRIx64 "\n", drv->drv_id);
0365     printf("  NAME:        %s\n", drv->name ? drv->name : "NO_NAME");
0366     printf("  BUS TYPE:    %d\n", drv->bus_type);
0367     printf("  OPERATIONS:\n");
0368     for (i = 0; i < DRVMGR_LEVEL_MAX; i++)
0369         printf("   init[%d]:    %p\n", i + 1, drv->ops->init[i]);
0370     printf("   remove:     %p\n", drv->ops->remove);
0371     printf("   info:       %p\n", drv->ops->info);
0372     printf("  NO. DEVICES: %d\n", drv->dev_cnt);
0373 
0374     /* Print devices united with this driver? */
0375     if (options & OPTION_DRV_DEVS) {
0376         DRVMGR_LOCK_READ();
0377         dev = drv->dev;
0378         while (dev) {
0379             printf("  DEV[%02d]:     %p  %s\n", dev->minor_drv,
0380                 dev, dev->name ? dev->name : "NO_NAME");
0381             dev = dev->next_in_drv;
0382         }
0383         DRVMGR_UNLOCK();
0384     }
0385 }
0386 
0387 void (*info_obj[3])(void *obj, unsigned int) = {
0388     /* DRVMGR_OBJ_DRV */ (void (*)(void *, unsigned int))drvmgr_info_drv,
0389     /* DRVMGR_OBJ_BUS */ (void (*)(void *, unsigned int))drvmgr_info_bus,
0390     /* DRVMGR_OBJ_DEV */ (void (*)(void *, unsigned int))drvmgr_info_dev,
0391 };
0392 
0393 /* Get information about a device/bus/driver */
0394 void drvmgr_info(void *id, unsigned int options)
0395 {
0396     int obj_type;
0397     void (*func)(void *, unsigned int);
0398 
0399     if (!id)
0400         return;
0401     obj_type = *(int *)id;
0402     if ((obj_type < DRVMGR_OBJ_DRV) || (obj_type > DRVMGR_OBJ_DEV))
0403         return;
0404     func = info_obj[obj_type - 1];
0405     func(id, options);
0406 }
0407 
0408 void drvmgr_info_devs_on_bus(struct drvmgr_bus *bus, unsigned int options)
0409 {
0410     struct drvmgr_dev *dev;
0411 
0412     /* Print All Devices on Bus */
0413     printf("\n\n  -= All Devices on BUS %p =-\n\n", bus);
0414     dev = bus->children;
0415     while (dev) {
0416         drvmgr_info_dev(dev, options);
0417         puts("");
0418         dev = dev->next_in_bus;
0419     }
0420 
0421     if ((options & OPTION_RECURSIVE) == 0)
0422         return;
0423 
0424     /* This device provides a bus, print the bus */
0425     dev = bus->children;
0426     while (dev) {
0427         if (dev->bus)
0428             drvmgr_info_devs_on_bus(dev->bus, options);
0429         dev = dev->next_in_bus;
0430     }
0431 }
0432 
0433 void drvmgr_info_devs(unsigned int options)
0434 {
0435     struct drvmgr *mgr = &drvmgr;
0436     struct drvmgr_dev *dev;
0437 
0438     /* Print device information of all devices and their child devices */
0439     dev = &mgr->root_dev;
0440     drvmgr_info_devs_on_bus(dev->bus, options);
0441     printf("\n\n");
0442 }
0443 
0444 void drvmgr_info_drvs(unsigned int options)
0445 {
0446     struct drvmgr *mgr = &drvmgr;
0447     struct drvmgr_drv *drv;
0448 
0449     drv = DRV_LIST_HEAD(&mgr->drivers);
0450     while (drv) {
0451         drvmgr_info_drv(drv, options);
0452         puts("\n");
0453         drv = drv->next;
0454     }
0455 }
0456 
0457 void drvmgr_info_buses(unsigned int options)
0458 {
0459     struct drvmgr *mgr = &drvmgr;
0460     struct drvmgr_bus *bus;
0461 
0462     bus = BUS_LIST_HEAD(&mgr->buses[DRVMGR_LEVEL_MAX]);
0463     while (bus) {
0464         drvmgr_info_bus(bus, options);
0465         puts("\n");
0466         bus = bus->next;
0467     }
0468 }