Index: cpukit/libmisc/monitor/mon-object.c
===================================================================
--- cpukit/libmisc/monitor/mon-object.c	(revision b06e68ef1f6df69cc86d72356c3a002054a35fad)
+++ cpukit/libmisc/monitor/mon-object.c	(revision b06e68ef1f6df69cc86d72356c3a002054a35fad)
@@ -0,0 +1,376 @@
+/*
+ *	@(#)object.c	1.7 - 95/08/02
+ *	
+ *
+ * RTEMS Monitor "object" support.
+ *
+ * Used to traverse object lists and print them out.
+ * An object can be an RTEMS object (chain based stuff) or
+ * a "misc" object such as a device driver.
+ *
+ * Each object has its own file in this directory (eg: extension.c)
+ * That file provides routines to convert a "native" structure
+ * to its canonical form, print a canonical structure, etc.
+ *
+ * TODO:
+ *     should allow for non-numeric id's???
+ *
+ *  $Id$
+ */
+
+#include <rtems.h>
+#include "monitor.h"
+
+#include <stdio.h>
+#include <stdlib.h>             /* strtoul() */
+
+#include <monitor.h>
+
+#define NUMELEMS(arr)	(sizeof(arr) / sizeof(arr[0]))
+
+/*
+ * add:
+ *     next
+ */
+
+rtems_monitor_object_info_t rtems_monitor_object_info[] =
+{
+    { RTEMS_OBJECT_CONFIG,
+      (void *) 0,
+      sizeof(rtems_monitor_config_t),
+      (rtems_monitor_object_next_fn)        rtems_monitor_config_next,
+      (rtems_monitor_object_canonical_fn)   rtems_monitor_config_canonical,
+      (rtems_monitor_object_dump_header_fn) rtems_monitor_config_dump_header,
+      (rtems_monitor_object_dump_fn)        rtems_monitor_config_dump,
+    },
+    { RTEMS_OBJECT_MPCI,
+      (void *) 0,
+      sizeof(rtems_monitor_mpci_t),
+      (rtems_monitor_object_next_fn)        rtems_monitor_mpci_next,
+      (rtems_monitor_object_canonical_fn)   rtems_monitor_mpci_canonical,
+      (rtems_monitor_object_dump_header_fn) rtems_monitor_mpci_dump_header,
+      (rtems_monitor_object_dump_fn)        rtems_monitor_mpci_dump,
+    },
+    { RTEMS_OBJECT_INIT_TASK,
+      (void *) 0,
+      sizeof(rtems_monitor_init_task_t),
+      (rtems_monitor_object_next_fn)        rtems_monitor_init_task_next,
+      (rtems_monitor_object_canonical_fn)   rtems_monitor_init_task_canonical,
+      (rtems_monitor_object_dump_header_fn) rtems_monitor_init_task_dump_header,
+      (rtems_monitor_object_dump_fn)        rtems_monitor_init_task_dump,
+    },
+    { RTEMS_OBJECT_TASK,
+      (void *) &_Thread_Information,
+      sizeof(rtems_monitor_task_t),
+      (rtems_monitor_object_next_fn)        rtems_monitor_manager_next,
+      (rtems_monitor_object_canonical_fn)   rtems_monitor_task_canonical,
+      (rtems_monitor_object_dump_header_fn) rtems_monitor_task_dump_header,
+      (rtems_monitor_object_dump_fn)        rtems_monitor_task_dump,
+    },
+    { RTEMS_OBJECT_QUEUE,
+      (void *) &_Message_queue_Information,
+      sizeof(rtems_monitor_queue_t),
+      (rtems_monitor_object_next_fn)        rtems_monitor_manager_next,
+      (rtems_monitor_object_canonical_fn)   rtems_monitor_queue_canonical,
+      (rtems_monitor_object_dump_header_fn) rtems_monitor_queue_dump_header,
+      (rtems_monitor_object_dump_fn)        rtems_monitor_queue_dump,
+    },
+    { RTEMS_OBJECT_EXTENSION,
+      (void *) &_Extension_Information,
+      sizeof(rtems_monitor_extension_t),
+      (rtems_monitor_object_next_fn)        rtems_monitor_manager_next,
+      (rtems_monitor_object_canonical_fn)   rtems_monitor_extension_canonical,
+      (rtems_monitor_object_dump_header_fn) rtems_monitor_extension_dump_header,
+      (rtems_monitor_object_dump_fn)        rtems_monitor_extension_dump,
+    },
+    { RTEMS_OBJECT_DRIVER,
+      (void *) 0,
+      sizeof(rtems_monitor_driver_t),
+      (rtems_monitor_object_next_fn)        rtems_monitor_driver_next,
+      (rtems_monitor_object_canonical_fn)   rtems_monitor_driver_canonical,
+      (rtems_monitor_object_dump_header_fn) rtems_monitor_driver_dump_header,
+      (rtems_monitor_object_dump_fn)        rtems_monitor_driver_dump,
+    },
+    { RTEMS_OBJECT_DNAME,
+      (void *) &rtems_driver_name_table[0],
+      sizeof(rtems_monitor_dname_t),
+      (rtems_monitor_object_next_fn)        rtems_monitor_dname_next,
+      (rtems_monitor_object_canonical_fn)   rtems_monitor_dname_canonical,
+      (rtems_monitor_object_dump_header_fn) rtems_monitor_dname_dump_header,
+      (rtems_monitor_object_dump_fn)        rtems_monitor_dname_dump,
+    },
+};
+
+/*
+ * Allow id's to be specified without the node number or
+ * type for convenience.
+ */
+
+rtems_id
+rtems_monitor_id_fixup(
+    rtems_id            id,
+    unsigned32          default_node,
+    rtems_object_type_t type
+)
+{
+    unsigned32  node;
+    
+    node = rtems_get_node(id);
+    if (node == 0)
+    {
+#if 0
+        /* XXX Uncomment this when types are added to id's */
+        if (rtems_get_type(id) != RTEMS_OBJECT_INVALID)
+            type = rtems_get_type(id);
+
+        id = _Objects_Build_id(type, default_node, rtems_get_index(id));
+#else
+        id = _Objects_Build_id(default_node, rtems_get_index(id));
+#endif
+    }
+    return id;
+}
+
+
+rtems_monitor_object_info_t *
+rtems_monitor_object_lookup(
+    rtems_object_type_t type
+)
+{
+    rtems_monitor_object_info_t *p;
+    for (p = &rtems_monitor_object_info[0];
+         p < &rtems_monitor_object_info[NUMELEMS(rtems_monitor_object_info)];
+         p++)
+    {
+        if (p->type == type)
+            return p;
+    }
+    return 0;
+}
+
+rtems_id
+rtems_monitor_object_canonical_next_remote(
+    rtems_object_type_t type,
+    rtems_id            id,
+    void               *canonical
+)
+{
+    rtems_id                        next_id;
+    rtems_status_code               status;
+    rtems_monitor_server_request_t  request;
+    rtems_monitor_server_response_t response;
+
+    /*
+     * Send request
+     */
+    
+    request.command = RTEMS_MONITOR_SERVER_CANONICAL;
+    request.argument0 = (unsigned32) type;
+    request.argument1 = (unsigned32) id;
+
+    status = rtems_monitor_server_request(rtems_get_node(id), &request, &response);
+    if (status != RTEMS_SUCCESSFUL)
+        goto failed;
+
+    /*
+     * process response
+     */
+    
+    next_id = (rtems_id) response.result0;
+    if (next_id != RTEMS_OBJECT_ID_FINAL)
+        (void) memcpy(canonical, &response.payload, response.result1);
+
+    return next_id;
+
+failed:
+    return RTEMS_OBJECT_ID_FINAL;
+
+}
+
+
+rtems_id
+rtems_monitor_object_canonical_next(
+    rtems_monitor_object_info_t *info,
+    rtems_id                     id,
+    void                        *canonical
+)
+{
+    rtems_id                     next_id;
+    void                        *raw_item;
+
+    if ( ! _Objects_Is_local_id(id))
+        next_id = rtems_monitor_object_canonical_next_remote(info->type,
+                                                             id,
+                                                             canonical);
+    else
+    {
+        next_id = id;
+        
+        raw_item = (void *) info->next(info->object_information,
+                                       canonical,
+                                       &next_id);
+
+        if (raw_item)
+        {
+            info->canonical(canonical, raw_item);
+            _Thread_Enable_dispatch();
+        }    
+    }    
+    return next_id;
+}
+
+
+/*
+ * this is routine server invokes locally to get the type
+ */
+
+rtems_id
+rtems_monitor_object_canonical_get(
+    rtems_object_type_t  type,
+    rtems_id             id,
+    void                *canonical,
+    unsigned32          *size_p
+)
+{
+    rtems_monitor_object_info_t *info;
+    rtems_id                     next_id;
+
+    *size_p = 0;
+
+    info = rtems_monitor_object_lookup(type);
+
+    if (info == 0)
+        return RTEMS_OBJECT_ID_FINAL;
+
+    next_id = rtems_monitor_object_canonical_next(info, id, canonical);
+    *size_p = info->size;
+
+    return next_id;
+}
+
+
+void
+rtems_monitor_object_dump_1(
+    rtems_monitor_object_info_t *info,
+    rtems_id                     id,
+    boolean                      verbose
+)
+{
+    rtems_id next_id;
+    rtems_monitor_union_t canonical;
+
+    if ((next_id = rtems_monitor_object_canonical_next(
+                                     info,
+                                     id,
+                                     &canonical)) != RTEMS_OBJECT_ID_FINAL)
+    {
+        /*
+         * If the one we actually got is the one we wanted, then
+         * print it out.
+         * For ones that have an id field, this works fine,
+         * for all others, always dump it out.
+         *
+         * HACK: the way we determine whether there is an id is a hack.
+         *
+         * by the way: the reason we try to not have an id, is that some
+         *   of the canonical structures are almost too big for shared
+         *   memory driver (eg: mpci)
+         */
+        
+        if ((info->next != rtems_monitor_manager_next) ||
+            (id == canonical.generic.id))
+            info->dump(&canonical, verbose);
+    }
+}
+
+void
+rtems_monitor_object_dump_all(
+    rtems_monitor_object_info_t *info,
+    boolean                      verbose
+)
+{
+    rtems_id next_id;
+    rtems_monitor_union_t canonical;
+
+    next_id = RTEMS_OBJECT_ID_INITIAL(rtems_monitor_default_node);
+
+    while ((next_id = rtems_monitor_object_canonical_next(
+                                         info,
+                                         next_id,
+                                         &canonical)) != RTEMS_OBJECT_ID_FINAL)
+    {
+        info->dump(&canonical, verbose);
+    }
+}
+
+void
+rtems_monitor_object_cmd(
+    int        argc,
+    char     **argv,
+    unsigned32 command_arg,
+    boolean    verbose
+)
+{
+    int arg;
+    rtems_monitor_object_info_t *info = 0;
+    rtems_object_type_t          type = (rtems_object_type_t) command_arg;
+    
+    /* what is the default type? */
+    type = (rtems_object_type_t) command_arg;
+
+    if (argc == 1)
+    {
+        if (type == RTEMS_OBJECT_INVALID)
+        {
+            printf("A type must be specified to \"dump all\"\n");
+            goto done;
+        }
+        
+        info = rtems_monitor_object_lookup(type);
+        if (info == 0)
+            goto not_found;
+
+        if (info->dump_header)
+            info->dump_header(verbose);
+        rtems_monitor_object_dump_all(info, verbose);
+    }
+    else
+    {
+        unsigned32          default_node = rtems_monitor_default_node;
+        rtems_object_type_t last_type = RTEMS_OBJECT_INVALID;
+        rtems_id            id;
+
+        for (arg=1; argv[arg]; arg++)
+        {
+            id = (rtems_id) strtoul(argv[arg], 0, 0);
+            id = rtems_monitor_id_fixup(id, default_node, type);
+#if 0
+            type = rtems_get_type(id);
+#endif
+            /*
+             * Allow the item type to change in the middle
+             * of the command.  If the type changes, then
+             * just dump out a new header and keep on going.
+             */
+            if (type != last_type)
+            {
+                info = rtems_monitor_object_lookup(type);
+                if (info == 0)
+                {
+not_found:          printf("Invalid or unsupported type %d\n", type);
+                    goto done;
+                }
+            
+                if (info->dump_header)
+                    info->dump_header(verbose);
+            }
+
+            rtems_monitor_object_dump_1(info, id, verbose);
+
+            default_node = rtems_get_node(id);
+            
+            last_type = type;
+        }
+    }
+done:
+}
