aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sparc/kernel/of_device.c2
-rw-r--r--arch/sparc/kernel/prom.c106
-rw-r--r--arch/sparc/lib/Makefile2
-rw-r--r--arch/sparc/lib/iomap.c48
-rw-r--r--arch/sparc64/kernel/auxio.c3
-rw-r--r--arch/sparc64/kernel/irq.c61
-rw-r--r--arch/sparc64/kernel/of_device.c3
-rw-r--r--arch/sparc64/kernel/prom.c107
-rw-r--r--arch/sparc64/mm/init.c1
-rw-r--r--drivers/mtd/maps/sun_uflash.c195
-rw-r--r--drivers/parport/parport_sunbpp.c2
-rw-r--r--drivers/sbus/char/cpwatchdog.c2
-rw-r--r--drivers/sbus/char/openprom.c593
-rw-r--r--drivers/sbus/char/riowatchdog.c4
-rw-r--r--fs/openpromfs/inode.c1158
-rw-r--r--include/asm-sparc/io.h16
-rw-r--r--include/asm-sparc/prom.h10
-rw-r--r--include/asm-sparc64/dma-mapping.h43
-rw-r--r--include/asm-sparc64/floppy.h50
-rw-r--r--include/asm-sparc64/prom.h10
20 files changed, 1053 insertions, 1363 deletions
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c
index 001b8673b4bd..80a809478781 100644
--- a/arch/sparc/kernel/of_device.c
+++ b/arch/sparc/kernel/of_device.c
@@ -138,6 +138,7 @@ struct bus_type ebus_bus_type = {
138 .suspend = of_device_suspend, 138 .suspend = of_device_suspend,
139 .resume = of_device_resume, 139 .resume = of_device_resume,
140}; 140};
141EXPORT_SYMBOL(ebus_bus_type);
141#endif 142#endif
142 143
143#ifdef CONFIG_SBUS 144#ifdef CONFIG_SBUS
@@ -149,6 +150,7 @@ struct bus_type sbus_bus_type = {
149 .suspend = of_device_suspend, 150 .suspend = of_device_suspend,
150 .resume = of_device_resume, 151 .resume = of_device_resume,
151}; 152};
153EXPORT_SYMBOL(sbus_bus_type);
152#endif 154#endif
153 155
154static int __init of_bus_driver_init(void) 156static int __init of_bus_driver_init(void)
diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c
index 63b2b9bd778e..946ce6d15819 100644
--- a/arch/sparc/kernel/prom.c
+++ b/arch/sparc/kernel/prom.c
@@ -27,6 +27,11 @@
27 27
28static struct device_node *allnodes; 28static struct device_node *allnodes;
29 29
30/* use when traversing tree through the allnext, child, sibling,
31 * or parent members of struct device_node.
32 */
33static DEFINE_RWLOCK(devtree_lock);
34
30int of_device_is_compatible(struct device_node *device, const char *compat) 35int of_device_is_compatible(struct device_node *device, const char *compat)
31{ 36{
32 const char* cp; 37 const char* cp;
@@ -185,6 +190,54 @@ int of_getintprop_default(struct device_node *np, const char *name, int def)
185} 190}
186EXPORT_SYMBOL(of_getintprop_default); 191EXPORT_SYMBOL(of_getintprop_default);
187 192
193int of_set_property(struct device_node *dp, const char *name, void *val, int len)
194{
195 struct property **prevp;
196 void *new_val;
197 int err;
198
199 new_val = kmalloc(len, GFP_KERNEL);
200 if (!new_val)
201 return -ENOMEM;
202
203 memcpy(new_val, val, len);
204
205 err = -ENODEV;
206
207 write_lock(&devtree_lock);
208 prevp = &dp->properties;
209 while (*prevp) {
210 struct property *prop = *prevp;
211
212 if (!strcmp(prop->name, name)) {
213 void *old_val = prop->value;
214 int ret;
215
216 ret = prom_setprop(dp->node, name, val, len);
217 err = -EINVAL;
218 if (ret >= 0) {
219 prop->value = new_val;
220 prop->length = len;
221
222 if (OF_IS_DYNAMIC(prop))
223 kfree(old_val);
224
225 OF_MARK_DYNAMIC(prop);
226
227 err = 0;
228 }
229 break;
230 }
231 prevp = &(*prevp)->next;
232 }
233 write_unlock(&devtree_lock);
234
235 /* XXX Upate procfs if necessary... */
236
237 return err;
238}
239EXPORT_SYMBOL(of_set_property);
240
188static unsigned int prom_early_allocated; 241static unsigned int prom_early_allocated;
189 242
190static void * __init prom_early_alloc(unsigned long size) 243static void * __init prom_early_alloc(unsigned long size)
@@ -354,7 +407,9 @@ static char * __init build_full_name(struct device_node *dp)
354 return n; 407 return n;
355} 408}
356 409
357static struct property * __init build_one_prop(phandle node, char *prev) 410static unsigned int unique_id;
411
412static struct property * __init build_one_prop(phandle node, char *prev, char *special_name, void *special_val, int special_len)
358{ 413{
359 static struct property *tmp = NULL; 414 static struct property *tmp = NULL;
360 struct property *p; 415 struct property *p;
@@ -364,25 +419,34 @@ static struct property * __init build_one_prop(phandle node, char *prev)
364 p = tmp; 419 p = tmp;
365 memset(p, 0, sizeof(*p) + 32); 420 memset(p, 0, sizeof(*p) + 32);
366 tmp = NULL; 421 tmp = NULL;
367 } else 422 } else {
368 p = prom_early_alloc(sizeof(struct property) + 32); 423 p = prom_early_alloc(sizeof(struct property) + 32);
424 p->unique_id = unique_id++;
425 }
369 426
370 p->name = (char *) (p + 1); 427 p->name = (char *) (p + 1);
371 if (prev == NULL) { 428 if (special_name) {
372 prom_firstprop(node, p->name); 429 p->length = special_len;
430 p->value = prom_early_alloc(special_len);
431 memcpy(p->value, special_val, special_len);
373 } else { 432 } else {
374 prom_nextprop(node, prev, p->name); 433 if (prev == NULL) {
375 } 434 prom_firstprop(node, p->name);
376 if (strlen(p->name) == 0) { 435 } else {
377 tmp = p; 436 prom_nextprop(node, prev, p->name);
378 return NULL; 437 }
379 } 438 if (strlen(p->name) == 0) {
380 p->length = prom_getproplen(node, p->name); 439 tmp = p;
381 if (p->length <= 0) { 440 return NULL;
382 p->length = 0; 441 }
383 } else { 442 p->length = prom_getproplen(node, p->name);
384 p->value = prom_early_alloc(p->length); 443 if (p->length <= 0) {
385 len = prom_getproperty(node, p->name, p->value, p->length); 444 p->length = 0;
445 } else {
446 p->value = prom_early_alloc(p->length + 1);
447 prom_getproperty(node, p->name, p->value, p->length);
448 ((unsigned char *)p->value)[p->length] = '\0';
449 }
386 } 450 }
387 return p; 451 return p;
388} 452}
@@ -391,9 +455,14 @@ static struct property * __init build_prop_list(phandle node)
391{ 455{
392 struct property *head, *tail; 456 struct property *head, *tail;
393 457
394 head = tail = build_one_prop(node, NULL); 458 head = tail = build_one_prop(node, NULL,
459 ".node", &node, sizeof(node));
460
461 tail->next = build_one_prop(node, NULL, NULL, NULL, 0);
462 tail = tail->next;
395 while(tail) { 463 while(tail) {
396 tail->next = build_one_prop(node, tail->name); 464 tail->next = build_one_prop(node, tail->name,
465 NULL, NULL, 0);
397 tail = tail->next; 466 tail = tail->next;
398 } 467 }
399 468
@@ -422,6 +491,7 @@ static struct device_node * __init create_node(phandle node)
422 return NULL; 491 return NULL;
423 492
424 dp = prom_early_alloc(sizeof(*dp)); 493 dp = prom_early_alloc(sizeof(*dp));
494 dp->unique_id = unique_id++;
425 495
426 kref_init(&dp->kref); 496 kref_init(&dp->kref);
427 497
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile
index fa5006946062..5db7e1d85385 100644
--- a/arch/sparc/lib/Makefile
+++ b/arch/sparc/lib/Makefile
@@ -9,3 +9,5 @@ lib-y := mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o memcpy.o memset.o \
9 strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \ 9 strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \
10 copy_user.o locks.o atomic.o atomic32.o bitops.o \ 10 copy_user.o locks.o atomic.o atomic32.o bitops.o \
11 lshrdi3.o ashldi3.o rwsem.o muldi3.o bitext.o 11 lshrdi3.o ashldi3.o rwsem.o muldi3.o bitext.o
12
13obj-y += iomap.o
diff --git a/arch/sparc/lib/iomap.c b/arch/sparc/lib/iomap.c
new file mode 100644
index 000000000000..54501c1ca785
--- /dev/null
+++ b/arch/sparc/lib/iomap.c
@@ -0,0 +1,48 @@
1/*
2 * Implement the sparc iomap interfaces
3 */
4#include <linux/pci.h>
5#include <linux/module.h>
6#include <asm/io.h>
7
8/* Create a virtual mapping cookie for an IO port range */
9void __iomem *ioport_map(unsigned long port, unsigned int nr)
10{
11 return (void __iomem *) (unsigned long) port;
12}
13
14void ioport_unmap(void __iomem *addr)
15{
16 /* Nothing to do */
17}
18EXPORT_SYMBOL(ioport_map);
19EXPORT_SYMBOL(ioport_unmap);
20
21/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
22void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
23{
24 unsigned long start = pci_resource_start(dev, bar);
25 unsigned long len = pci_resource_len(dev, bar);
26 unsigned long flags = pci_resource_flags(dev, bar);
27
28 if (!len || !start)
29 return NULL;
30 if (maxlen && len > maxlen)
31 len = maxlen;
32 if (flags & IORESOURCE_IO)
33 return ioport_map(start, len);
34 if (flags & IORESOURCE_MEM) {
35 if (flags & IORESOURCE_CACHEABLE)
36 return ioremap(start, len);
37 return ioremap_nocache(start, len);
38 }
39 /* What? */
40 return NULL;
41}
42
43void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
44{
45 /* nothing to do */
46}
47EXPORT_SYMBOL(pci_iomap);
48EXPORT_SYMBOL(pci_iounmap);
diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c
index 2c42894b188f..c2c69c167d18 100644
--- a/arch/sparc64/kernel/auxio.c
+++ b/arch/sparc64/kernel/auxio.c
@@ -6,6 +6,7 @@
6 */ 6 */
7 7
8#include <linux/config.h> 8#include <linux/config.h>
9#include <linux/module.h>
9#include <linux/kernel.h> 10#include <linux/kernel.h>
10#include <linux/init.h> 11#include <linux/init.h>
11#include <linux/ioport.h> 12#include <linux/ioport.h>
@@ -16,8 +17,8 @@
16#include <asm/ebus.h> 17#include <asm/ebus.h>
17#include <asm/auxio.h> 18#include <asm/auxio.h>
18 19
19/* This cannot be static, as it is referenced in irq.c */
20void __iomem *auxio_register = NULL; 20void __iomem *auxio_register = NULL;
21EXPORT_SYMBOL(auxio_register);
21 22
22enum auxio_type { 23enum auxio_type {
23 AUXIO_TYPE_NODEV, 24 AUXIO_TYPE_NODEV,
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 31e0fbb0d82c..cc89b06d0178 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -563,67 +563,6 @@ void handler_irq(int irq, struct pt_regs *regs)
563 irq_exit(); 563 irq_exit();
564} 564}
565 565
566#ifdef CONFIG_BLK_DEV_FD
567extern irqreturn_t floppy_interrupt(int, void *, struct pt_regs *);
568
569/* XXX No easy way to include asm/floppy.h XXX */
570extern unsigned char *pdma_vaddr;
571extern unsigned long pdma_size;
572extern volatile int doing_pdma;
573extern unsigned long fdc_status;
574
575irqreturn_t sparc_floppy_irq(int irq, void *dev_cookie, struct pt_regs *regs)
576{
577 if (likely(doing_pdma)) {
578 void __iomem *stat = (void __iomem *) fdc_status;
579 unsigned char *vaddr = pdma_vaddr;
580 unsigned long size = pdma_size;
581 u8 val;
582
583 while (size) {
584 val = readb(stat);
585 if (unlikely(!(val & 0x80))) {
586 pdma_vaddr = vaddr;
587 pdma_size = size;
588 return IRQ_HANDLED;
589 }
590 if (unlikely(!(val & 0x20))) {
591 pdma_vaddr = vaddr;
592 pdma_size = size;
593 doing_pdma = 0;
594 goto main_interrupt;
595 }
596 if (val & 0x40) {
597 /* read */
598 *vaddr++ = readb(stat + 1);
599 } else {
600 unsigned char data = *vaddr++;
601
602 /* write */
603 writeb(data, stat + 1);
604 }
605 size--;
606 }
607
608 pdma_vaddr = vaddr;
609 pdma_size = size;
610
611 /* Send Terminal Count pulse to floppy controller. */
612 val = readb(auxio_register);
613 val |= AUXIO_AUX1_FTCNT;
614 writeb(val, auxio_register);
615 val &= ~AUXIO_AUX1_FTCNT;
616 writeb(val, auxio_register);
617
618 doing_pdma = 0;
619 }
620
621main_interrupt:
622 return floppy_interrupt(irq, dev_cookie, regs);
623}
624EXPORT_SYMBOL(sparc_floppy_irq);
625#endif
626
627struct sun5_timer { 566struct sun5_timer {
628 u64 count0; 567 u64 count0;
629 u64 limit0; 568 u64 limit0;
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
index 566aa343aa62..768475bbce82 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -138,6 +138,7 @@ struct bus_type isa_bus_type = {
138 .suspend = of_device_suspend, 138 .suspend = of_device_suspend,
139 .resume = of_device_resume, 139 .resume = of_device_resume,
140}; 140};
141EXPORT_SYMBOL(isa_bus_type);
141 142
142struct bus_type ebus_bus_type = { 143struct bus_type ebus_bus_type = {
143 .name = "ebus", 144 .name = "ebus",
@@ -147,6 +148,7 @@ struct bus_type ebus_bus_type = {
147 .suspend = of_device_suspend, 148 .suspend = of_device_suspend,
148 .resume = of_device_resume, 149 .resume = of_device_resume,
149}; 150};
151EXPORT_SYMBOL(ebus_bus_type);
150#endif 152#endif
151 153
152#ifdef CONFIG_SBUS 154#ifdef CONFIG_SBUS
@@ -158,6 +160,7 @@ struct bus_type sbus_bus_type = {
158 .suspend = of_device_suspend, 160 .suspend = of_device_suspend,
159 .resume = of_device_resume, 161 .resume = of_device_resume,
160}; 162};
163EXPORT_SYMBOL(sbus_bus_type);
161#endif 164#endif
162 165
163static int __init of_bus_driver_init(void) 166static int __init of_bus_driver_init(void)
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
index e9d703eea806..8e87e7ea0325 100644
--- a/arch/sparc64/kernel/prom.c
+++ b/arch/sparc64/kernel/prom.c
@@ -27,6 +27,11 @@
27 27
28static struct device_node *allnodes; 28static struct device_node *allnodes;
29 29
30/* use when traversing tree through the allnext, child, sibling,
31 * or parent members of struct device_node.
32 */
33static DEFINE_RWLOCK(devtree_lock);
34
30int of_device_is_compatible(struct device_node *device, const char *compat) 35int of_device_is_compatible(struct device_node *device, const char *compat)
31{ 36{
32 const char* cp; 37 const char* cp;
@@ -185,6 +190,54 @@ int of_getintprop_default(struct device_node *np, const char *name, int def)
185} 190}
186EXPORT_SYMBOL(of_getintprop_default); 191EXPORT_SYMBOL(of_getintprop_default);
187 192
193int of_set_property(struct device_node *dp, const char *name, void *val, int len)
194{
195 struct property **prevp;
196 void *new_val;
197 int err;
198
199 new_val = kmalloc(len, GFP_KERNEL);
200 if (!new_val)
201 return -ENOMEM;
202
203 memcpy(new_val, val, len);
204
205 err = -ENODEV;
206
207 write_lock(&devtree_lock);
208 prevp = &dp->properties;
209 while (*prevp) {
210 struct property *prop = *prevp;
211
212 if (!strcmp(prop->name, name)) {
213 void *old_val = prop->value;
214 int ret;
215
216 ret = prom_setprop(dp->node, name, val, len);
217 err = -EINVAL;
218 if (ret >= 0) {
219 prop->value = new_val;
220 prop->length = len;
221
222 if (OF_IS_DYNAMIC(prop))
223 kfree(old_val);
224
225 OF_MARK_DYNAMIC(prop);
226
227 err = 0;
228 }
229 break;
230 }
231 prevp = &(*prevp)->next;
232 }
233 write_unlock(&devtree_lock);
234
235 /* XXX Upate procfs if necessary... */
236
237 return err;
238}
239EXPORT_SYMBOL(of_set_property);
240
188static unsigned int prom_early_allocated; 241static unsigned int prom_early_allocated;
189 242
190static void * __init prom_early_alloc(unsigned long size) 243static void * __init prom_early_alloc(unsigned long size)
@@ -531,7 +584,9 @@ static char * __init build_full_name(struct device_node *dp)
531 return n; 584 return n;
532} 585}
533 586
534static struct property * __init build_one_prop(phandle node, char *prev) 587static unsigned int unique_id;
588
589static struct property * __init build_one_prop(phandle node, char *prev, char *special_name, void *special_val, int special_len)
535{ 590{
536 static struct property *tmp = NULL; 591 static struct property *tmp = NULL;
537 struct property *p; 592 struct property *p;
@@ -540,25 +595,35 @@ static struct property * __init build_one_prop(phandle node, char *prev)
540 p = tmp; 595 p = tmp;
541 memset(p, 0, sizeof(*p) + 32); 596 memset(p, 0, sizeof(*p) + 32);
542 tmp = NULL; 597 tmp = NULL;
543 } else 598 } else {
544 p = prom_early_alloc(sizeof(struct property) + 32); 599 p = prom_early_alloc(sizeof(struct property) + 32);
600 p->unique_id = unique_id++;
601 }
545 602
546 p->name = (char *) (p + 1); 603 p->name = (char *) (p + 1);
547 if (prev == NULL) { 604 if (special_name) {
548 prom_firstprop(node, p->name); 605 strcpy(p->name, special_name);
606 p->length = special_len;
607 p->value = prom_early_alloc(special_len);
608 memcpy(p->value, special_val, special_len);
549 } else { 609 } else {
550 prom_nextprop(node, prev, p->name); 610 if (prev == NULL) {
551 } 611 prom_firstprop(node, p->name);
552 if (strlen(p->name) == 0) { 612 } else {
553 tmp = p; 613 prom_nextprop(node, prev, p->name);
554 return NULL; 614 }
555 } 615 if (strlen(p->name) == 0) {
556 p->length = prom_getproplen(node, p->name); 616 tmp = p;
557 if (p->length <= 0) { 617 return NULL;
558 p->length = 0; 618 }
559 } else { 619 p->length = prom_getproplen(node, p->name);
560 p->value = prom_early_alloc(p->length); 620 if (p->length <= 0) {
561 prom_getproperty(node, p->name, p->value, p->length); 621 p->length = 0;
622 } else {
623 p->value = prom_early_alloc(p->length + 1);
624 prom_getproperty(node, p->name, p->value, p->length);
625 ((unsigned char *)p->value)[p->length] = '\0';
626 }
562 } 627 }
563 return p; 628 return p;
564} 629}
@@ -567,9 +632,14 @@ static struct property * __init build_prop_list(phandle node)
567{ 632{
568 struct property *head, *tail; 633 struct property *head, *tail;
569 634
570 head = tail = build_one_prop(node, NULL); 635 head = tail = build_one_prop(node, NULL,
636 ".node", &node, sizeof(node));
637
638 tail->next = build_one_prop(node, NULL, NULL, NULL, 0);
639 tail = tail->next;
571 while(tail) { 640 while(tail) {
572 tail->next = build_one_prop(node, tail->name); 641 tail->next = build_one_prop(node, tail->name,
642 NULL, NULL, 0);
573 tail = tail->next; 643 tail = tail->next;
574 } 644 }
575 645
@@ -598,6 +668,7 @@ static struct device_node * __init create_node(phandle node)
598 return NULL; 668 return NULL;
599 669
600 dp = prom_early_alloc(sizeof(*dp)); 670 dp = prom_early_alloc(sizeof(*dp));
671 dp->unique_id = unique_id++;
601 672
602 kref_init(&dp->kref); 673 kref_init(&dp->kref);
603 674
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 513993414747..5c2bcf354ce6 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -1568,6 +1568,7 @@ pgprot_t PAGE_EXEC __read_mostly;
1568unsigned long pg_iobits __read_mostly; 1568unsigned long pg_iobits __read_mostly;
1569 1569
1570unsigned long _PAGE_IE __read_mostly; 1570unsigned long _PAGE_IE __read_mostly;
1571EXPORT_SYMBOL(_PAGE_IE);
1571 1572
1572unsigned long _PAGE_E __read_mostly; 1573unsigned long _PAGE_E __read_mostly;
1573EXPORT_SYMBOL(_PAGE_E); 1574EXPORT_SYMBOL(_PAGE_E);
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c
index 0758cb1d0105..24a03152d196 100644
--- a/drivers/mtd/maps/sun_uflash.c
+++ b/drivers/mtd/maps/sun_uflash.c
@@ -18,6 +18,7 @@
18#include <linux/ioport.h> 18#include <linux/ioport.h>
19#include <asm/ebus.h> 19#include <asm/ebus.h>
20#include <asm/oplib.h> 20#include <asm/oplib.h>
21#include <asm/prom.h>
21#include <asm/uaccess.h> 22#include <asm/uaccess.h>
22#include <asm/io.h> 23#include <asm/io.h>
23 24
@@ -30,146 +31,140 @@
30#define UFLASH_WINDOW_SIZE 0x200000 31#define UFLASH_WINDOW_SIZE 0x200000
31#define UFLASH_BUSWIDTH 1 /* EBus is 8-bit */ 32#define UFLASH_BUSWIDTH 1 /* EBus is 8-bit */
32 33
33MODULE_AUTHOR 34MODULE_AUTHOR("Eric Brower <ebrower@usa.net>");
34 ("Eric Brower <ebrower@usa.net>"); 35MODULE_DESCRIPTION("User-programmable flash device on Sun Microsystems boardsets");
35MODULE_DESCRIPTION 36MODULE_SUPPORTED_DEVICE("userflash");
36 ("User-programmable flash device on Sun Microsystems boardsets"); 37MODULE_LICENSE("GPL");
37MODULE_SUPPORTED_DEVICE 38MODULE_VERSION("2.0");
38 ("userflash");
39MODULE_LICENSE
40 ("GPL");
41 39
42static LIST_HEAD(device_list); 40static LIST_HEAD(device_list);
43struct uflash_dev { 41struct uflash_dev {
44 char * name; /* device name */ 42 char *name; /* device name */
45 struct map_info map; /* mtd map info */ 43 struct map_info map; /* mtd map info */
46 struct mtd_info * mtd; /* mtd info */ 44 struct mtd_info *mtd; /* mtd info */
47 struct list_head list;
48}; 45};
49 46
50 47
51struct map_info uflash_map_templ = { 48struct map_info uflash_map_templ = {
52 .name = "SUNW,???-????", 49 .name = "SUNW,???-????",
53 .size = UFLASH_WINDOW_SIZE, 50 .size = UFLASH_WINDOW_SIZE,
54 .bankwidth = UFLASH_BUSWIDTH, 51 .bankwidth = UFLASH_BUSWIDTH,
55}; 52};
56 53
57int uflash_devinit(struct linux_ebus_device* edev) 54int uflash_devinit(struct linux_ebus_device *edev, struct device_node *dp)
58{ 55{
59 int iTmp, nregs; 56 struct uflash_dev *up;
60 struct linux_prom_registers regs[2]; 57 struct resource *res;
61 struct uflash_dev *pdev;
62
63 iTmp = prom_getproperty(
64 edev->prom_node, "reg", (void *)regs, sizeof(regs));
65 if ((iTmp % sizeof(regs[0])) != 0) {
66 printk("%s: Strange reg property size %d\n",
67 UFLASH_DEVNAME, iTmp);
68 return -ENODEV;
69 }
70 58
71 nregs = iTmp / sizeof(regs[0]); 59 res = &edev->resource[0];
72 60
73 if (nregs != 1) { 61 if (edev->num_addrs != 1) {
74 /* Non-CFI userflash device-- once I find one we 62 /* Non-CFI userflash device-- once I find one we
75 * can work on supporting it. 63 * can work on supporting it.
76 */ 64 */
77 printk("%s: unsupported device at 0x%lx (%d regs): " \ 65 printk("%s: unsupported device at 0x%lx (%d regs): " \
78 "email ebrower@usa.net\n", 66 "email ebrower@usa.net\n",
79 UFLASH_DEVNAME, edev->resource[0].start, nregs); 67 dp->full_name, res->start, edev->num_addrs);
68
80 return -ENODEV; 69 return -ENODEV;
81 } 70 }
82 71
83 if(0 == (pdev = kmalloc(sizeof(struct uflash_dev), GFP_KERNEL))) { 72 up = kzalloc(sizeof(struct uflash_dev), GFP_KERNEL);
84 printk("%s: unable to kmalloc new device\n", UFLASH_DEVNAME); 73 if (!up)
85 return(-ENOMEM); 74 return -ENOMEM;
86 }
87 75
88 /* copy defaults and tweak parameters */ 76 /* copy defaults and tweak parameters */
89 memcpy(&pdev->map, &uflash_map_templ, sizeof(uflash_map_templ)); 77 memcpy(&up->map, &uflash_map_templ, sizeof(uflash_map_templ));
90 pdev->map.size = regs[0].reg_size; 78 up->map.size = (res->end - res->start) + 1UL;
91 79
92 iTmp = prom_getproplen(edev->prom_node, "model"); 80 up->name = of_get_property(dp, "model", NULL);
93 pdev->name = kmalloc(iTmp, GFP_KERNEL); 81 if (up->name && 0 < strlen(up->name))
94 prom_getstring(edev->prom_node, "model", pdev->name, iTmp); 82 up->map.name = up->name;
95 if(0 != pdev->name && 0 < strlen(pdev->name)) { 83
96 pdev->map.name = pdev->name; 84 up->map.phys = res->start;
97 } 85
98 pdev->map.phys = edev->resource[0].start; 86 up->map.virt = ioremap_nocache(res->start, up->map.size);
99 pdev->map.virt = ioremap_nocache(edev->resource[0].start, pdev->map.size); 87 if (!up->map.virt) {
100 if(0 == pdev->map.virt) { 88 printk("%s: Failed to map device.\n", dp->full_name);
101 printk("%s: failed to map device\n", __FUNCTION__); 89 kfree(up);
102 kfree(pdev->name); 90
103 kfree(pdev); 91 return -EINVAL;
104 return(-1);
105 } 92 }
106 93
107 simple_map_init(&pdev->map); 94 simple_map_init(&up->map);
108 95
109 /* MTD registration */ 96 /* MTD registration */
110 pdev->mtd = do_map_probe("cfi_probe", &pdev->map); 97 up->mtd = do_map_probe("cfi_probe", &up->map);
111 if(0 == pdev->mtd) { 98 if (!up->mtd) {
112 iounmap(pdev->map.virt); 99 iounmap(up->map.virt);
113 kfree(pdev->name); 100 kfree(up);
114 kfree(pdev); 101
115 return(-ENXIO); 102 return -ENXIO;
116 } 103 }
117 104
118 list_add(&pdev->list, &device_list); 105 up->mtd->owner = THIS_MODULE;
119 106
120 pdev->mtd->owner = THIS_MODULE; 107 add_mtd_device(up->mtd);
121 108
122 add_mtd_device(pdev->mtd); 109 dev_set_drvdata(&edev->ofdev.dev, up);
123 return(0); 110
111 return 0;
124} 112}
125 113
126static int __init uflash_init(void) 114static int __devinit uflash_probe(struct of_device *dev, const struct of_device_id *match)
127{ 115{
128 struct linux_ebus *ebus = NULL; 116 struct linux_ebus_device *edev = to_ebus_device(&dev->dev);
129 struct linux_ebus_device *edev = NULL; 117 struct device_node *dp = dev->node;
130
131 for_each_ebus(ebus) {
132 for_each_ebusdev(edev, ebus) {
133 if (!strcmp(edev->prom_name, UFLASH_OBPNAME)) {
134 if(0 > prom_getproplen(edev->prom_node, "user")) {
135 DEBUG(2, "%s: ignoring device at 0x%lx\n",
136 UFLASH_DEVNAME, edev->resource[0].start);
137 } else {
138 uflash_devinit(edev);
139 }
140 }
141 }
142 }
143 118
144 if(list_empty(&device_list)) { 119 if (of_find_property(dp, "user", NULL))
145 printk("%s: unable to locate device\n", UFLASH_DEVNAME);
146 return -ENODEV; 120 return -ENODEV;
147 } 121
148 return(0); 122 return uflash_devinit(edev, dp);
149} 123}
150 124
151static void __exit uflash_cleanup(void) 125static int __devexit uflash_remove(struct of_device *dev)
152{ 126{
153 struct list_head *udevlist; 127 struct uflash_dev *up = dev_get_drvdata(&dev->dev);
154 struct uflash_dev *udev; 128
155 129 if (up->mtd) {
156 list_for_each(udevlist, &device_list) { 130 del_mtd_device(up->mtd);
157 udev = list_entry(udevlist, struct uflash_dev, list); 131 map_destroy(up->mtd);
158 DEBUG(2, "%s: removing device %s\n",
159 UFLASH_DEVNAME, udev->name);
160
161 if(0 != udev->mtd) {
162 del_mtd_device(udev->mtd);
163 map_destroy(udev->mtd);
164 }
165 if(0 != udev->map.virt) {
166 iounmap(udev->map.virt);
167 udev->map.virt = NULL;
168 }
169 kfree(udev->name);
170 kfree(udev);
171 } 132 }
133 if (up->map.virt) {
134 iounmap(up->map.virt);
135 up->map.virt = NULL;
136 }
137
138 kfree(up);
139
140 return 0;
141}
142
143static struct of_device_id uflash_match[] = {
144 {
145 .name = UFLASH_OBPNAME,
146 },
147 {},
148};
149
150MODULE_DEVICE_TABLE(of, uflash_match);
151
152static struct of_platform_driver uflash_driver = {
153 .name = UFLASH_DEVNAME,
154 .match_table = uflash_match,
155 .probe = uflash_probe,
156 .remove = __devexit_p(uflash_remove),
157};
158
159static int __init uflash_init(void)
160{
161 return of_register_driver(&uflash_driver, &ebus_bus_type);
162}
163
164static void __exit uflash_exit(void)
165{
166 of_unregister_driver(&uflash_driver);
172} 167}
173 168
174module_init(uflash_init); 169module_init(uflash_init);
175module_exit(uflash_cleanup); 170module_exit(uflash_exit);
diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c
index 69a4bbd4cbee..7c43c5392bed 100644
--- a/drivers/parport/parport_sunbpp.c
+++ b/drivers/parport/parport_sunbpp.c
@@ -389,7 +389,7 @@ static struct of_device_id bpp_match[] = {
389 {}, 389 {},
390}; 390};
391 391
392MODULE_DEVICE_TABLE(of, qec_sbus_match); 392MODULE_DEVICE_TABLE(of, bpp_match);
393 393
394static struct of_platform_driver bpp_sbus_driver = { 394static struct of_platform_driver bpp_sbus_driver = {
395 .name = "bpp", 395 .name = "bpp",
diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c
index 5bf3dd901b65..21737b7e86a1 100644
--- a/drivers/sbus/char/cpwatchdog.c
+++ b/drivers/sbus/char/cpwatchdog.c
@@ -755,7 +755,7 @@ static int __init wd_init(void)
755 755
756 for_each_ebus(ebus) { 756 for_each_ebus(ebus) {
757 for_each_ebusdev(edev, ebus) { 757 for_each_ebusdev(edev, ebus) {
758 if (!strcmp(edev->prom_name, WD_OBPNAME)) 758 if (!strcmp(edev->ofdev.node->name, WD_OBPNAME))
759 goto ebus_done; 759 goto ebus_done;
760 } 760 }
761 } 761 }
diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c
index cf5b476b5496..d7e4bb41bd79 100644
--- a/drivers/sbus/char/openprom.c
+++ b/drivers/sbus/char/openprom.c
@@ -29,8 +29,6 @@
29 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 29 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 */ 30 */
31 31
32#define PROMLIB_INTERNAL
33
34#include <linux/config.h> 32#include <linux/config.h>
35#include <linux/module.h> 33#include <linux/module.h>
36#include <linux/kernel.h> 34#include <linux/kernel.h>
@@ -39,10 +37,10 @@
39#include <linux/slab.h> 37#include <linux/slab.h>
40#include <linux/string.h> 38#include <linux/string.h>
41#include <linux/miscdevice.h> 39#include <linux/miscdevice.h>
42#include <linux/smp_lock.h>
43#include <linux/init.h> 40#include <linux/init.h>
44#include <linux/fs.h> 41#include <linux/fs.h>
45#include <asm/oplib.h> 42#include <asm/oplib.h>
43#include <asm/prom.h>
46#include <asm/system.h> 44#include <asm/system.h>
47#include <asm/uaccess.h> 45#include <asm/uaccess.h>
48#include <asm/openpromio.h> 46#include <asm/openpromio.h>
@@ -51,15 +49,20 @@
51#include <asm/pbm.h> 49#include <asm/pbm.h>
52#endif 50#endif
53 51
52MODULE_AUTHOR("Thomas K. Dyas (tdyas@noc.rutgers.edu) and Eddie C. Dost (ecd@skynet.be)");
53MODULE_DESCRIPTION("OPENPROM Configuration Driver");
54MODULE_LICENSE("GPL");
55MODULE_VERSION("1.0");
56
54/* Private data kept by the driver for each descriptor. */ 57/* Private data kept by the driver for each descriptor. */
55typedef struct openprom_private_data 58typedef struct openprom_private_data
56{ 59{
57 int current_node; /* Current node for SunOS ioctls. */ 60 struct device_node *current_node; /* Current node for SunOS ioctls. */
58 int lastnode; /* Last valid node used by BSD ioctls. */ 61 struct device_node *lastnode; /* Last valid node used by BSD ioctls. */
59} DATA; 62} DATA;
60 63
61/* ID of the PROM node containing all of the EEPROM options. */ 64/* ID of the PROM node containing all of the EEPROM options. */
62static int options_node = 0; 65static struct device_node *options_node;
63 66
64/* 67/*
65 * Copy an openpromio structure into kernel space from user space. 68 * Copy an openpromio structure into kernel space from user space.
@@ -87,9 +90,8 @@ static int copyin(struct openpromio __user *info, struct openpromio **opp_p)
87 if (bufsize > OPROMMAXPARAM) 90 if (bufsize > OPROMMAXPARAM)
88 bufsize = OPROMMAXPARAM; 91 bufsize = OPROMMAXPARAM;
89 92
90 if (!(*opp_p = kmalloc(sizeof(int) + bufsize + 1, GFP_KERNEL))) 93 if (!(*opp_p = kzalloc(sizeof(int) + bufsize + 1, GFP_KERNEL)))
91 return -ENOMEM; 94 return -ENOMEM;
92 memset(*opp_p, 0, sizeof(int) + bufsize + 1);
93 95
94 if (copy_from_user(&(*opp_p)->oprom_array, 96 if (copy_from_user(&(*opp_p)->oprom_array,
95 &info->oprom_array, bufsize)) { 97 &info->oprom_array, bufsize)) {
@@ -107,10 +109,9 @@ static int getstrings(struct openpromio __user *info, struct openpromio **opp_p)
107 if (!info || !opp_p) 109 if (!info || !opp_p)
108 return -EFAULT; 110 return -EFAULT;
109 111
110 if (!(*opp_p = kmalloc(sizeof(int) + OPROMMAXPARAM + 1, GFP_KERNEL))) 112 if (!(*opp_p = kzalloc(sizeof(int) + OPROMMAXPARAM + 1, GFP_KERNEL)))
111 return -ENOMEM; 113 return -ENOMEM;
112 114
113 memset(*opp_p, 0, sizeof(int) + OPROMMAXPARAM + 1);
114 (*opp_p)->oprom_size = 0; 115 (*opp_p)->oprom_size = 0;
115 116
116 n = bufsize = 0; 117 n = bufsize = 0;
@@ -140,16 +141,164 @@ static int copyout(void __user *info, struct openpromio *opp, int len)
140 return 0; 141 return 0;
141} 142}
142 143
144static int opromgetprop(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize)
145{
146 void *pval;
147 int len;
148
149 pval = of_get_property(dp, op->oprom_array, &len);
150 if (!pval || len <= 0 || len > bufsize)
151 return copyout(argp, op, sizeof(int));
152
153 memcpy(op->oprom_array, pval, len);
154 op->oprom_array[len] = '\0';
155 op->oprom_size = len;
156
157 return copyout(argp, op, sizeof(int) + bufsize);
158}
159
160static int opromnxtprop(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize)
161{
162 struct property *prop;
163 int len;
164
165 if (op->oprom_array[0] == '\0') {
166 prop = dp->properties;
167 if (!prop)
168 return copyout(argp, op, sizeof(int));
169 len = strlen(prop->name);
170 } else {
171 prop = of_find_property(dp, op->oprom_array, NULL);
172
173 if (!prop ||
174 !prop->next ||
175 (len = strlen(prop->next->name)) + 1 > bufsize)
176 return copyout(argp, op, sizeof(int));
177
178 prop = prop->next;
179 }
180
181 memcpy(op->oprom_array, prop->name, len);
182 op->oprom_array[len] = '\0';
183 op->oprom_size = ++len;
184
185 return copyout(argp, op, sizeof(int) + bufsize);
186}
187
188static int opromsetopt(struct device_node *dp, struct openpromio *op, int bufsize)
189{
190 char *buf = op->oprom_array + strlen(op->oprom_array) + 1;
191 int len = op->oprom_array + bufsize - buf;
192
193 return of_set_property(options_node, op->oprom_array, buf, len);
194}
195
196static int opromnext(void __user *argp, unsigned int cmd, struct device_node *dp, struct openpromio *op, int bufsize, DATA *data)
197{
198 phandle ph;
199
200 BUILD_BUG_ON(sizeof(phandle) != sizeof(int));
201
202 if (bufsize < sizeof(phandle))
203 return -EINVAL;
204
205 ph = *((int *) op->oprom_array);
206 if (ph) {
207 dp = of_find_node_by_phandle(ph);
208 if (!dp)
209 return -EINVAL;
210
211 switch (cmd) {
212 case OPROMNEXT:
213 dp = dp->sibling;
214 break;
215
216 case OPROMCHILD:
217 dp = dp->child;
218 break;
219
220 case OPROMSETCUR:
221 default:
222 break;
223 };
224 } else {
225 /* Sibling of node zero is the root node. */
226 if (cmd != OPROMNEXT)
227 return -EINVAL;
228
229 dp = of_find_node_by_path("/");
230 }
231
232 ph = 0;
233 if (dp)
234 ph = dp->node;
235
236 data->current_node = dp;
237 *((int *) op->oprom_array) = ph;
238 op->oprom_size = sizeof(phandle);
239
240 return copyout(argp, op, bufsize + sizeof(int));
241}
242
243static int oprompci2node(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize, DATA *data)
244{
245 int err = -EINVAL;
246
247 if (bufsize >= 2*sizeof(int)) {
248#ifdef CONFIG_PCI
249 struct pci_dev *pdev;
250 struct pcidev_cookie *pcp;
251 pdev = pci_find_slot (((int *) op->oprom_array)[0],
252 ((int *) op->oprom_array)[1]);
253
254 pcp = pdev->sysdata;
255 if (pcp != NULL) {
256 dp = pcp->prom_node;
257 data->current_node = dp;
258 *((int *)op->oprom_array) = dp->node;
259 op->oprom_size = sizeof(int);
260 err = copyout(argp, op, bufsize + sizeof(int));
261 }
262#endif
263 }
264
265 return err;
266}
267
268static int oprompath2node(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize, DATA *data)
269{
270 dp = of_find_node_by_path(op->oprom_array);
271 data->current_node = dp;
272 *((int *)op->oprom_array) = dp->node;
273 op->oprom_size = sizeof(int);
274
275 return copyout(argp, op, bufsize + sizeof(int));
276}
277
278static int opromgetbootargs(void __user *argp, struct openpromio *op, int bufsize)
279{
280 char *buf = saved_command_line;
281 int len = strlen(buf);
282
283 if (len > bufsize)
284 return -EINVAL;
285
286 strcpy(op->oprom_array, buf);
287 op->oprom_size = len;
288
289 return copyout(argp, op, bufsize + sizeof(int));
290}
291
143/* 292/*
144 * SunOS and Solaris /dev/openprom ioctl calls. 293 * SunOS and Solaris /dev/openprom ioctl calls.
145 */ 294 */
146static int openprom_sunos_ioctl(struct inode * inode, struct file * file, 295static int openprom_sunos_ioctl(struct inode * inode, struct file * file,
147 unsigned int cmd, unsigned long arg, int node) 296 unsigned int cmd, unsigned long arg,
297 struct device_node *dp)
148{ 298{
149 DATA *data = (DATA *) file->private_data; 299 DATA *data = file->private_data;
150 char buffer[OPROMMAXPARAM+1], *buf;
151 struct openpromio *opp; 300 struct openpromio *opp;
152 int bufsize, len, error = 0; 301 int bufsize, error = 0;
153 static int cnt; 302 static int cnt;
154 void __user *argp = (void __user *)arg; 303 void __user *argp = (void __user *)arg;
155 304
@@ -164,119 +313,35 @@ static int openprom_sunos_ioctl(struct inode * inode, struct file * file,
164 switch (cmd) { 313 switch (cmd) {
165 case OPROMGETOPT: 314 case OPROMGETOPT:
166 case OPROMGETPROP: 315 case OPROMGETPROP:
167 len = prom_getproplen(node, opp->oprom_array); 316 error = opromgetprop(argp, dp, opp, bufsize);
168
169 if (len <= 0 || len > bufsize) {
170 error = copyout(argp, opp, sizeof(int));
171 break;
172 }
173
174 len = prom_getproperty(node, opp->oprom_array, buffer, bufsize);
175
176 memcpy(opp->oprom_array, buffer, len);
177 opp->oprom_array[len] = '\0';
178 opp->oprom_size = len;
179
180 error = copyout(argp, opp, sizeof(int) + bufsize);
181 break; 317 break;
182 318
183 case OPROMNXTOPT: 319 case OPROMNXTOPT:
184 case OPROMNXTPROP: 320 case OPROMNXTPROP:
185 buf = prom_nextprop(node, opp->oprom_array, buffer); 321 error = opromnxtprop(argp, dp, opp, bufsize);
186
187 len = strlen(buf);
188 if (len == 0 || len + 1 > bufsize) {
189 error = copyout(argp, opp, sizeof(int));
190 break;
191 }
192
193 memcpy(opp->oprom_array, buf, len);
194 opp->oprom_array[len] = '\0';
195 opp->oprom_size = ++len;
196
197 error = copyout(argp, opp, sizeof(int) + bufsize);
198 break; 322 break;
199 323
200 case OPROMSETOPT: 324 case OPROMSETOPT:
201 case OPROMSETOPT2: 325 case OPROMSETOPT2:
202 buf = opp->oprom_array + strlen(opp->oprom_array) + 1; 326 error = opromsetopt(dp, opp, bufsize);
203 len = opp->oprom_array + bufsize - buf;
204
205 error = prom_setprop(options_node, opp->oprom_array,
206 buf, len);
207
208 if (error < 0)
209 error = -EINVAL;
210 break; 327 break;
211 328
212 case OPROMNEXT: 329 case OPROMNEXT:
213 case OPROMCHILD: 330 case OPROMCHILD:
214 case OPROMSETCUR: 331 case OPROMSETCUR:
215 if (bufsize < sizeof(int)) { 332 error = opromnext(argp, cmd, dp, opp, bufsize, data);
216 error = -EINVAL;
217 break;
218 }
219
220 node = *((int *) opp->oprom_array);
221
222 switch (cmd) {
223 case OPROMNEXT: node = __prom_getsibling(node); break;
224 case OPROMCHILD: node = __prom_getchild(node); break;
225 case OPROMSETCUR: break;
226 }
227
228 data->current_node = node;
229 *((int *)opp->oprom_array) = node;
230 opp->oprom_size = sizeof(int);
231
232 error = copyout(argp, opp, bufsize + sizeof(int));
233 break; 333 break;
234 334
235 case OPROMPCI2NODE: 335 case OPROMPCI2NODE:
236 error = -EINVAL; 336 error = oprompci2node(argp, dp, opp, bufsize, data);
237
238 if (bufsize >= 2*sizeof(int)) {
239#ifdef CONFIG_PCI
240 struct pci_dev *pdev;
241 struct pcidev_cookie *pcp;
242 pdev = pci_find_slot (((int *) opp->oprom_array)[0],
243 ((int *) opp->oprom_array)[1]);
244
245 pcp = pdev->sysdata;
246 if (pcp != NULL) {
247 node = pcp->prom_node->node;
248 data->current_node = node;
249 *((int *)opp->oprom_array) = node;
250 opp->oprom_size = sizeof(int);
251 error = copyout(argp, opp, bufsize + sizeof(int));
252 }
253#endif
254 }
255 break; 337 break;
256 338
257 case OPROMPATH2NODE: 339 case OPROMPATH2NODE:
258 node = prom_finddevice(opp->oprom_array); 340 error = oprompath2node(argp, dp, opp, bufsize, data);
259 data->current_node = node;
260 *((int *)opp->oprom_array) = node;
261 opp->oprom_size = sizeof(int);
262
263 error = copyout(argp, opp, bufsize + sizeof(int));
264 break; 341 break;
265 342
266 case OPROMGETBOOTARGS: 343 case OPROMGETBOOTARGS:
267 buf = saved_command_line; 344 error = opromgetbootargs(argp, opp, bufsize);
268
269 len = strlen(buf);
270
271 if (len > bufsize) {
272 error = -EINVAL;
273 break;
274 }
275
276 strcpy(opp->oprom_array, buf);
277 opp->oprom_size = len;
278
279 error = copyout(argp, opp, bufsize + sizeof(int));
280 break; 345 break;
281 346
282 case OPROMU2P: 347 case OPROMU2P:
@@ -297,25 +362,14 @@ static int openprom_sunos_ioctl(struct inode * inode, struct file * file,
297 return error; 362 return error;
298} 363}
299 364
300 365static struct device_node *get_node(phandle n, DATA *data)
301/* Return nonzero if a specific node is in the PROM device tree. */
302static int intree(int root, int node)
303{ 366{
304 for (; root != 0; root = prom_getsibling(root)) 367 struct device_node *dp = of_find_node_by_phandle(n);
305 if (root == node || intree(prom_getchild(root),node))
306 return 1;
307 return 0;
308}
309 368
310/* Return nonzero if a specific node is "valid". */ 369 if (dp)
311static int goodnode(int n, DATA *data) 370 data->lastnode = dp;
312{ 371
313 if (n == data->lastnode || n == prom_root_node || n == options_node) 372 return dp;
314 return 1;
315 if (n == 0 || n == -1 || !intree(prom_root_node,n))
316 return 0;
317 data->lastnode = n;
318 return 1;
319} 373}
320 374
321/* Copy in a whole string from userspace into kernelspace. */ 375/* Copy in a whole string from userspace into kernelspace. */
@@ -330,7 +384,7 @@ static int copyin_string(char __user *user, size_t len, char **ptr)
330 if (!tmp) 384 if (!tmp)
331 return -ENOMEM; 385 return -ENOMEM;
332 386
333 if(copy_from_user(tmp, user, len)) { 387 if (copy_from_user(tmp, user, len)) {
334 kfree(tmp); 388 kfree(tmp);
335 return -EFAULT; 389 return -EFAULT;
336 } 390 }
@@ -345,162 +399,187 @@ static int copyin_string(char __user *user, size_t len, char **ptr)
345/* 399/*
346 * NetBSD /dev/openprom ioctl calls. 400 * NetBSD /dev/openprom ioctl calls.
347 */ 401 */
348static int openprom_bsd_ioctl(struct inode * inode, struct file * file, 402static int opiocget(void __user *argp, DATA *data)
349 unsigned int cmd, unsigned long arg)
350{ 403{
351 DATA *data = (DATA *) file->private_data;
352 void __user *argp = (void __user *)arg;
353 struct opiocdesc op; 404 struct opiocdesc op;
354 int error, node, len; 405 struct device_node *dp;
355 char *str, *tmp; 406 char *str;
356 char buffer[64]; 407 void *pval;
357 static int cnt; 408 int err, len;
358
359 switch (cmd) {
360 case OPIOCGET:
361 if (copy_from_user(&op, argp, sizeof(op)))
362 return -EFAULT;
363
364 if (!goodnode(op.op_nodeid,data))
365 return -EINVAL;
366 409
367 error = copyin_string(op.op_name, op.op_namelen, &str); 410 if (copy_from_user(&op, argp, sizeof(op)))
368 if (error) 411 return -EFAULT;
369 return error;
370 412
371 len = prom_getproplen(op.op_nodeid,str); 413 dp = get_node(op.op_nodeid, data);
372 414
373 if (len > op.op_buflen) { 415 err = copyin_string(op.op_name, op.op_namelen, &str);
374 kfree(str); 416 if (err)
375 return -ENOMEM; 417 return err;
376 }
377 418
419 pval = of_get_property(dp, str, &len);
420 err = 0;
421 if (!pval || len > op.op_buflen) {
422 err = -EINVAL;
423 } else {
378 op.op_buflen = len; 424 op.op_buflen = len;
425 if (copy_to_user(argp, &op, sizeof(op)) ||
426 copy_to_user(op.op_buf, pval, len))
427 err = -EFAULT;
428 }
429 kfree(str);
379 430
380 if (len <= 0) { 431 return err;
381 kfree(str); 432}
382 /* Verified by the above copy_from_user */
383 if (__copy_to_user(argp, &op,
384 sizeof(op)))
385 return -EFAULT;
386 return 0;
387 }
388 433
389 tmp = kmalloc(len + 1, GFP_KERNEL); 434static int opiocnextprop(void __user *argp, DATA *data)
390 if (!tmp) { 435{
391 kfree(str); 436 struct opiocdesc op;
392 return -ENOMEM; 437 struct device_node *dp;
393 } 438 struct property *prop;
439 char *str;
440 int err, len;
394 441
395 cnt = prom_getproperty(op.op_nodeid, str, tmp, len); 442 if (copy_from_user(&op, argp, sizeof(op)))
396 if (cnt <= 0) { 443 return -EFAULT;
397 error = -EINVAL;
398 } else {
399 tmp[len] = '\0';
400 444
401 if (__copy_to_user(argp, &op, sizeof(op)) != 0 || 445 dp = get_node(op.op_nodeid, data);
402 copy_to_user(op.op_buf, tmp, len) != 0) 446 if (!dp)
403 error = -EFAULT; 447 return -EINVAL;
404 }
405 448
406 kfree(tmp); 449 err = copyin_string(op.op_name, op.op_namelen, &str);
407 kfree(str); 450 if (err)
451 return err;
408 452
409 return error; 453 if (str[0] == '\0') {
454 prop = dp->properties;
455 } else {
456 prop = of_find_property(dp, str, NULL);
457 if (prop)
458 prop = prop->next;
459 }
460 kfree(str);
410 461
411 case OPIOCNEXTPROP: 462 if (!prop)
412 if (copy_from_user(&op, argp, sizeof(op))) 463 len = 0;
413 return -EFAULT; 464 else
465 len = prop->length;
414 466
415 if (!goodnode(op.op_nodeid,data)) 467 if (len > op.op_buflen)
416 return -EINVAL; 468 len = op.op_buflen;
417 469
418 error = copyin_string(op.op_name, op.op_namelen, &str); 470 if (copy_to_user(argp, &op, sizeof(op)))
419 if (error) 471 return -EFAULT;
420 return error;
421 472
422 tmp = prom_nextprop(op.op_nodeid,str,buffer); 473 if (len &&
474 copy_to_user(op.op_buf, prop->value, len))
475 return -EFAULT;
423 476
424 if (tmp) { 477 return 0;
425 len = strlen(tmp); 478}
426 if (len > op.op_buflen)
427 len = op.op_buflen;
428 else
429 op.op_buflen = len;
430 } else {
431 len = op.op_buflen = 0;
432 }
433 479
434 if (!access_ok(VERIFY_WRITE, argp, sizeof(op))) { 480static int opiocset(void __user *argp, DATA *data)
435 kfree(str); 481{
436 return -EFAULT; 482 struct opiocdesc op;
437 } 483 struct device_node *dp;
484 char *str, *tmp;
485 int err;
438 486
439 if (!access_ok(VERIFY_WRITE, op.op_buf, len)) { 487 if (copy_from_user(&op, argp, sizeof(op)))
440 kfree(str); 488 return -EFAULT;
441 return -EFAULT; 489
442 } 490 dp = get_node(op.op_nodeid, data);
491 if (!dp)
492 return -EINVAL;
443 493
444 error = __copy_to_user(argp, &op, sizeof(op)); 494 err = copyin_string(op.op_name, op.op_namelen, &str);
445 if (!error) error = __copy_to_user(op.op_buf, tmp, len); 495 if (err)
496 return err;
446 497
498 err = copyin_string(op.op_buf, op.op_buflen, &tmp);
499 if (err) {
447 kfree(str); 500 kfree(str);
501 return err;
502 }
448 503
449 return error; 504 err = of_set_property(dp, str, tmp, op.op_buflen);
450 505
451 case OPIOCSET: 506 kfree(str);
452 if (copy_from_user(&op, argp, sizeof(op))) 507 kfree(tmp);
453 return -EFAULT;
454 508
455 if (!goodnode(op.op_nodeid,data)) 509 return err;
456 return -EINVAL; 510}
457 511
458 error = copyin_string(op.op_name, op.op_namelen, &str); 512static int opiocgetnext(unsigned int cmd, void __user *argp)
459 if (error) 513{
460 return error; 514 struct device_node *dp;
515 phandle nd;
461 516
462 error = copyin_string(op.op_buf, op.op_buflen, &tmp); 517 BUILD_BUG_ON(sizeof(phandle) != sizeof(int));
463 if (error) {
464 kfree(str);
465 return error;
466 }
467 518
468 len = prom_setprop(op.op_nodeid,str,tmp,op.op_buflen+1); 519 if (copy_from_user(&nd, argp, sizeof(phandle)))
520 return -EFAULT;
469 521
470 if (len != op.op_buflen) 522 if (nd == 0) {
523 if (cmd != OPIOCGETNEXT)
471 return -EINVAL; 524 return -EINVAL;
525 dp = of_find_node_by_path("/");
526 } else {
527 dp = of_find_node_by_phandle(nd);
528 nd = 0;
529 if (dp) {
530 if (cmd == OPIOCGETNEXT)
531 dp = dp->sibling;
532 else
533 dp = dp->child;
534 }
535 }
536 if (dp)
537 nd = dp->node;
538 if (copy_to_user(argp, &nd, sizeof(phandle)))
539 return -EFAULT;
472 540
473 kfree(str); 541 return 0;
474 kfree(tmp); 542}
475 543
476 return 0; 544static int openprom_bsd_ioctl(struct inode * inode, struct file * file,
545 unsigned int cmd, unsigned long arg)
546{
547 DATA *data = (DATA *) file->private_data;
548 void __user *argp = (void __user *)arg;
549 int err;
477 550
478 case OPIOCGETOPTNODE: 551 switch (cmd) {
479 if (copy_to_user(argp, &options_node, sizeof(int))) 552 case OPIOCGET:
480 return -EFAULT; 553 err = opiocget(argp, data);
481 return 0; 554 break;
482 555
483 case OPIOCGETNEXT: 556 case OPIOCNEXTPROP:
484 case OPIOCGETCHILD: 557 err = opiocnextprop(argp, data);
485 if (copy_from_user(&node, argp, sizeof(int))) 558 break;
486 return -EFAULT;
487 559
488 if (cmd == OPIOCGETNEXT) 560 case OPIOCSET:
489 node = __prom_getsibling(node); 561 err = opiocset(argp, data);
490 else 562 break;
491 node = __prom_getchild(node); 563
564 case OPIOCGETOPTNODE:
565 BUILD_BUG_ON(sizeof(phandle) != sizeof(int));
492 566
493 if (__copy_to_user(argp, &node, sizeof(int))) 567 if (copy_to_user(argp, &options_node->node, sizeof(phandle)))
494 return -EFAULT; 568 return -EFAULT;
495 569
496 return 0; 570 return 0;
497 571
572 case OPIOCGETNEXT:
573 case OPIOCGETCHILD:
574 err = opiocgetnext(cmd, argp);
575 break;
576
498 default: 577 default:
499 if (cnt++ < 10)
500 printk(KERN_INFO "openprom_bsd_ioctl: cmd 0x%X\n", cmd);
501 return -EINVAL; 578 return -EINVAL;
502 579
503 } 580 };
581
582 return err;
504} 583}
505 584
506 585
@@ -511,7 +590,6 @@ static int openprom_ioctl(struct inode * inode, struct file * file,
511 unsigned int cmd, unsigned long arg) 590 unsigned int cmd, unsigned long arg)
512{ 591{
513 DATA *data = (DATA *) file->private_data; 592 DATA *data = (DATA *) file->private_data;
514 static int cnt;
515 593
516 switch (cmd) { 594 switch (cmd) {
517 case OPROMGETOPT: 595 case OPROMGETOPT:
@@ -563,10 +641,8 @@ static int openprom_ioctl(struct inode * inode, struct file * file,
563 return openprom_bsd_ioctl(inode,file,cmd,arg); 641 return openprom_bsd_ioctl(inode,file,cmd,arg);
564 642
565 default: 643 default:
566 if (cnt++ < 10)
567 printk("openprom_ioctl: cmd 0x%X, arg 0x%lX\n", cmd, arg);
568 return -EINVAL; 644 return -EINVAL;
569 } 645 };
570} 646}
571 647
572static long openprom_compat_ioctl(struct file *file, unsigned int cmd, 648static long openprom_compat_ioctl(struct file *file, unsigned int cmd,
@@ -594,9 +670,7 @@ static long openprom_compat_ioctl(struct file *file, unsigned int cmd,
594 case OPROMSETCUR: 670 case OPROMSETCUR:
595 case OPROMPCI2NODE: 671 case OPROMPCI2NODE:
596 case OPROMPATH2NODE: 672 case OPROMPATH2NODE:
597 lock_kernel();
598 rval = openprom_ioctl(file->f_dentry->d_inode, file, cmd, arg); 673 rval = openprom_ioctl(file->f_dentry->d_inode, file, cmd, arg);
599 lock_kernel();
600 break; 674 break;
601 } 675 }
602 676
@@ -607,13 +681,13 @@ static int openprom_open(struct inode * inode, struct file * file)
607{ 681{
608 DATA *data; 682 DATA *data;
609 683
610 data = (DATA *) kmalloc(sizeof(DATA), GFP_KERNEL); 684 data = kmalloc(sizeof(DATA), GFP_KERNEL);
611 if (!data) 685 if (!data)
612 return -ENOMEM; 686 return -ENOMEM;
613 687
614 data->current_node = prom_root_node; 688 data->current_node = of_find_node_by_path("/");
615 data->lastnode = prom_root_node; 689 data->lastnode = data->current_node;
616 file->private_data = (void *)data; 690 file->private_data = (void *) data;
617 691
618 return 0; 692 return 0;
619} 693}
@@ -634,24 +708,30 @@ static struct file_operations openprom_fops = {
634}; 708};
635 709
636static struct miscdevice openprom_dev = { 710static struct miscdevice openprom_dev = {
637 SUN_OPENPROM_MINOR, "openprom", &openprom_fops 711 .minor = SUN_OPENPROM_MINOR,
712 .name = "openprom",
713 .fops = &openprom_fops,
638}; 714};
639 715
640static int __init openprom_init(void) 716static int __init openprom_init(void)
641{ 717{
642 int error; 718 struct device_node *dp;
719 int err;
643 720
644 error = misc_register(&openprom_dev); 721 err = misc_register(&openprom_dev);
645 if (error) { 722 if (err)
646 printk(KERN_ERR "openprom: unable to get misc minor\n"); 723 return err;
647 return error;
648 }
649 724
650 options_node = prom_getchild(prom_root_node); 725 dp = of_find_node_by_path("/");
651 options_node = prom_searchsiblings(options_node,"options"); 726 dp = dp->child;
727 while (dp) {
728 if (!strcmp(dp->name, "options"))
729 break;
730 dp = dp->sibling;
731 }
732 options_node = dp;
652 733
653 if (options_node == 0 || options_node == -1) { 734 if (!options_node) {
654 printk(KERN_ERR "openprom: unable to find options node\n");
655 misc_deregister(&openprom_dev); 735 misc_deregister(&openprom_dev);
656 return -EIO; 736 return -EIO;
657 } 737 }
@@ -666,4 +746,3 @@ static void __exit openprom_cleanup(void)
666 746
667module_init(openprom_init); 747module_init(openprom_init);
668module_exit(openprom_cleanup); 748module_exit(openprom_cleanup);
669MODULE_LICENSE("GPL");
diff --git a/drivers/sbus/char/riowatchdog.c b/drivers/sbus/char/riowatchdog.c
index d1babff6a535..2a9cc8204429 100644
--- a/drivers/sbus/char/riowatchdog.c
+++ b/drivers/sbus/char/riowatchdog.c
@@ -211,7 +211,7 @@ static int __init riowd_bbc_init(void)
211 211
212 for_each_ebus(ebus) { 212 for_each_ebus(ebus) {
213 for_each_ebusdev(edev, ebus) { 213 for_each_ebusdev(edev, ebus) {
214 if (!strcmp(edev->prom_name, "bbc")) 214 if (!strcmp(edev->ofdev.node->name, "bbc"))
215 goto found_bbc; 215 goto found_bbc;
216 } 216 }
217 } 217 }
@@ -238,7 +238,7 @@ static int __init riowd_init(void)
238 238
239 for_each_ebus(ebus) { 239 for_each_ebus(ebus) {
240 for_each_ebusdev(edev, ebus) { 240 for_each_ebusdev(edev, ebus) {
241 if (!strcmp(edev->prom_name, RIOWD_NAME)) 241 if (!strcmp(edev->ofdev.node->name, RIOWD_NAME))
242 goto ebus_done; 242 goto ebus_done;
243 } 243 }
244 } 244 }
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index efc7c91128af..93a56bd4a2b7 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -1,5 +1,4 @@
1/* $Id: inode.c,v 1.15 2001/11/12 09:43:39 davem Exp $ 1/* inode.c: /proc/openprom handling routines
2 * openpromfs.c: /proc/openprom handling routines
3 * 2 *
4 * Copyright (C) 1996-1999 Jakub Jelinek (jakub@redhat.com) 3 * Copyright (C) 1996-1999 Jakub Jelinek (jakub@redhat.com)
5 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) 4 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
@@ -12,762 +11,245 @@
12#include <linux/openprom_fs.h> 11#include <linux/openprom_fs.h>
13#include <linux/init.h> 12#include <linux/init.h>
14#include <linux/slab.h> 13#include <linux/slab.h>
15#include <linux/smp_lock.h> 14#include <linux/seq_file.h>
16 15
17#include <asm/openprom.h> 16#include <asm/openprom.h>
18#include <asm/oplib.h> 17#include <asm/oplib.h>
18#include <asm/prom.h>
19#include <asm/uaccess.h> 19#include <asm/uaccess.h>
20 20
21#define ALIASES_NNODES 64 21static DEFINE_MUTEX(op_mutex);
22
23typedef struct {
24 u16 parent;
25 u16 next;
26 u16 child;
27 u16 first_prop;
28 u32 node;
29} openpromfs_node;
30
31typedef struct {
32#define OPP_STRING 0x10
33#define OPP_STRINGLIST 0x20
34#define OPP_BINARY 0x40
35#define OPP_HEXSTRING 0x80
36#define OPP_DIRTY 0x01
37#define OPP_QUOTED 0x02
38#define OPP_NOTQUOTED 0x04
39#define OPP_ASCIIZ 0x08
40 u32 flag;
41 u32 alloclen;
42 u32 len;
43 char *value;
44 char name[8];
45} openprom_property;
46
47static openpromfs_node *nodes;
48static int alloced;
49static u16 last_node;
50static u16 first_prop;
51static u16 options = 0xffff;
52static u16 aliases = 0xffff;
53static int aliases_nodes;
54static char *alias_names [ALIASES_NNODES];
55
56#define OPENPROM_ROOT_INO 16
57#define OPENPROM_FIRST_INO OPENPROM_ROOT_INO
58#define NODE(ino) nodes[ino - OPENPROM_FIRST_INO]
59#define NODE2INO(node) (node + OPENPROM_FIRST_INO)
60#define NODEP2INO(no) (no + OPENPROM_FIRST_INO + last_node)
61
62static int openpromfs_create (struct inode *, struct dentry *, int, struct nameidata *);
63static int openpromfs_readdir(struct file *, void *, filldir_t);
64static struct dentry *openpromfs_lookup(struct inode *, struct dentry *dentry, struct nameidata *nd);
65static int openpromfs_unlink (struct inode *, struct dentry *dentry);
66 22
67static inline u16 ptr_nod(void *p) 23#define OPENPROM_ROOT_INO 0
68{
69 return (long)p & 0xFFFF;
70}
71 24
72static ssize_t nodenum_read(struct file *file, char __user *buf, 25enum op_inode_type {
73 size_t count, loff_t *ppos) 26 op_inode_node,
27 op_inode_prop,
28};
29
30union op_inode_data {
31 struct device_node *node;
32 struct property *prop;
33};
34
35struct op_inode_info {
36 struct inode vfs_inode;
37 enum op_inode_type type;
38 union op_inode_data u;
39};
40
41static inline struct op_inode_info *OP_I(struct inode *inode)
74{ 42{
75 struct inode *inode = file->f_dentry->d_inode; 43 return container_of(inode, struct op_inode_info, vfs_inode);
76 char buffer[10];
77
78 if (count < 0 || !inode->u.generic_ip)
79 return -EINVAL;
80 sprintf (buffer, "%8.8lx\n", (long)inode->u.generic_ip);
81 if (file->f_pos >= 9)
82 return 0;
83 if (count > 9 - file->f_pos)
84 count = 9 - file->f_pos;
85 if (copy_to_user(buf, buffer + file->f_pos, count))
86 return -EFAULT;
87 *ppos += count;
88 return count;
89} 44}
90 45
91static ssize_t property_read(struct file *filp, char __user *buf, 46static int is_string(unsigned char *p, int len)
92 size_t count, loff_t *ppos)
93{ 47{
94 struct inode *inode = filp->f_dentry->d_inode; 48 int i;
95 int i, j, k;
96 u32 node;
97 char *p, *s;
98 u32 *q;
99 openprom_property *op;
100 char buffer[64];
101
102 if (!filp->private_data) {
103 node = nodes[ptr_nod(inode->u.generic_ip)].node;
104 i = ((u32)(long)inode->u.generic_ip) >> 16;
105 if (ptr_nod(inode->u.generic_ip) == aliases) {
106 if (i >= aliases_nodes)
107 p = NULL;
108 else
109 p = alias_names [i];
110 } else
111 for (p = prom_firstprop (node, buffer);
112 i && p && *p;
113 p = prom_nextprop (node, p, buffer), i--)
114 /* nothing */ ;
115 if (!p || !*p)
116 return -EIO;
117 i = prom_getproplen (node, p);
118 if (i < 0) {
119 if (ptr_nod(inode->u.generic_ip) == aliases)
120 i = 0;
121 else
122 return -EIO;
123 }
124 k = i;
125 if (i < 64) i = 64;
126 filp->private_data = kmalloc (sizeof (openprom_property)
127 + (j = strlen (p)) + 2 * i,
128 GFP_KERNEL);
129 if (!filp->private_data)
130 return -ENOMEM;
131 op = filp->private_data;
132 op->flag = 0;
133 op->alloclen = 2 * i;
134 strcpy (op->name, p);
135 op->value = (char *)(((unsigned long)(op->name + j + 4)) & ~3);
136 op->len = k;
137 if (k && prom_getproperty (node, p, op->value, i) < 0)
138 return -EIO;
139 op->value [k] = 0;
140 if (k) {
141 for (s = NULL, p = op->value; p < op->value + k; p++) {
142 if ((*p >= ' ' && *p <= '~') || *p == '\n') {
143 op->flag |= OPP_STRING;
144 s = p;
145 continue;
146 }
147 if (p > op->value && !*p && s == p - 1) {
148 if (p < op->value + k - 1)
149 op->flag |= OPP_STRINGLIST;
150 else
151 op->flag |= OPP_ASCIIZ;
152 continue;
153 }
154 if (k == 1 && !*p) {
155 op->flag |= (OPP_STRING|OPP_ASCIIZ);
156 break;
157 }
158 op->flag &= ~(OPP_STRING|OPP_STRINGLIST);
159 if (k & 3)
160 op->flag |= OPP_HEXSTRING;
161 else
162 op->flag |= OPP_BINARY;
163 break;
164 }
165 if (op->flag & OPP_STRINGLIST)
166 op->flag &= ~(OPP_STRING);
167 if (op->flag & OPP_ASCIIZ)
168 op->len--;
169 }
170 } else
171 op = filp->private_data;
172 if (!count || !(op->len || (op->flag & OPP_ASCIIZ)))
173 return 0;
174 if (*ppos >= 0xffffff || count >= 0xffffff)
175 return -EINVAL;
176 if (op->flag & OPP_STRINGLIST) {
177 for (k = 0, p = op->value; p < op->value + op->len; p++)
178 if (!*p)
179 k++;
180 i = op->len + 4 * k + 3;
181 } else if (op->flag & OPP_STRING) {
182 i = op->len + 3;
183 } else if (op->flag & OPP_BINARY) {
184 i = (op->len * 9) >> 2;
185 } else {
186 i = (op->len << 1) + 1;
187 }
188 k = *ppos;
189 if (k >= i) return 0;
190 if (count > i - k) count = i - k;
191 if (op->flag & OPP_STRING) {
192 if (!k) {
193 if (put_user('\'', buf))
194 return -EFAULT;
195 k++;
196 count--;
197 }
198 49
199 if (k + count >= i - 2) 50 for (i = 0; i < len; i++) {
200 j = i - 2 - k; 51 unsigned char val = p[i];
201 else
202 j = count;
203
204 if (j >= 0) {
205 if (copy_to_user(buf + k - *ppos,
206 op->value + k - 1, j))
207 return -EFAULT;
208 count -= j;
209 k += j;
210 }
211 52
212 if (count) { 53 if ((i && !val) ||
213 if (put_user('\'', &buf [k++ - *ppos])) 54 (val >= ' ' && val <= '~'))
214 return -EFAULT; 55 continue;
215 }
216 if (count > 1) {
217 if (put_user('\n', &buf [k++ - *ppos]))
218 return -EFAULT;
219 }
220 } else if (op->flag & OPP_STRINGLIST) {
221 char *tmp;
222
223 tmp = kmalloc (i, GFP_KERNEL);
224 if (!tmp)
225 return -ENOMEM;
226
227 s = tmp;
228 *s++ = '\'';
229 for (p = op->value; p < op->value + op->len; p++) {
230 if (!*p) {
231 strcpy(s, "' + '");
232 s += 5;
233 continue;
234 }
235 *s++ = *p;
236 }
237 strcpy(s, "'\n");
238
239 if (copy_to_user(buf, tmp + k, count))
240 return -EFAULT;
241
242 kfree(tmp);
243 k += count;
244
245 } else if (op->flag & OPP_BINARY) {
246 char buffer[10];
247 u32 *first, *last;
248 int first_off, last_cnt;
249
250 first = ((u32 *)op->value) + k / 9;
251 first_off = k % 9;
252 last = ((u32 *)op->value) + (k + count - 1) / 9;
253 last_cnt = (k + count) % 9;
254 if (!last_cnt) last_cnt = 9;
255
256 if (first == last) {
257 sprintf (buffer, "%08x.", *first);
258 if (copy_to_user(buf, buffer + first_off,
259 last_cnt - first_off))
260 return -EFAULT;
261 buf += last_cnt - first_off;
262 } else {
263 for (q = first; q <= last; q++) {
264 sprintf (buffer, "%08x.", *q);
265 if (q == first) {
266 if (copy_to_user(buf, buffer + first_off,
267 9 - first_off))
268 return -EFAULT;
269 buf += 9 - first_off;
270 } else if (q == last) {
271 if (copy_to_user(buf, buffer, last_cnt))
272 return -EFAULT;
273 buf += last_cnt;
274 } else {
275 if (copy_to_user(buf, buffer, 9))
276 return -EFAULT;
277 buf += 9;
278 }
279 }
280 }
281 56
282 if (last == (u32 *)(op->value + op->len - 4) && last_cnt == 9) { 57 return 0;
283 if (put_user('\n', (buf - 1))) 58 }
284 return -EFAULT;
285 }
286 59
287 k += count; 60 return 1;
61}
288 62
289 } else if (op->flag & OPP_HEXSTRING) { 63static int property_show(struct seq_file *f, void *v)
290 char buffer[3]; 64{
65 struct property *prop = f->private;
66 void *pval;
67 int len;
291 68
292 if ((k < i - 1) && (k & 1)) { 69 len = prop->length;
293 sprintf (buffer, "%02x", 70 pval = prop->value;
294 (unsigned char) *(op->value + (k >> 1)) & 0xff);
295 if (put_user(buffer[1], &buf[k++ - *ppos]))
296 return -EFAULT;
297 count--;
298 }
299 71
300 for (; (count > 1) && (k < i - 1); k += 2) { 72 if (is_string(pval, len)) {
301 sprintf (buffer, "%02x", 73 while (len > 0) {
302 (unsigned char) *(op->value + (k >> 1)) & 0xff); 74 int n = strlen(pval);
303 if (copy_to_user(buf + k - *ppos, buffer, 2))
304 return -EFAULT;
305 count -= 2;
306 }
307 75
308 if (count && (k < i - 1)) { 76 seq_printf(f, "%s", (char *) pval);
309 sprintf (buffer, "%02x",
310 (unsigned char) *(op->value + (k >> 1)) & 0xff);
311 if (put_user(buffer[0], &buf[k++ - *ppos]))
312 return -EFAULT;
313 count--;
314 }
315 77
316 if (count) { 78 /* Skip over the NULL byte too. */
317 if (put_user('\n', &buf [k++ - *ppos])) 79 pval += n + 1;
318 return -EFAULT; 80 len -= n + 1;
319 }
320 }
321 count = k - *ppos;
322 *ppos = k;
323 return count;
324}
325 81
326static ssize_t property_write(struct file *filp, const char __user *buf, 82 if (len > 0)
327 size_t count, loff_t *ppos) 83 seq_printf(f, " + ");
328{
329 int i, j, k;
330 char *p;
331 u32 *q;
332 void *b;
333 openprom_property *op;
334
335 if (*ppos >= 0xffffff || count >= 0xffffff)
336 return -EINVAL;
337 if (!filp->private_data) {
338 i = property_read (filp, NULL, 0, NULL);
339 if (i)
340 return i;
341 }
342 k = *ppos;
343 op = filp->private_data;
344 if (!(op->flag & OPP_STRING)) {
345 u32 *first, *last;
346 int first_off, last_cnt;
347 u32 mask, mask2;
348 char tmp [9];
349 int forcelen = 0;
350
351 j = k % 9;
352 for (i = 0; i < count; i++, j++) {
353 if (j == 9) j = 0;
354 if (!j) {
355 char ctmp;
356 if (get_user(ctmp, &buf[i]))
357 return -EFAULT;
358 if (ctmp != '.') {
359 if (ctmp != '\n') {
360 if (op->flag & OPP_BINARY)
361 return -EINVAL;
362 else
363 goto write_try_string;
364 } else {
365 count = i + 1;
366 forcelen = 1;
367 break;
368 }
369 }
370 } else {
371 char ctmp;
372 if (get_user(ctmp, &buf[i]))
373 return -EFAULT;
374 if (ctmp < '0' ||
375 (ctmp > '9' && ctmp < 'A') ||
376 (ctmp > 'F' && ctmp < 'a') ||
377 ctmp > 'f') {
378 if (op->flag & OPP_BINARY)
379 return -EINVAL;
380 else
381 goto write_try_string;
382 }
383 }
384 }
385 op->flag |= OPP_BINARY;
386 tmp [8] = 0;
387 i = ((count + k + 8) / 9) << 2;
388 if (op->alloclen <= i) {
389 b = kmalloc (sizeof (openprom_property) + 2 * i,
390 GFP_KERNEL);
391 if (!b)
392 return -ENOMEM;
393 memcpy (b, filp->private_data,
394 sizeof (openprom_property)
395 + strlen (op->name) + op->alloclen);
396 memset (b + sizeof (openprom_property)
397 + strlen (op->name) + op->alloclen,
398 0, 2 * i - op->alloclen);
399 op = b;
400 op->alloclen = 2*i;
401 b = filp->private_data;
402 filp->private_data = op;
403 kfree (b);
404 } 84 }
405 first = ((u32 *)op->value) + (k / 9); 85 } else {
406 first_off = k % 9; 86 if (len & 3) {
407 last = (u32 *)(op->value + i); 87 while (len) {
408 last_cnt = (k + count) % 9; 88 len--;
409 if (first + 1 == last) { 89 if (len)
410 memset (tmp, '0', 8); 90 seq_printf(f, "%02x.",
411 if (copy_from_user(tmp + first_off, buf, 91 *(unsigned char *) pval);
412 (count + first_off > 8) ? 92 else
413 8 - first_off : count)) 93 seq_printf(f, "%02x",
414 return -EFAULT; 94 *(unsigned char *) pval);
415 mask = 0xffffffff; 95 pval++;
416 mask2 = 0xffffffff;
417 for (j = 0; j < first_off; j++)
418 mask >>= 1;
419 for (j = 8 - count - first_off; j > 0; j--)
420 mask2 <<= 1;
421 mask &= mask2;
422 if (mask) {
423 *first &= ~mask;
424 *first |= simple_strtoul (tmp, NULL, 16);
425 op->flag |= OPP_DIRTY;
426 } 96 }
427 } else { 97 } else {
428 op->flag |= OPP_DIRTY; 98 while (len >= 4) {
429 for (q = first; q < last; q++) { 99 len -= 4;
430 if (q == first) { 100
431 if (first_off < 8) { 101 if (len)
432 memset (tmp, '0', 8); 102 seq_printf(f, "%08x.",
433 if (copy_from_user(tmp + first_off, 103 *(unsigned int *) pval);
434 buf, 104 else
435 8 - first_off)) 105 seq_printf(f, "%08x",
436 return -EFAULT; 106 *(unsigned int *) pval);
437 mask = 0xffffffff; 107 pval += 4;
438 for (j = 0; j < first_off; j++)
439 mask >>= 1;
440 *q &= ~mask;
441 *q |= simple_strtoul (tmp,NULL,16);
442 }
443 buf += 9;
444 } else if ((q == last - 1) && last_cnt
445 && (last_cnt < 8)) {
446 memset (tmp, '0', 8);
447 if (copy_from_user(tmp, buf, last_cnt))
448 return -EFAULT;
449 mask = 0xffffffff;
450 for (j = 0; j < 8 - last_cnt; j++)
451 mask <<= 1;
452 *q &= ~mask;
453 *q |= simple_strtoul (tmp, NULL, 16);
454 buf += last_cnt;
455 } else {
456 char tchars[2 * sizeof(long) + 1];
457
458 if (copy_from_user(tchars, buf, sizeof(tchars) - 1))
459 return -EFAULT;
460 tchars[sizeof(tchars) - 1] = '\0';
461 *q = simple_strtoul (tchars, NULL, 16);
462 buf += 9;
463 }
464 }
465 }
466 if (!forcelen) {
467 if (op->len < i)
468 op->len = i;
469 } else
470 op->len = i;
471 *ppos += count;
472 }
473write_try_string:
474 if (!(op->flag & OPP_BINARY)) {
475 if (!(op->flag & (OPP_QUOTED | OPP_NOTQUOTED))) {
476 char ctmp;
477
478 /* No way, if somebody starts writing from the middle,
479 * we don't know whether he uses quotes around or not
480 */
481 if (k > 0)
482 return -EINVAL;
483 if (get_user(ctmp, buf))
484 return -EFAULT;
485 if (ctmp == '\'') {
486 op->flag |= OPP_QUOTED;
487 buf++;
488 count--;
489 (*ppos)++;
490 if (!count) {
491 op->flag |= OPP_STRING;
492 return 1;
493 }
494 } else
495 op->flag |= OPP_NOTQUOTED;
496 }
497 op->flag |= OPP_STRING;
498 if (op->alloclen <= count + *ppos) {
499 b = kmalloc (sizeof (openprom_property)
500 + 2 * (count + *ppos), GFP_KERNEL);
501 if (!b)
502 return -ENOMEM;
503 memcpy (b, filp->private_data,
504 sizeof (openprom_property)
505 + strlen (op->name) + op->alloclen);
506 memset (b + sizeof (openprom_property)
507 + strlen (op->name) + op->alloclen,
508 0, 2*(count - *ppos) - op->alloclen);
509 op = b;
510 op->alloclen = 2*(count + *ppos);
511 b = filp->private_data;
512 filp->private_data = op;
513 kfree (b);
514 }
515 p = op->value + *ppos - ((op->flag & OPP_QUOTED) ? 1 : 0);
516 if (copy_from_user(p, buf, count))
517 return -EFAULT;
518 op->flag |= OPP_DIRTY;
519 for (i = 0; i < count; i++, p++)
520 if (*p == '\n') {
521 *p = 0;
522 break;
523 } 108 }
524 if (i < count) {
525 op->len = p - op->value;
526 *ppos += i + 1;
527 if ((p > op->value) && (op->flag & OPP_QUOTED)
528 && (*(p - 1) == '\''))
529 op->len--;
530 } else {
531 if (p - op->value > op->len)
532 op->len = p - op->value;
533 *ppos += count;
534 } 109 }
535 } 110 }
536 return *ppos - k; 111 seq_printf(f, "\n");
112
113 return 0;
537} 114}
538 115
539int property_release (struct inode *inode, struct file *filp) 116static void *property_start(struct seq_file *f, loff_t *pos)
540{ 117{
541 openprom_property *op = filp->private_data; 118 if (*pos == 0)
542 int error; 119 return pos;
543 u32 node; 120 return NULL;
544 121}
545 if (!op) 122
546 return 0; 123static void *property_next(struct seq_file *f, void *v, loff_t *pos)
547 lock_kernel(); 124{
548 node = nodes[ptr_nod(inode->u.generic_ip)].node; 125 (*pos)++;
549 if (ptr_nod(inode->u.generic_ip) == aliases) { 126 return NULL;
550 if ((op->flag & OPP_DIRTY) && (op->flag & OPP_STRING)) { 127}
551 char *p = op->name; 128
552 int i = (op->value - op->name) - strlen (op->name) - 1; 129static void property_stop(struct seq_file *f, void *v)
553 op->value [op->len] = 0; 130{
554 *(op->value - 1) = ' '; 131 /* Nothing to do */
555 if (i) { 132}
556 for (p = op->value - i - 2; p >= op->name; p--) 133
557 p[i] = *p; 134static struct seq_operations property_op = {
558 p = op->name + i; 135 .start = property_start,
559 } 136 .next = property_next,
560 memcpy (p - 8, "nvalias ", 8); 137 .stop = property_stop,
561 prom_feval (p - 8); 138 .show = property_show
562 } 139};
563 } else if (op->flag & OPP_DIRTY) { 140
564 if (op->flag & OPP_STRING) { 141static int property_open(struct inode *inode, struct file *file)
565 op->value [op->len] = 0; 142{
566 error = prom_setprop (node, op->name, 143 struct op_inode_info *oi = OP_I(inode);
567 op->value, op->len + 1); 144 int ret;
568 if (error <= 0) 145
569 printk (KERN_WARNING "openpromfs: " 146 BUG_ON(oi->type != op_inode_prop);
570 "Couldn't write property %s\n", 147
571 op->name); 148 ret = seq_open(file, &property_op);
572 } else if ((op->flag & OPP_BINARY) || !op->len) { 149 if (!ret) {
573 error = prom_setprop (node, op->name, 150 struct seq_file *m = file->private_data;
574 op->value, op->len); 151 m->private = oi->u.prop;
575 if (error <= 0)
576 printk (KERN_WARNING "openpromfs: "
577 "Couldn't write property %s\n",
578 op->name);
579 } else {
580 printk (KERN_WARNING "openpromfs: "
581 "Unknown property type of %s\n",
582 op->name);
583 }
584 } 152 }
585 unlock_kernel(); 153 return ret;
586 kfree (filp->private_data);
587 return 0;
588} 154}
589 155
590static const struct file_operations openpromfs_prop_ops = { 156static const struct file_operations openpromfs_prop_ops = {
591 .read = property_read, 157 .open = property_open,
592 .write = property_write, 158 .read = seq_read,
593 .release = property_release, 159 .llseek = seq_lseek,
160 .release = seq_release,
594}; 161};
595 162
596static const struct file_operations openpromfs_nodenum_ops = { 163static int openpromfs_readdir(struct file *, void *, filldir_t);
597 .read = nodenum_read,
598};
599 164
600static const struct file_operations openprom_operations = { 165static const struct file_operations openprom_operations = {
601 .read = generic_read_dir, 166 .read = generic_read_dir,
602 .readdir = openpromfs_readdir, 167 .readdir = openpromfs_readdir,
603}; 168};
604 169
605static struct inode_operations openprom_alias_inode_operations = { 170static struct dentry *openpromfs_lookup(struct inode *, struct dentry *, struct nameidata *);
606 .create = openpromfs_create,
607 .lookup = openpromfs_lookup,
608 .unlink = openpromfs_unlink,
609};
610 171
611static struct inode_operations openprom_inode_operations = { 172static struct inode_operations openprom_inode_operations = {
612 .lookup = openpromfs_lookup, 173 .lookup = openpromfs_lookup,
613}; 174};
614 175
615static int lookup_children(u16 n, const char * name, int len) 176static struct dentry *openpromfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
616{ 177{
617 int ret; 178 struct op_inode_info *ent_oi, *oi = OP_I(dir);
618 u16 node; 179 struct device_node *dp, *child;
619 for (; n != 0xffff; n = nodes[n].next) { 180 struct property *prop;
620 node = nodes[n].child; 181 enum op_inode_type ent_type;
621 if (node != 0xffff) { 182 union op_inode_data ent_data;
622 char buffer[128];
623 int i;
624 char *p;
625
626 while (node != 0xffff) {
627 if (prom_getname (nodes[node].node,
628 buffer, 128) >= 0) {
629 i = strlen (buffer);
630 if ((len == i)
631 && !strncmp (buffer, name, len))
632 return NODE2INO(node);
633 p = strchr (buffer, '@');
634 if (p && (len == p - buffer)
635 && !strncmp (buffer, name, len))
636 return NODE2INO(node);
637 }
638 node = nodes[node].next;
639 }
640 } else
641 continue;
642 ret = lookup_children (nodes[n].child, name, len);
643 if (ret) return ret;
644 }
645 return 0;
646}
647
648static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
649{
650 int ino = 0;
651#define OPFSL_DIR 0
652#define OPFSL_PROPERTY 1
653#define OPFSL_NODENUM 2
654 int type = 0;
655 char buffer[128];
656 char *p;
657 const char *name; 183 const char *name;
658 u32 n;
659 u16 dirnode;
660 unsigned int len;
661 int i;
662 struct inode *inode; 184 struct inode *inode;
663 char buffer2[64]; 185 unsigned int ino;
186 int len;
664 187
665 inode = NULL; 188 BUG_ON(oi->type != op_inode_node);
189
190 dp = oi->u.node;
191
666 name = dentry->d_name.name; 192 name = dentry->d_name.name;
667 len = dentry->d_name.len; 193 len = dentry->d_name.len;
668 lock_kernel(); 194
669 if (name [0] == '.' && len == 5 && !strncmp (name + 1, "node", 4)) { 195 mutex_lock(&op_mutex);
670 ino = NODEP2INO(NODE(dir->i_ino).first_prop); 196
671 type = OPFSL_NODENUM; 197 child = dp->child;
672 } 198 while (child) {
673 if (!ino) { 199 int n = strlen(child->path_component_name);
674 u16 node = NODE(dir->i_ino).child; 200
675 while (node != 0xffff) { 201 if (len == n &&
676 if (prom_getname (nodes[node].node, buffer, 128) >= 0) { 202 !strncmp(child->path_component_name, name, len)) {
677 i = strlen (buffer); 203 ent_type = op_inode_node;
678 if (len == i && !strncmp (buffer, name, len)) { 204 ent_data.node = child;
679 ino = NODE2INO(node); 205 ino = child->unique_id;
680 type = OPFSL_DIR; 206 goto found;
681 break;
682 }
683 p = strchr (buffer, '@');
684 if (p && (len == p - buffer)
685 && !strncmp (buffer, name, len)) {
686 ino = NODE2INO(node);
687 type = OPFSL_DIR;
688 break;
689 }
690 }
691 node = nodes[node].next;
692 }
693 }
694 n = NODE(dir->i_ino).node;
695 dirnode = dir->i_ino - OPENPROM_FIRST_INO;
696 if (!ino) {
697 int j = NODEP2INO(NODE(dir->i_ino).first_prop);
698 if (dirnode != aliases) {
699 for (p = prom_firstprop (n, buffer2);
700 p && *p;
701 p = prom_nextprop (n, p, buffer2)) {
702 j++;
703 if ((len == strlen (p))
704 && !strncmp (p, name, len)) {
705 ino = j;
706 type = OPFSL_PROPERTY;
707 break;
708 }
709 }
710 } else {
711 int k;
712 for (k = 0; k < aliases_nodes; k++) {
713 j++;
714 if (alias_names [k]
715 && (len == strlen (alias_names [k]))
716 && !strncmp (alias_names [k], name, len)) {
717 ino = j;
718 type = OPFSL_PROPERTY;
719 break;
720 }
721 }
722 } 207 }
208 child = child->sibling;
723 } 209 }
724 if (!ino) { 210
725 ino = lookup_children (NODE(dir->i_ino).child, name, len); 211 prop = dp->properties;
726 if (ino) 212 while (prop) {
727 type = OPFSL_DIR; 213 int n = strlen(prop->name);
728 else { 214
729 unlock_kernel(); 215 if (len == n && !strncmp(prop->name, name, len)) {
730 return ERR_PTR(-ENOENT); 216 ent_type = op_inode_prop;
217 ent_data.prop = prop;
218 ino = prop->unique_id;
219 goto found;
731 } 220 }
221
222 prop = prop->next;
732 } 223 }
733 inode = iget (dir->i_sb, ino); 224
734 unlock_kernel(); 225 mutex_unlock(&op_mutex);
226 return ERR_PTR(-ENOENT);
227
228found:
229 inode = iget(dir->i_sb, ino);
230 mutex_unlock(&op_mutex);
735 if (!inode) 231 if (!inode)
736 return ERR_PTR(-EINVAL); 232 return ERR_PTR(-EINVAL);
737 switch (type) { 233 ent_oi = OP_I(inode);
738 case OPFSL_DIR: 234 ent_oi->type = ent_type;
235 ent_oi->u = ent_data;
236
237 switch (ent_type) {
238 case op_inode_node:
739 inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; 239 inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
740 if (ino == OPENPROM_FIRST_INO + aliases) { 240 inode->i_op = &openprom_inode_operations;
741 inode->i_mode |= S_IWUSR;
742 inode->i_op = &openprom_alias_inode_operations;
743 } else
744 inode->i_op = &openprom_inode_operations;
745 inode->i_fop = &openprom_operations; 241 inode->i_fop = &openprom_operations;
746 inode->i_nlink = 2; 242 inode->i_nlink = 2;
747 break; 243 break;
748 case OPFSL_NODENUM: 244 case op_inode_prop:
749 inode->i_mode = S_IFREG | S_IRUGO; 245 if (!strcmp(dp->name, "options") && (len == 17) &&
750 inode->i_fop = &openpromfs_nodenum_ops; 246 !strncmp (name, "security-password", 17))
751 inode->i_nlink = 1;
752 inode->u.generic_ip = (void *)(long)(n);
753 break;
754 case OPFSL_PROPERTY:
755 if ((dirnode == options) && (len == 17)
756 && !strncmp (name, "security-password", 17))
757 inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR; 247 inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR;
758 else { 248 else
759 inode->i_mode = S_IFREG | S_IRUGO; 249 inode->i_mode = S_IFREG | S_IRUGO;
760 if (dirnode == options || dirnode == aliases) {
761 if (len != 4 || strncmp (name, "name", 4))
762 inode->i_mode |= S_IWUSR;
763 }
764 }
765 inode->i_fop = &openpromfs_prop_ops; 250 inode->i_fop = &openpromfs_prop_ops;
766 inode->i_nlink = 1; 251 inode->i_nlink = 1;
767 if (inode->i_size < 0) 252 inode->i_size = ent_oi->u.prop->length;
768 inode->i_size = 0;
769 inode->u.generic_ip = (void *)(long)(((u16)dirnode) |
770 (((u16)(ino - NODEP2INO(NODE(dir->i_ino).first_prop) - 1)) << 16));
771 break; 253 break;
772 } 254 }
773 255
@@ -781,237 +263,89 @@ static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentr
781static int openpromfs_readdir(struct file * filp, void * dirent, filldir_t filldir) 263static int openpromfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
782{ 264{
783 struct inode *inode = filp->f_dentry->d_inode; 265 struct inode *inode = filp->f_dentry->d_inode;
266 struct op_inode_info *oi = OP_I(inode);
267 struct device_node *dp = oi->u.node;
268 struct device_node *child;
269 struct property *prop;
784 unsigned int ino; 270 unsigned int ino;
785 u32 n; 271 int i;
786 int i, j; 272
787 char buffer[128]; 273 mutex_lock(&op_mutex);
788 u16 node;
789 char *p;
790 char buffer2[64];
791
792 lock_kernel();
793 274
794 ino = inode->i_ino; 275 ino = inode->i_ino;
795 i = filp->f_pos; 276 i = filp->f_pos;
796 switch (i) { 277 switch (i) {
797 case 0: 278 case 0:
798 if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) goto out; 279 if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
280 goto out;
799 i++; 281 i++;
800 filp->f_pos++; 282 filp->f_pos++;
801 /* fall thru */ 283 /* fall thru */
802 case 1: 284 case 1:
803 if (filldir(dirent, "..", 2, i, 285 if (filldir(dirent, "..", 2, i,
804 (NODE(ino).parent == 0xffff) ? 286 (dp->parent == NULL ?
805 OPENPROM_ROOT_INO : NODE2INO(NODE(ino).parent), DT_DIR) < 0) 287 OPENPROM_ROOT_INO :
288 dp->parent->unique_id), DT_DIR) < 0)
806 goto out; 289 goto out;
807 i++; 290 i++;
808 filp->f_pos++; 291 filp->f_pos++;
809 /* fall thru */ 292 /* fall thru */
810 default: 293 default:
811 i -= 2; 294 i -= 2;
812 node = NODE(ino).child; 295
813 while (i && node != 0xffff) { 296 /* First, the children nodes as directories. */
814 node = nodes[node].next; 297 child = dp->child;
298 while (i && child) {
299 child = child->sibling;
815 i--; 300 i--;
816 } 301 }
817 while (node != 0xffff) { 302 while (child) {
818 if (prom_getname (nodes[node].node, buffer, 128) < 0) 303 if (filldir(dirent,
819 goto out; 304 child->path_component_name,
820 if (filldir(dirent, buffer, strlen(buffer), 305 strlen(child->path_component_name),
821 filp->f_pos, NODE2INO(node), DT_DIR) < 0) 306 filp->f_pos, child->unique_id, DT_DIR) < 0)
822 goto out; 307 goto out;
308
823 filp->f_pos++; 309 filp->f_pos++;
824 node = nodes[node].next; 310 child = child->sibling;
825 } 311 }
826 j = NODEP2INO(NODE(ino).first_prop); 312
827 if (!i) { 313 /* Next, the properties as files. */
828 if (filldir(dirent, ".node", 5, filp->f_pos, j, DT_REG) < 0) 314 prop = dp->properties;
315 while (i && prop) {
316 prop = prop->next;
317 i--;
318 }
319 while (prop) {
320 if (filldir(dirent, prop->name, strlen(prop->name),
321 filp->f_pos, prop->unique_id, DT_REG) < 0)
829 goto out; 322 goto out;
323
830 filp->f_pos++; 324 filp->f_pos++;
831 } else 325 prop = prop->next;
832 i--;
833 n = NODE(ino).node;
834 if (ino == OPENPROM_FIRST_INO + aliases) {
835 for (j++; i < aliases_nodes; i++, j++) {
836 if (alias_names [i]) {
837 if (filldir (dirent, alias_names [i],
838 strlen (alias_names [i]),
839 filp->f_pos, j, DT_REG) < 0) goto out;
840 filp->f_pos++;
841 }
842 }
843 } else {
844 for (p = prom_firstprop (n, buffer2);
845 p && *p;
846 p = prom_nextprop (n, p, buffer2)) {
847 j++;
848 if (i) i--;
849 else {
850 if (filldir(dirent, p, strlen(p),
851 filp->f_pos, j, DT_REG) < 0)
852 goto out;
853 filp->f_pos++;
854 }
855 }
856 } 326 }
857 } 327 }
858out: 328out:
859 unlock_kernel(); 329 mutex_unlock(&op_mutex);
860 return 0;
861}
862
863static int openpromfs_create (struct inode *dir, struct dentry *dentry, int mode,
864 struct nameidata *nd)
865{
866 char *p;
867 struct inode *inode;
868
869 if (!dir)
870 return -ENOENT;
871 if (dentry->d_name.len > 256)
872 return -EINVAL;
873 p = kmalloc (dentry->d_name.len + 1, GFP_KERNEL);
874 if (!p)
875 return -ENOMEM;
876 strncpy (p, dentry->d_name.name, dentry->d_name.len);
877 p [dentry->d_name.len] = 0;
878 lock_kernel();
879 if (aliases_nodes == ALIASES_NNODES) {
880 kfree(p);
881 unlock_kernel();
882 return -EIO;
883 }
884 alias_names [aliases_nodes++] = p;
885 inode = iget (dir->i_sb,
886 NODEP2INO(NODE(dir->i_ino).first_prop) + aliases_nodes);
887 if (!inode) {
888 unlock_kernel();
889 return -EINVAL;
890 }
891 inode->i_mode = S_IFREG | S_IRUGO | S_IWUSR;
892 inode->i_fop = &openpromfs_prop_ops;
893 inode->i_nlink = 1;
894 if (inode->i_size < 0) inode->i_size = 0;
895 inode->u.generic_ip = (void *)(long)(((u16)aliases) |
896 (((u16)(aliases_nodes - 1)) << 16));
897 unlock_kernel();
898 d_instantiate(dentry, inode);
899 return 0; 330 return 0;
900} 331}
901 332
902static int openpromfs_unlink (struct inode *dir, struct dentry *dentry) 333static kmem_cache_t *op_inode_cachep;
903{
904 unsigned int len;
905 char *p;
906 const char *name;
907 int i;
908
909 name = dentry->d_name.name;
910 len = dentry->d_name.len;
911 lock_kernel();
912 for (i = 0; i < aliases_nodes; i++)
913 if ((strlen (alias_names [i]) == len)
914 && !strncmp (name, alias_names[i], len)) {
915 char buffer[512];
916
917 p = alias_names [i];
918 alias_names [i] = NULL;
919 kfree (p);
920 strcpy (buffer, "nvunalias ");
921 memcpy (buffer + 10, name, len);
922 buffer [10 + len] = 0;
923 prom_feval (buffer);
924 }
925 unlock_kernel();
926 return 0;
927}
928 334
929/* {{{ init section */ 335static struct inode *openprom_alloc_inode(struct super_block *sb)
930static int __init check_space (u16 n)
931{ 336{
932 unsigned long pages; 337 struct op_inode_info *oi;
933 338
934 if ((1 << alloced) * PAGE_SIZE < (n + 2) * sizeof(openpromfs_node)) { 339 oi = kmem_cache_alloc(op_inode_cachep, SLAB_KERNEL);
935 pages = __get_free_pages (GFP_KERNEL, alloced + 1); 340 if (!oi)
936 if (!pages) 341 return NULL;
937 return -1;
938 342
939 if (nodes) { 343 return &oi->vfs_inode;
940 memcpy ((char *)pages, nodes,
941 (1 << alloced) * PAGE_SIZE);
942 free_pages ((unsigned long)nodes, alloced);
943 }
944 alloced++;
945 nodes = (openpromfs_node *)pages;
946 }
947 return 0;
948} 344}
949 345
950static u16 __init get_nodes (u16 parent, u32 node) 346static void openprom_destroy_inode(struct inode *inode)
951{ 347{
952 char *p; 348 kmem_cache_free(op_inode_cachep, OP_I(inode));
953 u16 n = last_node++, i;
954 char buffer[64];
955
956 if (check_space (n) < 0)
957 return 0xffff;
958 nodes[n].parent = parent;
959 nodes[n].node = node;
960 nodes[n].next = 0xffff;
961 nodes[n].child = 0xffff;
962 nodes[n].first_prop = first_prop++;
963 if (!parent) {
964 char buffer[8];
965 int j;
966
967 if ((j = prom_getproperty (node, "name", buffer, 8)) >= 0) {
968 buffer[j] = 0;
969 if (!strcmp (buffer, "options"))
970 options = n;
971 else if (!strcmp (buffer, "aliases"))
972 aliases = n;
973 }
974 }
975 if (n != aliases)
976 for (p = prom_firstprop (node, buffer);
977 p && p != (char *)-1 && *p;
978 p = prom_nextprop (node, p, buffer))
979 first_prop++;
980 else {
981 char *q;
982 for (p = prom_firstprop (node, buffer);
983 p && p != (char *)-1 && *p;
984 p = prom_nextprop (node, p, buffer)) {
985 if (aliases_nodes == ALIASES_NNODES)
986 break;
987 for (i = 0; i < aliases_nodes; i++)
988 if (!strcmp (p, alias_names [i]))
989 break;
990 if (i < aliases_nodes)
991 continue;
992 q = kmalloc (strlen (p) + 1, GFP_KERNEL);
993 if (!q)
994 return 0xffff;
995 strcpy (q, p);
996 alias_names [aliases_nodes++] = q;
997 }
998 first_prop += ALIASES_NNODES;
999 }
1000 node = prom_getchild (node);
1001 if (node) {
1002 parent = get_nodes (n, node);
1003 if (parent == 0xffff)
1004 return 0xffff;
1005 nodes[n].child = parent;
1006 while ((node = prom_getsibling (node)) != 0) {
1007 i = get_nodes (n, node);
1008 if (i == 0xffff)
1009 return 0xffff;
1010 nodes[parent].next = i;
1011 parent = i;
1012 }
1013 }
1014 return n;
1015} 349}
1016 350
1017static void openprom_read_inode(struct inode * inode) 351static void openprom_read_inode(struct inode * inode)
@@ -1031,6 +365,8 @@ static int openprom_remount(struct super_block *sb, int *flags, char *data)
1031} 365}
1032 366
1033static struct super_operations openprom_sops = { 367static struct super_operations openprom_sops = {
368 .alloc_inode = openprom_alloc_inode,
369 .destroy_inode = openprom_destroy_inode,
1034 .read_inode = openprom_read_inode, 370 .read_inode = openprom_read_inode,
1035 .statfs = simple_statfs, 371 .statfs = simple_statfs,
1036 .remount_fs = openprom_remount, 372 .remount_fs = openprom_remount,
@@ -1038,7 +374,8 @@ static struct super_operations openprom_sops = {
1038 374
1039static int openprom_fill_super(struct super_block *s, void *data, int silent) 375static int openprom_fill_super(struct super_block *s, void *data, int silent)
1040{ 376{
1041 struct inode * root_inode; 377 struct inode *root_inode;
378 struct op_inode_info *oi;
1042 379
1043 s->s_flags |= MS_NOATIME; 380 s->s_flags |= MS_NOATIME;
1044 s->s_blocksize = 1024; 381 s->s_blocksize = 1024;
@@ -1049,6 +386,11 @@ static int openprom_fill_super(struct super_block *s, void *data, int silent)
1049 root_inode = iget(s, OPENPROM_ROOT_INO); 386 root_inode = iget(s, OPENPROM_ROOT_INO);
1050 if (!root_inode) 387 if (!root_inode)
1051 goto out_no_root; 388 goto out_no_root;
389
390 oi = OP_I(root_inode);
391 oi->type = op_inode_node;
392 oi->u.node = of_find_node_by_path("/");
393
1052 s->s_root = d_alloc_root(root_inode); 394 s->s_root = d_alloc_root(root_inode);
1053 if (!s->s_root) 395 if (!s->s_root)
1054 goto out_no_root; 396 goto out_no_root;
@@ -1073,29 +415,39 @@ static struct file_system_type openprom_fs_type = {
1073 .kill_sb = kill_anon_super, 415 .kill_sb = kill_anon_super,
1074}; 416};
1075 417
418static void op_inode_init_once(void *data, kmem_cache_t * cachep, unsigned long flags)
419{
420 struct op_inode_info *oi = (struct op_inode_info *) data;
421
422 if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
423 SLAB_CTOR_CONSTRUCTOR)
424 inode_init_once(&oi->vfs_inode);
425}
426
1076static int __init init_openprom_fs(void) 427static int __init init_openprom_fs(void)
1077{ 428{
1078 nodes = (openpromfs_node *)__get_free_pages(GFP_KERNEL, 0); 429 int err;
1079 if (!nodes) { 430
1080 printk (KERN_WARNING "openpromfs: can't get free page\n"); 431 op_inode_cachep = kmem_cache_create("op_inode_cache",
1081 return -EIO; 432 sizeof(struct op_inode_info),
1082 } 433 0,
1083 if (get_nodes (0xffff, prom_root_node) == 0xffff) { 434 (SLAB_RECLAIM_ACCOUNT |
1084 printk (KERN_WARNING "openpromfs: couldn't setup tree\n"); 435 SLAB_MEM_SPREAD),
1085 return -EIO; 436 op_inode_init_once, NULL);
1086 } 437 if (!op_inode_cachep)
1087 nodes[last_node].first_prop = first_prop; 438 return -ENOMEM;
1088 return register_filesystem(&openprom_fs_type); 439
440 err = register_filesystem(&openprom_fs_type);
441 if (err)
442 kmem_cache_destroy(op_inode_cachep);
443
444 return err;
1089} 445}
1090 446
1091static void __exit exit_openprom_fs(void) 447static void __exit exit_openprom_fs(void)
1092{ 448{
1093 int i;
1094 unregister_filesystem(&openprom_fs_type); 449 unregister_filesystem(&openprom_fs_type);
1095 free_pages ((unsigned long)nodes, alloced); 450 kmem_cache_destroy(op_inode_cachep);
1096 for (i = 0; i < aliases_nodes; i++)
1097 kfree (alias_names [i]);
1098 nodes = NULL;
1099} 451}
1100 452
1101module_init(init_openprom_fs) 453module_init(init_openprom_fs)
diff --git a/include/asm-sparc/io.h b/include/asm-sparc/io.h
index a42df208d590..cab0b851b8b1 100644
--- a/include/asm-sparc/io.h
+++ b/include/asm-sparc/io.h
@@ -249,6 +249,22 @@ extern void __iomem *ioremap(unsigned long offset, unsigned long size);
249#define ioremap_nocache(X,Y) ioremap((X),(Y)) 249#define ioremap_nocache(X,Y) ioremap((X),(Y))
250extern void iounmap(volatile void __iomem *addr); 250extern void iounmap(volatile void __iomem *addr);
251 251
252#define ioread8(X) readb(X)
253#define ioread16(X) readw(X)
254#define ioread32(X) readl(X)
255#define iowrite8(val,X) writeb(val,X)
256#define iowrite16(val,X) writew(val,X)
257#define iowrite32(val,X) writel(val,X)
258
259/* Create a virtual mapping cookie for an IO port range */
260extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
261extern void ioport_unmap(void __iomem *);
262
263/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
264struct pci_dev;
265extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
266extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
267
252/* 268/*
253 * Bus number may be in res->flags... somewhere. 269 * Bus number may be in res->flags... somewhere.
254 */ 270 */
diff --git a/include/asm-sparc/prom.h b/include/asm-sparc/prom.h
index c5e3d26eabd3..f9cf44c07164 100644
--- a/include/asm-sparc/prom.h
+++ b/include/asm-sparc/prom.h
@@ -35,6 +35,8 @@ struct property {
35 int length; 35 int length;
36 void *value; 36 void *value;
37 struct property *next; 37 struct property *next;
38 unsigned long _flags;
39 unsigned int unique_id;
38}; 40};
39 41
40struct device_node { 42struct device_node {
@@ -58,8 +60,15 @@ struct device_node {
58 struct kref kref; 60 struct kref kref;
59 unsigned long _flags; 61 unsigned long _flags;
60 void *data; 62 void *data;
63 unsigned int unique_id;
61}; 64};
62 65
66/* flag descriptions */
67#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
68
69#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
70#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
71
63static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de) 72static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de)
64{ 73{
65 dn->pde = de; 74 dn->pde = de;
@@ -88,6 +97,7 @@ extern struct property *of_find_property(struct device_node *np,
88extern int of_device_is_compatible(struct device_node *device, const char *); 97extern int of_device_is_compatible(struct device_node *device, const char *);
89extern void *of_get_property(struct device_node *node, const char *name, 98extern void *of_get_property(struct device_node *node, const char *name,
90 int *lenp); 99 int *lenp);
100extern int of_set_property(struct device_node *node, const char *name, void *val, int len);
91extern int of_getintprop_default(struct device_node *np, 101extern int of_getintprop_default(struct device_node *np,
92 const char *name, 102 const char *name,
93 int def); 103 int def);
diff --git a/include/asm-sparc64/dma-mapping.h b/include/asm-sparc64/dma-mapping.h
index 3c2b5bc8650b..0f5b89c9323b 100644
--- a/include/asm-sparc64/dma-mapping.h
+++ b/include/asm-sparc64/dma-mapping.h
@@ -162,4 +162,47 @@ static inline void dma_free_coherent(struct device *dev, size_t size,
162 162
163#endif /* PCI */ 163#endif /* PCI */
164 164
165
166/* Now for the API extensions over the pci_ one */
167
168#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
169#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
170#define dma_is_consistent(d) (1)
171
172static inline int
173dma_get_cache_alignment(void)
174{
175 /* no easy way to get cache size on all processors, so return
176 * the maximum possible, to be safe */
177 return (1 << INTERNODE_CACHE_SHIFT);
178}
179
180static inline void
181dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
182 unsigned long offset, size_t size,
183 enum dma_data_direction direction)
184{
185 /* just sync everything, that's all the pci API can do */
186 dma_sync_single_for_cpu(dev, dma_handle, offset+size, direction);
187}
188
189static inline void
190dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
191 unsigned long offset, size_t size,
192 enum dma_data_direction direction)
193{
194 /* just sync everything, that's all the pci API can do */
195 dma_sync_single_for_device(dev, dma_handle, offset+size, direction);
196}
197
198static inline void
199dma_cache_sync(void *vaddr, size_t size,
200 enum dma_data_direction direction)
201{
202 /* could define this in terms of the dma_cache ... operations,
203 * but if you get this on a platform, you should convert the platform
204 * to using the generic device DMA API */
205 BUG();
206}
207
165#endif /* _ASM_SPARC64_DMA_MAPPING_H */ 208#endif /* _ASM_SPARC64_DMA_MAPPING_H */
diff --git a/include/asm-sparc64/floppy.h b/include/asm-sparc64/floppy.h
index f8d57bb5570c..b591d0e8d8f0 100644
--- a/include/asm-sparc64/floppy.h
+++ b/include/asm-sparc64/floppy.h
@@ -208,7 +208,55 @@ static void sun_fd_enable_dma(void)
208 pdma_areasize = pdma_size; 208 pdma_areasize = pdma_size;
209} 209}
210 210
211extern irqreturn_t sparc_floppy_irq(int, void *, struct pt_regs *); 211irqreturn_t sparc_floppy_irq(int irq, void *dev_cookie, struct pt_regs *regs)
212{
213 if (likely(doing_pdma)) {
214 void __iomem *stat = (void __iomem *) fdc_status;
215 unsigned char *vaddr = pdma_vaddr;
216 unsigned long size = pdma_size;
217 u8 val;
218
219 while (size) {
220 val = readb(stat);
221 if (unlikely(!(val & 0x80))) {
222 pdma_vaddr = vaddr;
223 pdma_size = size;
224 return IRQ_HANDLED;
225 }
226 if (unlikely(!(val & 0x20))) {
227 pdma_vaddr = vaddr;
228 pdma_size = size;
229 doing_pdma = 0;
230 goto main_interrupt;
231 }
232 if (val & 0x40) {
233 /* read */
234 *vaddr++ = readb(stat + 1);
235 } else {
236 unsigned char data = *vaddr++;
237
238 /* write */
239 writeb(data, stat + 1);
240 }
241 size--;
242 }
243
244 pdma_vaddr = vaddr;
245 pdma_size = size;
246
247 /* Send Terminal Count pulse to floppy controller. */
248 val = readb(auxio_register);
249 val |= AUXIO_AUX1_FTCNT;
250 writeb(val, auxio_register);
251 val &= ~AUXIO_AUX1_FTCNT;
252 writeb(val, auxio_register);
253
254 doing_pdma = 0;
255 }
256
257main_interrupt:
258 return floppy_interrupt(irq, dev_cookie, regs);
259}
212 260
213static int sun_fd_request_irq(void) 261static int sun_fd_request_irq(void)
214{ 262{
diff --git a/include/asm-sparc64/prom.h b/include/asm-sparc64/prom.h
index 6d1556c0c263..265614d497c4 100644
--- a/include/asm-sparc64/prom.h
+++ b/include/asm-sparc64/prom.h
@@ -35,6 +35,8 @@ struct property {
35 int length; 35 int length;
36 void *value; 36 void *value;
37 struct property *next; 37 struct property *next;
38 unsigned long _flags;
39 unsigned int unique_id;
38}; 40};
39 41
40struct device_node { 42struct device_node {
@@ -58,8 +60,15 @@ struct device_node {
58 struct kref kref; 60 struct kref kref;
59 unsigned long _flags; 61 unsigned long _flags;
60 void *data; 62 void *data;
63 unsigned int unique_id;
61}; 64};
62 65
66/* flag descriptions */
67#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
68
69#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
70#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
71
63static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de) 72static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de)
64{ 73{
65 dn->pde = de; 74 dn->pde = de;
@@ -88,6 +97,7 @@ extern struct property *of_find_property(struct device_node *np,
88extern int of_device_is_compatible(struct device_node *device, const char *); 97extern int of_device_is_compatible(struct device_node *device, const char *);
89extern void *of_get_property(struct device_node *node, const char *name, 98extern void *of_get_property(struct device_node *node, const char *name,
90 int *lenp); 99 int *lenp);
100extern int of_set_property(struct device_node *node, const char *name, void *val, int len);
91extern int of_getintprop_default(struct device_node *np, 101extern int of_getintprop_default(struct device_node *np,
92 const char *name, 102 const char *name,
93 int def); 103 int def);