1 | /* Driver Manager Information printing Interface Implementation |
---|
2 | * |
---|
3 | * COPYRIGHT (c) 2009 Cobham Gaisler AB. |
---|
4 | * |
---|
5 | * The license and distribution terms for this file may be |
---|
6 | * found in the file LICENSE in this distribution or at |
---|
7 | * http://www.rtems.org/license/LICENSE. |
---|
8 | */ |
---|
9 | |
---|
10 | /* |
---|
11 | * These functions print stuff about the driver manager, what devices were |
---|
12 | * found and were united with a driver, the Bus topology, memory taken, etc. |
---|
13 | * |
---|
14 | */ |
---|
15 | |
---|
16 | #include <stdio.h> |
---|
17 | #include <stdlib.h> |
---|
18 | #include <string.h> |
---|
19 | |
---|
20 | #include <drvmgr/drvmgr.h> |
---|
21 | #include "drvmgr_internal.h" |
---|
22 | |
---|
23 | typedef void (*fun_ptr)(void); |
---|
24 | |
---|
25 | static int print_dev_found(struct drvmgr_dev *dev, void *arg) |
---|
26 | { |
---|
27 | char **pparg = arg; |
---|
28 | |
---|
29 | if (pparg && *pparg) { |
---|
30 | printf(*pparg); |
---|
31 | *pparg = NULL; |
---|
32 | } |
---|
33 | |
---|
34 | printf(" DEV %p %s on bus %p\n", dev, |
---|
35 | dev->name ? dev->name : "NO_NAME", dev->parent); |
---|
36 | |
---|
37 | return 0; /* Continue to next device */ |
---|
38 | } |
---|
39 | |
---|
40 | void drvmgr_print_devs(unsigned int options) |
---|
41 | { |
---|
42 | struct drvmgr *mgr = &drvmgr; |
---|
43 | char *parg; |
---|
44 | |
---|
45 | /* Print Drivers */ |
---|
46 | if (options & PRINT_DEVS_ASSIGNED) { |
---|
47 | parg = " --- DEVICES ASSIGNED TO DRIVER ---\n"; |
---|
48 | drvmgr_for_each_listdev(&mgr->devices[DRVMGR_LEVEL_MAX], |
---|
49 | DEV_STATE_UNITED, 0, print_dev_found, &parg); |
---|
50 | if (parg != NULL) |
---|
51 | printf("\n NO DEVICES WERE ASSIGNED A DRIVER\n"); |
---|
52 | } |
---|
53 | |
---|
54 | if (options & PRINT_DEVS_UNASSIGNED) { |
---|
55 | parg = "\n --- DEVICES WITHOUT DRIVER ---\n"; |
---|
56 | drvmgr_for_each_listdev(&mgr->devices_inactive, 0, |
---|
57 | DEV_STATE_UNITED, print_dev_found, &parg); |
---|
58 | if (parg != NULL) |
---|
59 | printf("\n NO DEVICES WERE WITHOUT DRIVER\n"); |
---|
60 | } |
---|
61 | |
---|
62 | if (options & PRINT_DEVS_FAILED) { |
---|
63 | parg = "\n --- DEVICES FAILED TO INITIALIZE ---\n"; |
---|
64 | drvmgr_for_each_listdev(&mgr->devices_inactive, |
---|
65 | DEV_STATE_INIT_FAILED, 0, print_dev_found, &parg); |
---|
66 | if (parg != NULL) |
---|
67 | printf("\n NO DEVICES FAILED TO INITIALIZE\n"); |
---|
68 | } |
---|
69 | |
---|
70 | if (options & PRINT_DEVS_IGNORED) { |
---|
71 | parg = "\n --- DEVICES IGNORED ---\n"; |
---|
72 | drvmgr_for_each_listdev(&mgr->devices_inactive, |
---|
73 | DEV_STATE_IGNORED, 0, print_dev_found, &parg); |
---|
74 | if (parg != NULL) |
---|
75 | printf("\n NO DEVICES WERE IGNORED\n"); |
---|
76 | } |
---|
77 | |
---|
78 | printf("\n\n"); |
---|
79 | } |
---|
80 | |
---|
81 | static int drvmgr_topo_func(struct drvmgr_dev *dev, void *arg) |
---|
82 | { |
---|
83 | char prefix[32]; |
---|
84 | int depth = dev->parent->depth; |
---|
85 | |
---|
86 | if (depth > 30) |
---|
87 | return 0; /* depth more than 30 not supported */ |
---|
88 | memset(prefix, ' ', depth + 1); |
---|
89 | prefix[depth + 1] = '\0'; |
---|
90 | |
---|
91 | printf(" %s|-> DEV %p %s\n", prefix, dev, |
---|
92 | dev->name ? dev->name : "NO_NAME"); |
---|
93 | return 0; |
---|
94 | } |
---|
95 | |
---|
96 | void drvmgr_print_topo(void) |
---|
97 | { |
---|
98 | /* Print Bus topology */ |
---|
99 | printf(" --- BUS TOPOLOGY ---\n"); |
---|
100 | drvmgr_for_each_dev(drvmgr_topo_func, NULL, DRVMGR_FED_DF); |
---|
101 | printf("\n\n"); |
---|
102 | } |
---|
103 | |
---|
104 | /* Print the memory usage */ |
---|
105 | void drvmgr_print_mem(void) |
---|
106 | { |
---|
107 | struct drvmgr *mgr = &drvmgr; |
---|
108 | struct drvmgr_bus *bus; |
---|
109 | struct drvmgr_dev *dev; |
---|
110 | struct drvmgr_drv *drv; |
---|
111 | |
---|
112 | struct drvmgr_bus_res *node; |
---|
113 | struct drvmgr_drv_res *res; |
---|
114 | struct drvmgr_key *key; |
---|
115 | |
---|
116 | unsigned int busmem = 0; |
---|
117 | unsigned int devmem = 0; |
---|
118 | unsigned int drvmem = 0; |
---|
119 | unsigned int resmem = 0; |
---|
120 | unsigned int devprivmem = 0; |
---|
121 | |
---|
122 | DRVMGR_LOCK_READ(); |
---|
123 | |
---|
124 | bus = BUS_LIST_HEAD(&mgr->buses[DRVMGR_LEVEL_MAX]); |
---|
125 | while (bus) { |
---|
126 | busmem += sizeof(struct drvmgr_bus); |
---|
127 | |
---|
128 | /* Get size of resources on this bus */ |
---|
129 | node = bus->reslist; |
---|
130 | while (node) { |
---|
131 | resmem += sizeof(struct drvmgr_bus_res); |
---|
132 | |
---|
133 | res = node->resource; |
---|
134 | while (res->keys) { |
---|
135 | resmem += sizeof(struct drvmgr_drv_res); |
---|
136 | |
---|
137 | key = res->keys; |
---|
138 | while (key->key_type != DRVMGR_KT_NONE) { |
---|
139 | resmem += sizeof |
---|
140 | (struct drvmgr_key); |
---|
141 | key++; |
---|
142 | } |
---|
143 | resmem += sizeof(struct drvmgr_key); |
---|
144 | res++; |
---|
145 | } |
---|
146 | |
---|
147 | node = node->next; |
---|
148 | } |
---|
149 | |
---|
150 | bus = bus->next; |
---|
151 | } |
---|
152 | |
---|
153 | drv = DRV_LIST_HEAD(&mgr->drivers); |
---|
154 | while (drv) { |
---|
155 | drvmem += sizeof(struct drvmgr_drv); |
---|
156 | drv = drv->next; |
---|
157 | } |
---|
158 | |
---|
159 | dev = DEV_LIST_HEAD(&mgr->devices[DRVMGR_LEVEL_MAX]); |
---|
160 | while (dev) { |
---|
161 | devmem += sizeof(struct drvmgr_dev); |
---|
162 | if (dev->drv && dev->drv->dev_priv_size > 0) |
---|
163 | devprivmem += dev->drv->dev_priv_size; |
---|
164 | dev = dev->next; |
---|
165 | } |
---|
166 | |
---|
167 | DRVMGR_UNLOCK(); |
---|
168 | |
---|
169 | printf(" --- MEMORY USAGE ---\n"); |
---|
170 | printf(" BUS: %d bytes\n", busmem); |
---|
171 | printf(" DRV: %d bytes\n", drvmem); |
---|
172 | printf(" DEV: %d bytes\n", devmem); |
---|
173 | printf(" DEV private: %d bytes\n", devprivmem); |
---|
174 | printf(" RES: %d bytes\n", resmem); |
---|
175 | printf(" TOTAL: %d bytes\n", |
---|
176 | busmem + drvmem + devmem + devprivmem + resmem); |
---|
177 | printf("\n\n"); |
---|
178 | } |
---|
179 | |
---|
180 | /* Print the memory usage */ |
---|
181 | void drvmgr_summary(void) |
---|
182 | { |
---|
183 | struct drvmgr *mgr = &drvmgr; |
---|
184 | struct drvmgr_bus *bus; |
---|
185 | struct drvmgr_dev *dev; |
---|
186 | struct drvmgr_drv *drv; |
---|
187 | int i, buscnt = 0, devcnt = 0, drvcnt = 0; |
---|
188 | |
---|
189 | printf(" --- SUMMARY ---\n"); |
---|
190 | |
---|
191 | drv = DRV_LIST_HEAD(&mgr->drivers); |
---|
192 | while (drv) { |
---|
193 | drvcnt++; |
---|
194 | drv = drv->next; |
---|
195 | } |
---|
196 | printf(" NUMBER OF DRIVERS: %d\n", drvcnt); |
---|
197 | |
---|
198 | DRVMGR_LOCK_READ(); |
---|
199 | |
---|
200 | for (i = 0; i <= DRVMGR_LEVEL_MAX; i++) { |
---|
201 | buscnt = 0; |
---|
202 | bus = BUS_LIST_HEAD(&mgr->buses[i]); |
---|
203 | while (bus) { |
---|
204 | buscnt++; |
---|
205 | bus = bus->next; |
---|
206 | } |
---|
207 | if (buscnt > 0) { |
---|
208 | printf(" NUMBER OF BUSES IN LEVEL[%d]: %d\n", |
---|
209 | i, buscnt); |
---|
210 | } |
---|
211 | } |
---|
212 | |
---|
213 | for (i = 0; i <= DRVMGR_LEVEL_MAX; i++) { |
---|
214 | devcnt = 0; |
---|
215 | dev = DEV_LIST_HEAD(&mgr->devices[i]); |
---|
216 | while (dev) { |
---|
217 | devcnt++; |
---|
218 | dev = dev->next; |
---|
219 | } |
---|
220 | if (devcnt > 0) { |
---|
221 | printf(" NUMBER OF DEVS IN LEVEL[%d]: %d\n", |
---|
222 | i, devcnt); |
---|
223 | } |
---|
224 | } |
---|
225 | |
---|
226 | DRVMGR_UNLOCK(); |
---|
227 | |
---|
228 | printf("\n\n"); |
---|
229 | } |
---|
230 | |
---|
231 | static void print_info(void *p, char *str) |
---|
232 | { |
---|
233 | printf(" "); |
---|
234 | puts(str); |
---|
235 | } |
---|
236 | |
---|
237 | void drvmgr_info_dev(struct drvmgr_dev *dev, unsigned int options) |
---|
238 | { |
---|
239 | if (!dev) |
---|
240 | return; |
---|
241 | |
---|
242 | printf(" -- DEVICE %p --\n", dev); |
---|
243 | if (options & OPTION_DEV_GENINFO) { |
---|
244 | printf(" PARENT BUS: %p\n", dev->parent); |
---|
245 | printf(" NAME: %s\n", dev->name ? dev->name : "NO_NAME"); |
---|
246 | printf(" STATE: 0x%08x\n", dev->state); |
---|
247 | if (dev->bus) |
---|
248 | printf(" BRIDGE TO: %p\n", dev->bus); |
---|
249 | printf(" INIT LEVEL: %d\n", dev->level); |
---|
250 | printf(" ERROR: %d\n", dev->error); |
---|
251 | printf(" MINOR BUS: %d\n", dev->minor_bus); |
---|
252 | if (dev->drv) { |
---|
253 | printf(" MINOR DRV: %d\n", dev->minor_drv); |
---|
254 | printf(" DRIVER: %p (%s)\n", dev->drv, |
---|
255 | dev->drv->name ? dev->drv->name : "NO_NAME"); |
---|
256 | printf(" PRIVATE: %p\n", dev->priv); |
---|
257 | } |
---|
258 | } |
---|
259 | |
---|
260 | if (options & OPTION_DEV_BUSINFO) { |
---|
261 | printf(" --- DEVICE INFO FROM BUS DRIVER ---\n"); |
---|
262 | if (!dev->parent) |
---|
263 | printf(" !! device has no parent bus !!\n"); |
---|
264 | else if (dev->parent->ops->get_info_dev) |
---|
265 | dev->parent->ops->get_info_dev(dev, print_info, NULL); |
---|
266 | else |
---|
267 | printf(" Bus doesn't implement get_info_dev func\n"); |
---|
268 | } |
---|
269 | |
---|
270 | if (options & OPTION_DEV_DRVINFO) { |
---|
271 | if (dev->drv) { |
---|
272 | printf(" --- DEVICE INFO FROM DEVICE DRIVER ---\n"); |
---|
273 | if (dev->drv->ops->info) |
---|
274 | dev->drv->ops->info(dev, print_info, NULL, 0, 0); |
---|
275 | else |
---|
276 | printf(" Driver doesn't implement info func\n"); |
---|
277 | } |
---|
278 | } |
---|
279 | } |
---|
280 | |
---|
281 | static void drvmgr_info_bus_map(struct drvmgr_map_entry *map) |
---|
282 | { |
---|
283 | if (map == NULL) |
---|
284 | printf(" Addresses mapped 1:1\n"); |
---|
285 | else if (map == DRVMGR_TRANSLATE_NO_BRIDGE) |
---|
286 | printf(" No bridge in this direction\n"); |
---|
287 | else { |
---|
288 | while (map->size != 0) { |
---|
289 | printf(" 0x%08lx-0x%08lx => 0x%08lx-0x%08lx %s\n", |
---|
290 | (unsigned long)map->from_adr, |
---|
291 | (unsigned long)(map->from_adr + map->size - 1), |
---|
292 | (unsigned long)map->to_adr, |
---|
293 | (unsigned long)(map->to_adr + map->size - 1), |
---|
294 | map->name ? map->name : "no label"); |
---|
295 | map++; |
---|
296 | } |
---|
297 | } |
---|
298 | } |
---|
299 | |
---|
300 | void drvmgr_info_bus(struct drvmgr_bus *bus, unsigned int options) |
---|
301 | { |
---|
302 | struct drvmgr_dev *dev; |
---|
303 | |
---|
304 | /* Print Driver */ |
---|
305 | printf("-- BUS %p --\n", bus); |
---|
306 | printf(" BUS TYPE: %d\n", bus->bus_type); |
---|
307 | printf(" DEVICE: %p (%s)\n", bus->dev, |
---|
308 | bus->dev->name ? bus->dev->name : "NO_NAME"); |
---|
309 | printf(" OPS: %p\n", bus->ops); |
---|
310 | printf(" CHILDREN: %d devices\n", bus->dev_cnt); |
---|
311 | printf(" LEVEL: %d\n", bus->level); |
---|
312 | printf(" STATE: 0x%08x\n", bus->state); |
---|
313 | printf(" ERROR: %d\n", bus->error); |
---|
314 | |
---|
315 | /* Print address mappings up- (to parent) and down- (from parent to |
---|
316 | * this bus) stream the bridge of this bus |
---|
317 | */ |
---|
318 | printf(" DOWN STREAMS BRIDGE MAPPINGS (from parent to this bus)\n"); |
---|
319 | drvmgr_info_bus_map(bus->maps_down); |
---|
320 | printf(" UP STREAMS BRIDGE MAPPINGS (from this bus to parent)\n"); |
---|
321 | drvmgr_info_bus_map(bus->maps_up); |
---|
322 | |
---|
323 | /* Print Devices on this bus? */ |
---|
324 | if (options & OPTION_BUS_DEVS) { |
---|
325 | printf(" CHILDREN:\n"); |
---|
326 | DRVMGR_LOCK_READ(); |
---|
327 | dev = bus->children; |
---|
328 | while (dev) { |
---|
329 | printf(" |- DEV[%02d]: %p %s\n", dev->minor_bus, |
---|
330 | dev, dev->name ? dev->name : "NO_NAME"); |
---|
331 | dev = dev->next_in_bus; |
---|
332 | } |
---|
333 | DRVMGR_UNLOCK(); |
---|
334 | } |
---|
335 | } |
---|
336 | |
---|
337 | void drvmgr_info_drv(struct drvmgr_drv *drv, unsigned int options) |
---|
338 | { |
---|
339 | struct drvmgr_dev *dev; |
---|
340 | int i; |
---|
341 | |
---|
342 | /* Print Driver */ |
---|
343 | printf(" -- DRIVER %p --\n", drv); |
---|
344 | printf(" DRIVER ID: 0x%llx\n", drv->drv_id); |
---|
345 | printf(" NAME: %s\n", drv->name ? drv->name : "NO_NAME"); |
---|
346 | printf(" BUS TYPE: %d\n", drv->bus_type); |
---|
347 | printf(" OPERATIONS:\n"); |
---|
348 | for (i = 0; i < DRVMGR_LEVEL_MAX; i++) |
---|
349 | printf(" init[%d]: %p\n", i + 1, drv->ops->init[i]); |
---|
350 | printf(" remove: %p\n", drv->ops->remove); |
---|
351 | printf(" info: %p\n", drv->ops->info); |
---|
352 | printf(" NO. DEVICES: %d\n", drv->dev_cnt); |
---|
353 | |
---|
354 | /* Print devices united with this driver? */ |
---|
355 | if (options & OPTION_DRV_DEVS) { |
---|
356 | DRVMGR_LOCK_READ(); |
---|
357 | dev = drv->dev; |
---|
358 | while (dev) { |
---|
359 | printf(" DEV[%02d]: %p %s\n", dev->minor_drv, |
---|
360 | dev, dev->name ? dev->name : "NO_NAME"); |
---|
361 | dev = dev->next_in_drv; |
---|
362 | } |
---|
363 | DRVMGR_UNLOCK(); |
---|
364 | } |
---|
365 | } |
---|
366 | |
---|
367 | void (*info_obj[3])(void *obj, unsigned int) = { |
---|
368 | /* DRVMGR_OBJ_DRV */ (void (*)(void *, unsigned int))drvmgr_info_drv, |
---|
369 | /* DRVMGR_OBJ_BUS */ (void (*)(void *, unsigned int))drvmgr_info_bus, |
---|
370 | /* DRVMGR_OBJ_DEV */ (void (*)(void *, unsigned int))drvmgr_info_dev, |
---|
371 | }; |
---|
372 | |
---|
373 | /* Get information about a device/bus/driver */ |
---|
374 | void drvmgr_info(void *id, unsigned int options) |
---|
375 | { |
---|
376 | int obj_type; |
---|
377 | void (*func)(void *, unsigned int); |
---|
378 | |
---|
379 | if (!id) |
---|
380 | return; |
---|
381 | obj_type = *(int *)id; |
---|
382 | if ((obj_type < DRVMGR_OBJ_DRV) || (obj_type > DRVMGR_OBJ_DEV)) |
---|
383 | return; |
---|
384 | func = info_obj[obj_type - 1]; |
---|
385 | func(id, options); |
---|
386 | } |
---|
387 | |
---|
388 | void drvmgr_info_devs_on_bus(struct drvmgr_bus *bus, unsigned int options) |
---|
389 | { |
---|
390 | struct drvmgr_dev *dev; |
---|
391 | |
---|
392 | /* Print All Devices on Bus */ |
---|
393 | printf("\n\n -= All Devices on BUS %p =-\n\n", bus); |
---|
394 | dev = bus->children; |
---|
395 | while (dev) { |
---|
396 | drvmgr_info_dev(dev, options); |
---|
397 | puts(""); |
---|
398 | dev = dev->next_in_bus; |
---|
399 | } |
---|
400 | |
---|
401 | if ((options & OPTION_RECURSIVE) == 0) |
---|
402 | return; |
---|
403 | |
---|
404 | /* This device provides a bus, print the bus */ |
---|
405 | dev = bus->children; |
---|
406 | while (dev) { |
---|
407 | if (dev->bus) |
---|
408 | drvmgr_info_devs_on_bus(dev->bus, options); |
---|
409 | dev = dev->next_in_bus; |
---|
410 | } |
---|
411 | } |
---|
412 | |
---|
413 | void drvmgr_info_devs(unsigned int options) |
---|
414 | { |
---|
415 | struct drvmgr *mgr = &drvmgr; |
---|
416 | struct drvmgr_dev *dev; |
---|
417 | |
---|
418 | /* Print device information of all devices and their child devices */ |
---|
419 | dev = &mgr->root_dev; |
---|
420 | drvmgr_info_devs_on_bus(dev->bus, options); |
---|
421 | printf("\n\n"); |
---|
422 | } |
---|
423 | |
---|
424 | void drvmgr_info_drvs(unsigned int options) |
---|
425 | { |
---|
426 | struct drvmgr *mgr = &drvmgr; |
---|
427 | struct drvmgr_drv *drv; |
---|
428 | |
---|
429 | drv = DRV_LIST_HEAD(&mgr->drivers); |
---|
430 | while (drv) { |
---|
431 | drvmgr_info_drv(drv, options); |
---|
432 | puts("\n"); |
---|
433 | drv = drv->next; |
---|
434 | } |
---|
435 | } |
---|
436 | |
---|
437 | void drvmgr_info_buses(unsigned int options) |
---|
438 | { |
---|
439 | struct drvmgr *mgr = &drvmgr; |
---|
440 | struct drvmgr_bus *bus; |
---|
441 | |
---|
442 | bus = BUS_LIST_HEAD(&mgr->buses[DRVMGR_LEVEL_MAX]); |
---|
443 | while (bus) { |
---|
444 | drvmgr_info_bus(bus, options); |
---|
445 | puts("\n"); |
---|
446 | bus = bus->next; |
---|
447 | } |
---|
448 | } |
---|