1 #include <linux/kernel.h>
3 #include <linux/proc_fs.h>
4 #include <asm-l/tree_entry.h>
7 #include "sbus_proc_tree.h"
9 static struct proc_dir_entry
*sbus_ent
= NULL
;
11 typedef knode_t node_t
;
13 node_t
*create_node(void)
15 node_t
*new_node
= kmalloc(sizeof(node_t
), GFP_KERNEL
);
19 new_node
->child
= NULL
;
20 new_node
->type
= NO_TYPE
;
21 new_node
->next
= NULL
;
26 void add_child(node_t
*parent
, node_t
*node
)
28 node
->parent
= parent
;
29 node
->depth
= parent
->depth
+ 1;
32 node_t
*sibling
= parent
->child
;
34 sibling
= sibling
->next
;
41 int build_sub_tree(node_t
*parent
, int prom_node
, int depth
, int type
)
47 while (prom_node
!= 0 && prom_node
!= -1) {
48 if ((node
= create_node()) == NULL
) {
49 pr_err("MCT_TREE:build_sub_tree:"
50 " Error memory allocation\n");
54 len
= (int)prom_getproperty(prom_node
, "name",
55 node
->name
, sizeof(node
->name
));
56 prom_getstring(prom_node
, "device_type",
57 node_str
, sizeof(node_str
));
59 if (!strcmp(node_str
, "cpu") ||
60 !strcmp(node
->name
, "memory") ||
61 !strcmp(node
->name
, "pcin")) {
70 if (strcmp(node
->name
, "sbus") == 0) {
75 len
= prom_getproperty(prom_node
, "reg",
76 (char *) node
->reg_addrs
,
77 sizeof(node
->reg_addrs
));
79 node
->num_registers
= 0;
83 if (len
% sizeof(struct linux_prom_registers
)) {
84 pr_err("fill_sbus_device: proplen for regs of %s "
85 " was %d, need multiple of %d\n",
87 (int) sizeof(struct linux_prom_registers
));
90 if (len
> (sizeof(struct linux_prom_registers
)*PROMREG_MAX
)) {
91 pr_err("fill_sbus_device: Too many register properties"
92 " for device %s, len=%d\n",
96 node
->num_registers
= len
/sizeof(struct linux_prom_registers
);
97 node
->ranges_applied
= 0;
99 /* Compute the slot number. */
100 node
->slot
= prom_getint(prom_node
, "slot");
101 if (node
->slot
== -1)
102 node
->slot
= node
->reg_addrs
[0].which_io
;
104 len
= prom_getproperty(prom_node
, "ranges",
105 (char *)node
->device_ranges
,
106 sizeof(node
->device_ranges
));
108 node
->num_device_ranges
= 0;
111 if (len
% sizeof(struct linux_prom_ranges
)) {
112 pr_err("fill_sbus_device: proplen for ranges of %s "
113 " was %d, need multiple of %d\n",
115 (int) sizeof(struct linux_prom_ranges
));
118 if (len
> (sizeof(struct linux_prom_ranges
) * PROMREG_MAX
)) {
119 pr_err("fill_sbus_device: Too many range properties "
120 "for device %s, len=%d\n",
124 node
->num_device_ranges
= len
/sizeof(struct linux_prom_ranges
);
126 add_child(parent
, node
);
128 if (prom_getchild(prom_node
)) {
129 build_sub_tree(node
, prom_getchild(prom_node
),
133 prom_node
= prom_getsibling(prom_node
);
138 int print_nodes(node_t
*node
, char *buf
, int len
)
143 if (!strcmp(node
->name
, ".")) {
145 len
= print_nodes(node
->child
, buf
, len
);
151 for (i
= 0; i
< node
->depth
; i
++) {
152 len
+= sprintf(buf
+len
, " ");
156 switch (node
->type
) {
158 len
+= sprintf(buf
+len
, "%s@0x%08x Slot %x\n",
160 node
->reg_addrs
[0].phys_addr
,
164 len
+= sprintf(buf
+len
, "%s\n", node
->name
);
170 len
= print_nodes(node
->child
, buf
, len
);
179 int proc_sbus_entry(char *buf
, char **start
,
180 off_t off
, int count
,
181 int *eof
, void *data
) {
183 node_t
*root
= (node_t
*)data
;
185 len
= print_nodes(root
->child
, buf
, len
);
191 void make_sbus_tree(void)
195 char proc_bus_path
[128] = "bus/sbus";
197 if ((tree_root
= create_node()) == NULL
) {
198 pr_err("MCT_TREE:do_build_tree: Error memory allocation\n");
201 tree_root
->depth
= 0;
202 tree_root
->slot
= -1;
204 root_node
= prom_getchild(prom_root_node
);
205 build_sub_tree(tree_root
, root_node
, 0, NO_TYPE
);
207 if ((sbus_ent
= proc_mkdir(proc_bus_path
, NULL
)) == NULL
)
210 create_proc_read_entry("devices",
217 static int __init
tree_init(void)
224 static void __exit
tree_destroy(void)
227 remove_proc_entry("devices", sbus_ent
);
231 subsys_initcall(tree_init
);
232 module_exit(tree_destroy
);
233 MODULE_LICENSE("GPL");