~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/proc/proc_devtree.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * proc_devtree.c - handles /proc/device-tree
  3  *
  4  * Copyright 1997 Paul Mackerras
  5  */
  6 #include <linux/errno.h>
  7 #include <linux/sched.h>
  8 #include <linux/proc_fs.h>
  9 #include <linux/stat.h>
 10 #include <linux/string.h>
 11 #include <asm/prom.h>
 12 #include <asm/uaccess.h>
 13 
 14 static struct proc_dir_entry *proc_device_tree;
 15 
 16 /*
 17  * Supply data on a read from /proc/device-tree/node/property.
 18  */
 19 static int property_read_proc(char *page, char **start, off_t off,
 20                               int count, int *eof, void *data)
 21 {
 22         struct property *pp = data;
 23         int n;
 24 
 25         if (off >= pp->length) {
 26                 *eof = 1;
 27                 return 0;
 28         }
 29         n = pp->length - off;
 30         if (n > count)
 31                 n = count;
 32         else
 33                 *eof = 1;
 34         memcpy(page, pp->value + off, n);
 35         *start = page;
 36         return n;
 37 }
 38 
 39 /*
 40  * For a node with a name like "gc@10", we make symlinks called "gc"
 41  * and "@10" to it.
 42  */
 43 
 44 /*
 45  * Process a node, adding entries for its children and its properties.
 46  */
 47 static void add_node(struct device_node *np, struct proc_dir_entry *de)
 48 {
 49         struct property *pp;
 50         struct proc_dir_entry *ent;
 51         struct device_node *child, *sib;
 52         const char *p, *at;
 53         int l;
 54         struct proc_dir_entry *list, **lastp, *al;
 55 
 56         lastp = &list;
 57         for (pp = np->properties; pp != 0; pp = pp->next) {
 58                 /*
 59                  * Unfortunately proc_register puts each new entry
 60                  * at the beginning of the list.  So we rearrange them.
 61                  */
 62                 ent = create_proc_read_entry(pp->name, S_IRUGO, de,
 63                                              property_read_proc, pp);
 64                 if (ent == 0)
 65                         break;
 66                 ent->size = pp->length;
 67                 *lastp = ent;
 68                 lastp = &ent->next;
 69         }
 70         for (child = np->child; child != 0; child = child->sibling) {
 71                 p = strrchr(child->full_name, '/');
 72                 if (p == 0)
 73                         p = child->full_name;
 74                 else
 75                         ++p;
 76                 /* chop off '@0' if the name ends with that */
 77                 l = strlen(p);
 78                 if (l > 2 && p[l-2] == '@' && p[l-1] == '')
 79                         l -= 2;
 80                 ent = proc_mkdir(p, de);
 81                 if (ent == 0)
 82                         break;
 83                 *lastp = ent;
 84                 lastp = &ent->next;
 85                 add_node(child, ent);
 86 
 87                 /*
 88                  * If we left the address part on the name, consider
 89                  * adding symlinks from the name and address parts.
 90                  */
 91                 if (p[l] != 0 || (at = strchr(p, '@')) == 0)
 92                         continue;
 93 
 94                 /*
 95                  * If this is the first node with a given name property,
 96                  * add a symlink with the name property as its name.
 97                  */
 98                 for (sib = np->child; sib != child; sib = sib->sibling)
 99                         if (sib->name && strcmp(sib->name, child->name) == 0)
100                                 break;
101                 if (sib == child && strncmp(p, child->name, l) != 0) {
102                         al = proc_symlink(child->name, de, ent->name);
103                         if (al == 0)
104                                 break;
105                         *lastp = al;
106                         lastp = &al->next;
107                 }
108 
109                 /*
110                  * Add another directory with the @address part as its name.
111                  */
112                 al = proc_symlink(at, de, ent->name);
113                 if (al == 0)
114                         break;
115                 *lastp = al;
116                 lastp = &al->next;
117         }
118         *lastp = 0;
119         de->subdir = list;
120 }
121 
122 /*
123  * Called on initialization to set up the /proc/device-tree subtree
124  */
125 void proc_device_tree_init(void)
126 {
127         struct device_node *root;
128         if ( !have_of )
129                 return;
130         proc_device_tree = proc_mkdir("device-tree", 0);
131         if (proc_device_tree == 0)
132                 return;
133         root = find_path_device("/");
134         if (root == 0) {
135                 printk(KERN_ERR "/proc/device-tree: can't find root\n");
136                 return;
137         }
138         add_node(root, proc_device_tree);
139 }
140 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.