1 /* $Id: openpromfs.c,v 1.26 1998/01/28 09:55:32 ecd Exp $
2 * openpromfs.c: /proc/openprom handling routines
4 * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
7 #include <linux/module.h>
8 #include <linux/types.h>
9 #include <linux/string.h>
11 #include <linux/proc_fs.h>
12 #include <linux/init.h>
14 #include <asm/openprom.h>
15 #include <asm/oplib.h>
16 #include <asm/uaccess.h>
18 #define ALIASES_NNODES 64
29 #define OPP_STRING 0x10
30 #define OPP_BINARY 0x20
31 #define OPP_DIRTY 0x01
32 #define OPP_QUOTED 0x02
33 #define OPP_NOTQUOTED 0x04
34 #define OPP_ASCIIZ 0x08
42 static openpromfs_node
*nodes
= NULL
;
43 static int alloced
= 0;
44 static u16 last_node
= 0;
45 static u16 first_prop
= 0;
46 static u16 options
= 0xffff;
47 static u16 aliases
= 0xffff;
48 static int aliases_nodes
= 0;
49 static char *alias_names
[ALIASES_NNODES
];
50 static struct inode_operations
*proc_openprom_iops
= 0;
51 static struct openpromfs_dev
**devices
;
53 #define NODE(ino) nodes[ino - PROC_OPENPROM_FIRST]
54 #define NODE2INO(node) (node + PROC_OPENPROM_FIRST)
55 #define NODEP2INO(no) (no + PROC_OPENPROM_FIRST + last_node)
57 static int openpromfs_create (struct inode
*, struct dentry
*, int);
58 static int openpromfs_readdir(struct file
*, void *, filldir_t
);
59 static int openpromfs_lookup(struct inode
*, struct dentry
*dentry
);
60 static int openpromfs_unlink (struct inode
*, struct dentry
*dentry
);
62 static ssize_t
nodenum_read(struct file
*file
, char *buf
,
63 size_t count
, loff_t
*ppos
)
65 struct inode
*inode
= file
->f_dentry
->d_inode
;
68 if (count
< 0 || !inode
->u
.generic_ip
)
70 sprintf (buffer
, "%8.8x\n", (u32
)(long)(inode
->u
.generic_ip
));
73 if (count
> 9 - file
->f_pos
)
74 count
= 9 - file
->f_pos
;
75 copy_to_user(buf
, buffer
+ file
->f_pos
, count
);
80 static ssize_t
property_read(struct file
*filp
, char *buf
,
81 size_t count
, loff_t
*ppos
)
83 struct inode
*inode
= filp
->f_dentry
->d_inode
;
88 openprom_property
*op
;
91 if (filp
->f_pos
>= 0xffffff)
93 if (!filp
->private_data
) {
94 node
= nodes
[(u16
)((long)inode
->u
.generic_ip
)].node
;
95 i
= ((u32
)(long)inode
->u
.generic_ip
) >> 16;
96 if ((u16
)((long)inode
->u
.generic_ip
) == aliases
) {
97 if (i
>= aliases_nodes
)
102 for (p
= prom_firstprop (node
, buffer
);
104 p
= prom_nextprop (node
, p
, buffer
), i
--)
108 i
= prom_getproplen (node
, p
);
110 if ((u16
)((long)inode
->u
.generic_ip
) == aliases
)
117 filp
->private_data
= kmalloc (sizeof (openprom_property
)
118 + (j
= strlen (p
)) + 2 * i
,
120 if (!filp
->private_data
)
122 op
= (openprom_property
*)filp
->private_data
;
124 op
->alloclen
= 2 * i
;
125 strcpy (op
->name
, p
);
126 op
->value
= (char *)(((unsigned long)(op
->name
+ j
+ 4)) & ~3);
128 if (k
&& prom_getproperty (node
, p
, op
->value
, i
) < 0)
132 for (p
= op
->value
; *p
>= ' ' && *p
<= '~'; p
++);
133 if (p
>= op
->value
+ k
- 1 && !*p
) {
134 op
->flag
|= OPP_STRING
;
135 if (p
== op
->value
+ k
- 1) {
136 op
->flag
|= OPP_ASCIIZ
;
140 op
->flag
|= OPP_BINARY
;
142 printk ("/proc/openprom: Strange property "
148 op
= (openprom_property
*)filp
->private_data
;
149 if (!count
|| !op
->len
) return 0;
150 if (op
->flag
& OPP_STRING
)
153 i
= (op
->len
* 9)>>2;
155 if (k
>= i
) return 0;
156 if (count
> i
- k
) count
= i
- k
;
157 if (op
->flag
& OPP_STRING
) {
159 __put_user('\'', buf
);
163 if (k
+ count
>= i
- 2)
168 copy_to_user(buf
+ k
- filp
->f_pos
,
169 op
->value
+ k
- 1, j
);
174 __put_user('\'', &buf
[k
++ - filp
->f_pos
]);
176 __put_user('\n', &buf
[k
++ - filp
->f_pos
]);
177 } else if (op
->flag
& OPP_BINARY
) {
180 int first_off
, last_cnt
;
182 first
= ((u32
*)op
->value
) + k
/ 9;
184 last
= ((u32
*)op
->value
) + (k
+ count
- 1) / 9;
185 last_cnt
= (k
+ count
) % 9;
186 if (!last_cnt
) last_cnt
= 9;
189 sprintf (buffer
, "%08x.", *first
);
190 copy_to_user (buf
, buffer
+ first_off
, last_cnt
- first_off
);
191 buf
+= last_cnt
- first_off
;
193 for (q
= first
; q
<= last
; q
++) {
194 sprintf (buffer
, "%08x.", *q
);
196 copy_to_user (buf
, buffer
+ first_off
,
198 buf
+= 9 - first_off
;
199 } else if (q
== last
) {
200 copy_to_user (buf
, buffer
, last_cnt
);
203 copy_to_user (buf
, buffer
, 9);
208 if (last
== (u32
*)(op
->value
+ op
->len
- 4) && last_cnt
== 9)
209 __put_user('\n', (buf
- 1));
212 count
= k
- filp
->f_pos
;
217 static ssize_t
property_write(struct file
*filp
, const char *buf
,
218 size_t count
, loff_t
*ppos
)
224 openprom_property
*op
;
226 if (filp
->f_pos
>= 0xffffff)
228 if (!filp
->private_data
) {
229 i
= property_read (filp
, NULL
, 0, 0);
234 op
= (openprom_property
*)filp
->private_data
;
235 if (!(op
->flag
& OPP_STRING
)) {
237 int first_off
, last_cnt
;
243 for (i
= 0; i
< count
; i
++, j
++) {
247 __get_user(ctmp
, &buf
[i
]);
250 if (op
->flag
& OPP_BINARY
)
253 goto write_try_string
;
262 __get_user(ctmp
, &buf
[i
]);
264 (ctmp
> '9' && ctmp
< 'A') ||
265 (ctmp
> 'F' && ctmp
< 'a') ||
267 if (op
->flag
& OPP_BINARY
)
270 goto write_try_string
;
274 op
->flag
|= OPP_BINARY
;
276 i
= ((count
+ k
+ 8) / 9) << 2;
277 if (op
->alloclen
<= i
) {
278 b
= kmalloc (sizeof (openprom_property
) + 2 * i
,
282 memcpy (b
, filp
->private_data
,
283 sizeof (openprom_property
)
284 + strlen (op
->name
) + op
->alloclen
);
285 memset (((char *)b
) + sizeof (openprom_property
)
286 + strlen (op
->name
) + op
->alloclen
,
287 0, 2 * i
- op
->alloclen
);
288 op
= (openprom_property
*)b
;
290 b
= filp
->private_data
;
291 filp
->private_data
= (void *)op
;
294 first
= ((u32
*)op
->value
) + (k
/ 9);
296 last
= (u32
*)(op
->value
+ i
);
297 last_cnt
= (k
+ count
) % 9;
298 if (first
+ 1 == last
) {
299 memset (tmp
, '0', 8);
300 copy_from_user (tmp
+ first_off
, buf
,
301 (count
+ first_off
> 8) ? 8 - first_off
: count
);
304 for (j
= 0; j
< first_off
; j
++)
306 for (j
= 8 - count
- first_off
; j
> 0; j
--)
311 *first
|= simple_strtoul (tmp
, 0, 16);
312 op
->flag
|= OPP_DIRTY
;
315 op
->flag
|= OPP_DIRTY
;
316 for (q
= first
; q
< last
; q
++) {
319 memset (tmp
, '0', 8);
320 copy_from_user (tmp
+ first_off
, buf
,
323 for (j
= 0; j
< first_off
; j
++)
326 *q
|= simple_strtoul (tmp
,0,16);
329 } else if ((q
== last
- 1) && last_cnt
331 memset (tmp
, '0', 8);
332 copy_from_user (tmp
, buf
, last_cnt
);
334 for (j
= 0; j
< 8 - last_cnt
; j
++)
337 *q
|= simple_strtoul (tmp
, 0, 16);
340 char tchars
[17]; /* XXX yuck... */
342 copy_from_user(tchars
, buf
, 16);
343 *q
= simple_strtoul (tchars
, 0, 16);
353 filp
->f_pos
+= count
;
356 if (!(op
->flag
& OPP_BINARY
)) {
357 if (!(op
->flag
& (OPP_QUOTED
| OPP_NOTQUOTED
))) {
360 /* No way, if somebody starts writing from the middle,
361 * we don't know whether he uses quotes around or not
365 __get_user(ctmp
, buf
);
367 op
->flag
|= OPP_QUOTED
;
372 op
->flag
|= OPP_STRING
;
376 op
->flag
|= OPP_NOTQUOTED
;
378 op
->flag
|= OPP_STRING
;
379 if (op
->alloclen
<= count
+ filp
->f_pos
) {
380 b
= kmalloc (sizeof (openprom_property
)
381 + 2 * (count
+ filp
->f_pos
), GFP_KERNEL
);
384 memcpy (b
, filp
->private_data
,
385 sizeof (openprom_property
)
386 + strlen (op
->name
) + op
->alloclen
);
387 memset (((char *)b
) + sizeof (openprom_property
)
388 + strlen (op
->name
) + op
->alloclen
,
389 0, 2*(count
- filp
->f_pos
) - op
->alloclen
);
390 op
= (openprom_property
*)b
;
391 op
->alloclen
= 2*(count
+ filp
->f_pos
);
392 b
= filp
->private_data
;
393 filp
->private_data
= (void *)op
;
396 p
= op
->value
+ filp
->f_pos
- ((op
->flag
& OPP_QUOTED
) ? 1 : 0);
397 copy_from_user (p
, buf
, count
);
398 op
->flag
|= OPP_DIRTY
;
399 for (i
= 0; i
< count
; i
++, p
++)
405 op
->len
= p
- op
->value
;
406 filp
->f_pos
+= i
+ 1;
407 if ((p
> op
->value
) && (op
->flag
& OPP_QUOTED
)
408 && (*(p
- 1) == '\''))
411 if (p
- op
->value
> op
->len
)
412 op
->len
= p
- op
->value
;
413 filp
->f_pos
+= count
;
416 return filp
->f_pos
- k
;
419 int property_release (struct inode
*inode
, struct file
*filp
)
421 openprom_property
*op
= (openprom_property
*)filp
->private_data
;
428 node
= nodes
[(u16
)((long)inode
->u
.generic_ip
)].node
;
429 if ((u16
)((long)inode
->u
.generic_ip
) == aliases
) {
430 if ((op
->flag
& OPP_DIRTY
) && (op
->flag
& OPP_STRING
)) {
432 int i
= (op
->value
- op
->name
) - strlen (op
->name
) - 1;
433 op
->value
[op
->len
] = 0;
434 *(op
->value
- 1) = ' ';
436 for (p
= op
->value
- i
- 2; p
>= op
->name
; p
--)
440 memcpy (p
- 8, "nvalias ", 8);
443 } else if (op
->flag
& OPP_DIRTY
) {
444 if (op
->flag
& OPP_STRING
) {
445 op
->value
[op
->len
] = 0;
446 save_and_cli (flags
);
447 error
= prom_setprop (node
, op
->name
,
448 op
->value
, op
->len
+ 1);
449 restore_flags (flags
);
451 printk (KERN_WARNING
"/proc/openprom: "
452 "Couldn't write property %s\n",
454 } else if ((op
->flag
& OPP_BINARY
) || !op
->len
) {
455 save_and_cli (flags
);
456 error
= prom_setprop (node
, op
->name
,
458 restore_flags (flags
);
460 printk (KERN_WARNING
"/proc/openprom: "
461 "Couldn't write property %s\n",
464 printk (KERN_WARNING
"/proc/openprom: "
465 "Unknown property type of %s\n",
469 kfree (filp
->private_data
);
473 static struct file_operations openpromfs_prop_ops
= {
474 NULL
, /* lseek - default */
475 property_read
, /* read */
476 property_write
, /* write - bad */
478 NULL
, /* poll - default */
479 NULL
, /* ioctl - default */
481 NULL
, /* no special open code */
483 property_release
, /* no special release code */
484 NULL
/* can't fsync */
487 static struct inode_operations openpromfs_prop_inode_ops
= {
488 &openpromfs_prop_ops
, /* default property file-ops */
499 NULL
, /* follow_link */
501 NULL
, /* writepage */
504 NULL
/* permission */
507 static struct file_operations openpromfs_nodenum_ops
= {
508 NULL
, /* lseek - default */
509 nodenum_read
, /* read */
510 NULL
, /* write - bad */
512 NULL
, /* poll - default */
513 NULL
, /* ioctl - default */
515 NULL
, /* no special open code */
517 NULL
, /* no special release code */
518 NULL
/* can't fsync */
521 static struct inode_operations openpromfs_nodenum_inode_ops
= {
522 &openpromfs_nodenum_ops
,/* default .node file-ops */
533 NULL
, /* follow_link */
535 NULL
, /* writepage */
538 NULL
/* permission */
541 static struct file_operations openprom_alias_operations
= {
542 NULL
, /* lseek - default */
543 NULL
, /* read - bad */
544 NULL
, /* write - bad */
545 openpromfs_readdir
, /* readdir */
546 NULL
, /* poll - default */
547 NULL
, /* ioctl - default */
549 NULL
, /* no special open code */
551 NULL
, /* no special release code */
552 NULL
/* can't fsync */
555 static struct inode_operations openprom_alias_inode_operations
= {
556 &openprom_alias_operations
,/* default aliases directory file-ops */
557 openpromfs_create
, /* create */
558 openpromfs_lookup
, /* lookup */
560 openpromfs_unlink
, /* unlink */
567 NULL
, /* follow_link */
569 NULL
, /* writepage */
572 NULL
/* permission */
575 static int lookup_children(u16 n
, const char * name
, int len
)
579 for (; n
!= 0xffff; n
= nodes
[n
].next
) {
580 node
= nodes
[n
].child
;
581 if (node
!= 0xffff) {
586 while (node
!= 0xffff) {
587 if (prom_getname (nodes
[node
].node
,
591 && !strncmp (buffer
, name
, len
))
592 return NODE2INO(node
);
593 p
= strchr (buffer
, '@');
594 if (p
&& (len
== p
- buffer
)
595 && !strncmp (buffer
, name
, len
))
596 return NODE2INO(node
);
598 node
= nodes
[node
].next
;
602 ret
= lookup_children (nodes
[n
].child
, name
, len
);
608 static int openpromfs_lookup(struct inode
* dir
, struct dentry
*dentry
)
612 #define OPFSL_PROPERTY 1
613 #define OPFSL_NODENUM 2
614 #define OPFSL_DEVICE 3
624 struct openpromfs_dev
*d
= NULL
;
628 name
= dentry
->d_name
.name
;
629 len
= dentry
->d_name
.len
;
630 if (name
[0] == '.' && len
== 5 && !strncmp (name
+ 1, "node", 4)) {
631 ino
= NODEP2INO(NODE(dir
->i_ino
).first_prop
);
632 type
= OPFSL_NODENUM
;
635 u16 node
= NODE(dir
->i_ino
).child
;
636 while (node
!= 0xffff) {
637 if (prom_getname (nodes
[node
].node
, buffer
, 128) >= 0) {
639 if (len
== i
&& !strncmp (buffer
, name
, len
)) {
640 ino
= NODE2INO(node
);
644 p
= strchr (buffer
, '@');
645 if (p
&& (len
== p
- buffer
)
646 && !strncmp (buffer
, name
, len
)) {
647 ino
= NODE2INO(node
);
652 node
= nodes
[node
].next
;
655 n
= NODE(dir
->i_ino
).node
;
656 dirnode
= dir
->i_ino
- PROC_OPENPROM_FIRST
;
658 int j
= NODEP2INO(NODE(dir
->i_ino
).first_prop
);
659 if (dirnode
!= aliases
) {
660 for (p
= prom_firstprop (n
, buffer2
);
662 p
= prom_nextprop (n
, p
, buffer2
)) {
664 if ((len
== strlen (p
))
665 && !strncmp (p
, name
, len
)) {
667 type
= OPFSL_PROPERTY
;
673 for (k
= 0; k
< aliases_nodes
; k
++) {
676 && (len
== strlen (alias_names
[k
]))
677 && !strncmp (alias_names
[k
], name
, len
)) {
679 type
= OPFSL_PROPERTY
;
686 for (d
= *devices
; d
; d
= d
->next
)
687 if ((d
->node
== n
) && (strlen (d
->name
) == len
)
688 && !strncmp (d
->name
, name
, len
)) {
695 ino
= lookup_children (NODE(dir
->i_ino
).child
, name
, len
);
701 inode
= proc_get_inode (dir
->i_sb
, ino
, 0);
706 inode
->i_mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
;
707 if (ino
== PROC_OPENPROM_FIRST
+ aliases
) {
708 inode
->i_mode
|= S_IWUSR
;
709 inode
->i_op
= &openprom_alias_inode_operations
;
711 inode
->i_op
= proc_openprom_iops
;
715 inode
->i_mode
= S_IFREG
| S_IRUGO
;
716 inode
->i_op
= &openpromfs_nodenum_inode_ops
;
718 inode
->u
.generic_ip
= (void *)(long)(n
);
721 if ((dirnode
== options
) && (len
== 17)
722 && !strncmp (name
, "security-password", 17))
723 inode
->i_mode
= S_IFREG
| S_IRUSR
| S_IWUSR
;
725 inode
->i_mode
= S_IFREG
| S_IRUGO
;
726 if (dirnode
== options
|| dirnode
== aliases
) {
727 if (len
!= 4 || strncmp (name
, "name", 4))
728 inode
->i_mode
|= S_IWUSR
;
731 inode
->i_op
= &openpromfs_prop_inode_ops
;
733 if (inode
->i_size
< 0)
735 inode
->u
.generic_ip
= (void *)(long)(((u16
)dirnode
) |
736 (((u16
)(ino
- NODEP2INO(NODE(dir
->i_ino
).first_prop
) - 1)) << 16));
739 inode
->i_mode
= d
->mode
;
740 inode
->i_op
= &chrdev_inode_operations
;
742 inode
->i_rdev
= d
->rdev
;
745 d_add(dentry
, inode
);
749 static int openpromfs_readdir(struct file
* filp
, void * dirent
, filldir_t filldir
)
751 struct inode
*inode
= filp
->f_dentry
->d_inode
;
758 struct openpromfs_dev
*d
;
761 if (!inode
|| !S_ISDIR (inode
->i_mode
)) return -ENOTDIR
;
766 if (filldir(dirent
, ".", 1, i
, ino
) < 0) return 0;
771 if (filldir(dirent
, "..", 2, i
,
772 (NODE(ino
).parent
== 0xffff) ?
773 PROC_ROOT_INO
: NODE2INO(NODE(ino
).parent
)) < 0)
780 node
= NODE(ino
).child
;
781 while (i
&& node
!= 0xffff) {
782 node
= nodes
[node
].next
;
785 while (node
!= 0xffff) {
786 if (prom_getname (nodes
[node
].node
, buffer
, 128) < 0)
788 if (filldir(dirent
, buffer
, strlen(buffer
),
789 filp
->f_pos
, NODE2INO(node
)) < 0)
792 node
= nodes
[node
].next
;
794 j
= NODEP2INO(NODE(ino
).first_prop
);
796 if (filldir(dirent
, ".node", 5, filp
->f_pos
, j
) < 0)
802 if (ino
== PROC_OPENPROM_FIRST
+ aliases
) {
803 for (j
++; i
< aliases_nodes
; i
++, j
++) {
804 if (alias_names
[i
]) {
805 if (filldir (dirent
, alias_names
[i
],
806 strlen (alias_names
[i
]),
807 filp
->f_pos
, j
) < 0) return 0;
812 for (p
= prom_firstprop (n
, buffer2
);
814 p
= prom_nextprop (n
, p
, buffer2
)) {
818 if (filldir(dirent
, p
, strlen(p
),
825 for (d
= *devices
; d
; d
= d
->next
) {
829 if (filldir(dirent
, d
->name
,
831 filp
->f_pos
, d
->inode
) < 0)
841 static int openpromfs_create (struct inode
*dir
, struct dentry
*dentry
, int mode
)
848 if (dentry
->d_name
.len
> 256)
850 if (aliases_nodes
== ALIASES_NNODES
)
852 p
= kmalloc (dentry
->d_name
.len
+ 1, GFP_KERNEL
);
855 strncpy (p
, dentry
->d_name
.name
, dentry
->d_name
.len
);
856 p
[dentry
->d_name
.len
] = 0;
857 alias_names
[aliases_nodes
++] = p
;
858 inode
= proc_get_inode (dir
->i_sb
,
859 NODEP2INO(NODE(dir
->i_ino
).first_prop
)
863 inode
->i_mode
= S_IFREG
| S_IRUGO
| S_IWUSR
;
864 inode
->i_op
= &openpromfs_prop_inode_ops
;
866 if (inode
->i_size
< 0) inode
->i_size
= 0;
867 inode
->u
.generic_ip
= (void *)(long)(((u16
)aliases
) |
868 (((u16
)(aliases_nodes
- 1)) << 16));
869 d_instantiate(dentry
, inode
);
873 static int openpromfs_unlink (struct inode
*dir
, struct dentry
*dentry
)
880 name
= dentry
->d_name
.name
;
881 len
= dentry
->d_name
.len
;
882 for (i
= 0; i
< aliases_nodes
; i
++)
883 if ((strlen (alias_names
[i
]) == len
)
884 && !strncmp (name
, alias_names
[i
], len
)) {
888 alias_names
[i
] = NULL
;
890 strcpy (buffer
, "nvunalias ");
891 memcpy (buffer
+ 10, name
, len
);
892 buffer
[10 + len
] = 0;
899 /* {{{ init section */
901 __initfunc(static int check_space (u16 n
))
903 static int check_space (u16 n
)
908 if ((1 << alloced
) * PAGE_SIZE
< (n
+ 2) * sizeof(openpromfs_node
)) {
909 pages
= __get_free_pages (GFP_KERNEL
, alloced
+ 1);
914 memcpy ((char *)pages
, (char *)nodes
,
915 (1 << alloced
) * PAGE_SIZE
);
916 free_pages ((unsigned long)nodes
, alloced
);
919 nodes
= (openpromfs_node
*)pages
;
925 __initfunc(static u16
get_nodes (u16 parent
, u32 node
))
927 static u16
get_nodes (u16 parent
, u32 node
)
931 u16 n
= last_node
++, i
;
934 if (check_space (n
) < 0)
936 nodes
[n
].parent
= parent
;
937 nodes
[n
].node
= node
;
938 nodes
[n
].next
= 0xffff;
939 nodes
[n
].child
= 0xffff;
940 nodes
[n
].first_prop
= first_prop
++;
945 if ((j
= prom_getproperty (node
, "name", buffer
, 8)) >= 0) {
947 if (!strcmp (buffer
, "options"))
949 else if (!strcmp (buffer
, "aliases"))
954 for (p
= prom_firstprop (node
, buffer
);
955 p
&& p
!= (char *)-1 && *p
;
956 p
= prom_nextprop (node
, p
, buffer
))
960 for (p
= prom_firstprop (node
, buffer
);
961 p
&& p
!= (char *)-1 && *p
;
962 p
= prom_nextprop (node
, p
, buffer
)) {
963 if (aliases_nodes
== ALIASES_NNODES
)
965 for (i
= 0; i
< aliases_nodes
; i
++)
966 if (!strcmp (p
, alias_names
[i
]))
968 if (i
< aliases_nodes
)
970 q
= kmalloc (strlen (p
) + 1, GFP_KERNEL
);
974 alias_names
[aliases_nodes
++] = q
;
976 first_prop
+= ALIASES_NNODES
;
978 node
= prom_getchild (node
);
980 parent
= get_nodes (n
, node
);
981 if (parent
== 0xffff)
983 nodes
[n
].child
= parent
;
984 while ((node
= prom_getsibling (node
)) != 0) {
985 i
= get_nodes (n
, node
);
988 nodes
[parent
].next
= i
;
997 void openpromfs_use (struct inode
*inode
, int inc
)
999 static int root_fresh
= 1;
1000 static int dec_first
= 1;
1001 #ifdef OPENPROM_DEBUGGING
1002 static int usec
= 0;
1005 if (inode
->i_count
== 1)
1007 else if (root_fresh
&& inode
->i_ino
== PROC_OPENPROM_FIRST
) {
1012 if (inode
->i_ino
== PROC_OPENPROM_FIRST
)
1017 printk ("openpromfs_use: %d %d %d %d\n",
1018 inode
->i_ino
, inc
, usec
, inode
->i_count
);
1021 if (inode
->i_count
== 1)
1023 else if (root_fresh
&& inode
->i_ino
== PROC_OPENPROM_FIRST
) {
1028 if (inode
->i_ino
== PROC_OPENPROM_FIRST
)
1038 #define openpromfs_use 0
1043 __initfunc(void openpromfs_init (void))
1049 int init_module (void)
1052 nodes
= (openpromfs_node
*)__get_free_pages(GFP_KERNEL
, 0);
1054 printk (KERN_WARNING
"/proc/openprom: can't get free page\n");
1057 if (get_nodes (0xffff, prom_root_node
) == 0xffff) {
1058 printk (KERN_WARNING
"/proc/openprom: couldn't setup tree\n");
1061 nodes
[last_node
].first_prop
= first_prop
;
1062 proc_openprom_iops
= proc_openprom_register (openpromfs_readdir
,
1070 void cleanup_module (void)
1073 proc_openprom_deregister ();
1074 free_pages ((unsigned long)nodes
, alloced
);
1075 for (i
= 0; i
< aliases_nodes
; i
++)
1076 if (alias_names
[i
])
1077 kfree (alias_names
[i
]);