aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-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
5 files changed, 435 insertions, 361 deletions
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 }