powerpc/kprobes: Fix validation of prefixed instructions across page boundary
[sfrench/cifs-2.6.git] / arch / powerpc / kernel / rtas-proc.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *   Copyright (C) 2000 Tilmann Bitterberg
4  *   (tilmann@bitterberg.de)
5  *
6  *   RTAS (Runtime Abstraction Services) stuff
7  *   Intention is to provide a clean user interface
8  *   to use the RTAS.
9  *
10  *   TODO:
11  *   Split off a header file and maybe move it to a different
12  *   location. Write Documentation on what the /proc/rtas/ entries
13  *   actually do.
14  */
15
16 #include <linux/errno.h>
17 #include <linux/sched.h>
18 #include <linux/proc_fs.h>
19 #include <linux/stat.h>
20 #include <linux/ctype.h>
21 #include <linux/time.h>
22 #include <linux/string.h>
23 #include <linux/init.h>
24 #include <linux/seq_file.h>
25 #include <linux/bitops.h>
26 #include <linux/rtc.h>
27
28 #include <linux/uaccess.h>
29 #include <asm/processor.h>
30 #include <asm/io.h>
31 #include <asm/prom.h>
32 #include <asm/rtas.h>
33 #include <asm/machdep.h> /* for ppc_md */
34 #include <asm/time.h>
35
36 /* Token for Sensors */
37 #define KEY_SWITCH              0x0001
38 #define ENCLOSURE_SWITCH        0x0002
39 #define THERMAL_SENSOR          0x0003
40 #define LID_STATUS              0x0004
41 #define POWER_SOURCE            0x0005
42 #define BATTERY_VOLTAGE         0x0006
43 #define BATTERY_REMAINING       0x0007
44 #define BATTERY_PERCENTAGE      0x0008
45 #define EPOW_SENSOR             0x0009
46 #define BATTERY_CYCLESTATE      0x000a
47 #define BATTERY_CHARGING        0x000b
48
49 /* IBM specific sensors */
50 #define IBM_SURVEILLANCE        0x2328 /* 9000 */
51 #define IBM_FANRPM              0x2329 /* 9001 */
52 #define IBM_VOLTAGE             0x232a /* 9002 */
53 #define IBM_DRCONNECTOR         0x232b /* 9003 */
54 #define IBM_POWERSUPPLY         0x232c /* 9004 */
55
56 /* Status return values */
57 #define SENSOR_CRITICAL_HIGH    13
58 #define SENSOR_WARNING_HIGH     12
59 #define SENSOR_NORMAL           11
60 #define SENSOR_WARNING_LOW      10
61 #define SENSOR_CRITICAL_LOW      9
62 #define SENSOR_SUCCESS           0
63 #define SENSOR_HW_ERROR         -1
64 #define SENSOR_BUSY             -2
65 #define SENSOR_NOT_EXIST        -3
66 #define SENSOR_DR_ENTITY        -9000
67
68 /* Location Codes */
69 #define LOC_SCSI_DEV_ADDR       'A'
70 #define LOC_SCSI_DEV_LOC        'B'
71 #define LOC_CPU                 'C'
72 #define LOC_DISKETTE            'D'
73 #define LOC_ETHERNET            'E'
74 #define LOC_FAN                 'F'
75 #define LOC_GRAPHICS            'G'
76 /* reserved / not used          'H' */
77 #define LOC_IO_ADAPTER          'I'
78 /* reserved / not used          'J' */
79 #define LOC_KEYBOARD            'K'
80 #define LOC_LCD                 'L'
81 #define LOC_MEMORY              'M'
82 #define LOC_NV_MEMORY           'N'
83 #define LOC_MOUSE               'O'
84 #define LOC_PLANAR              'P'
85 #define LOC_OTHER_IO            'Q'
86 #define LOC_PARALLEL            'R'
87 #define LOC_SERIAL              'S'
88 #define LOC_DEAD_RING           'T'
89 #define LOC_RACKMOUNTED         'U' /* for _u_nit is rack mounted */
90 #define LOC_VOLTAGE             'V'
91 #define LOC_SWITCH_ADAPTER      'W'
92 #define LOC_OTHER               'X'
93 #define LOC_FIRMWARE            'Y'
94 #define LOC_SCSI                'Z'
95
96 /* Tokens for indicators */
97 #define TONE_FREQUENCY          0x0001 /* 0 - 1000 (HZ)*/
98 #define TONE_VOLUME             0x0002 /* 0 - 100 (%) */
99 #define SYSTEM_POWER_STATE      0x0003 
100 #define WARNING_LIGHT           0x0004
101 #define DISK_ACTIVITY_LIGHT     0x0005
102 #define HEX_DISPLAY_UNIT        0x0006
103 #define BATTERY_WARNING_TIME    0x0007
104 #define CONDITION_CYCLE_REQUEST 0x0008
105 #define SURVEILLANCE_INDICATOR  0x2328 /* 9000 */
106 #define DR_ACTION               0x2329 /* 9001 */
107 #define DR_INDICATOR            0x232a /* 9002 */
108 /* 9003 - 9004: Vendor specific */
109 /* 9006 - 9999: Vendor specific */
110
111 /* other */
112 #define MAX_SENSORS              17  /* I only know of 17 sensors */    
113 #define MAX_LINELENGTH          256
114 #define SENSOR_PREFIX           "ibm,sensor-"
115 #define cel_to_fahr(x)          ((x*9/5)+32)
116
117 struct individual_sensor {
118         unsigned int token;
119         unsigned int quant;
120 };
121
122 struct rtas_sensors {
123         struct individual_sensor sensor[MAX_SENSORS];
124         unsigned int quant;
125 };
126
127 /* Globals */
128 static struct rtas_sensors sensors;
129 static struct device_node *rtas_node = NULL;
130 static unsigned long power_on_time = 0; /* Save the time the user set */
131 static char progress_led[MAX_LINELENGTH];
132
133 static unsigned long rtas_tone_frequency = 1000;
134 static unsigned long rtas_tone_volume = 0;
135
136 /* ****************************************************************** */
137 /* Declarations */
138 static int ppc_rtas_sensors_show(struct seq_file *m, void *v);
139 static int ppc_rtas_clock_show(struct seq_file *m, void *v);
140 static ssize_t ppc_rtas_clock_write(struct file *file,
141                 const char __user *buf, size_t count, loff_t *ppos);
142 static int ppc_rtas_progress_show(struct seq_file *m, void *v);
143 static ssize_t ppc_rtas_progress_write(struct file *file,
144                 const char __user *buf, size_t count, loff_t *ppos);
145 static int ppc_rtas_poweron_show(struct seq_file *m, void *v);
146 static ssize_t ppc_rtas_poweron_write(struct file *file,
147                 const char __user *buf, size_t count, loff_t *ppos);
148
149 static ssize_t ppc_rtas_tone_freq_write(struct file *file,
150                 const char __user *buf, size_t count, loff_t *ppos);
151 static int ppc_rtas_tone_freq_show(struct seq_file *m, void *v);
152 static ssize_t ppc_rtas_tone_volume_write(struct file *file,
153                 const char __user *buf, size_t count, loff_t *ppos);
154 static int ppc_rtas_tone_volume_show(struct seq_file *m, void *v);
155 static int ppc_rtas_rmo_buf_show(struct seq_file *m, void *v);
156
157 static int poweron_open(struct inode *inode, struct file *file)
158 {
159         return single_open(file, ppc_rtas_poweron_show, NULL);
160 }
161
162 static const struct proc_ops ppc_rtas_poweron_proc_ops = {
163         .proc_open      = poweron_open,
164         .proc_read      = seq_read,
165         .proc_lseek     = seq_lseek,
166         .proc_write     = ppc_rtas_poweron_write,
167         .proc_release   = single_release,
168 };
169
170 static int progress_open(struct inode *inode, struct file *file)
171 {
172         return single_open(file, ppc_rtas_progress_show, NULL);
173 }
174
175 static const struct proc_ops ppc_rtas_progress_proc_ops = {
176         .proc_open      = progress_open,
177         .proc_read      = seq_read,
178         .proc_lseek     = seq_lseek,
179         .proc_write     = ppc_rtas_progress_write,
180         .proc_release   = single_release,
181 };
182
183 static int clock_open(struct inode *inode, struct file *file)
184 {
185         return single_open(file, ppc_rtas_clock_show, NULL);
186 }
187
188 static const struct proc_ops ppc_rtas_clock_proc_ops = {
189         .proc_open      = clock_open,
190         .proc_read      = seq_read,
191         .proc_lseek     = seq_lseek,
192         .proc_write     = ppc_rtas_clock_write,
193         .proc_release   = single_release,
194 };
195
196 static int tone_freq_open(struct inode *inode, struct file *file)
197 {
198         return single_open(file, ppc_rtas_tone_freq_show, NULL);
199 }
200
201 static const struct proc_ops ppc_rtas_tone_freq_proc_ops = {
202         .proc_open      = tone_freq_open,
203         .proc_read      = seq_read,
204         .proc_lseek     = seq_lseek,
205         .proc_write     = ppc_rtas_tone_freq_write,
206         .proc_release   = single_release,
207 };
208
209 static int tone_volume_open(struct inode *inode, struct file *file)
210 {
211         return single_open(file, ppc_rtas_tone_volume_show, NULL);
212 }
213
214 static const struct proc_ops ppc_rtas_tone_volume_proc_ops = {
215         .proc_open      = tone_volume_open,
216         .proc_read      = seq_read,
217         .proc_lseek     = seq_lseek,
218         .proc_write     = ppc_rtas_tone_volume_write,
219         .proc_release   = single_release,
220 };
221
222 static int ppc_rtas_find_all_sensors(void);
223 static void ppc_rtas_process_sensor(struct seq_file *m,
224         struct individual_sensor *s, int state, int error, const char *loc);
225 static char *ppc_rtas_process_error(int error);
226 static void get_location_code(struct seq_file *m,
227         struct individual_sensor *s, const char *loc);
228 static void check_location_string(struct seq_file *m, const char *c);
229 static void check_location(struct seq_file *m, const char *c);
230
231 static int __init proc_rtas_init(void)
232 {
233         if (!machine_is(pseries))
234                 return -ENODEV;
235
236         rtas_node = of_find_node_by_name(NULL, "rtas");
237         if (rtas_node == NULL)
238                 return -ENODEV;
239
240         proc_create("powerpc/rtas/progress", 0644, NULL,
241                     &ppc_rtas_progress_proc_ops);
242         proc_create("powerpc/rtas/clock", 0644, NULL,
243                     &ppc_rtas_clock_proc_ops);
244         proc_create("powerpc/rtas/poweron", 0644, NULL,
245                     &ppc_rtas_poweron_proc_ops);
246         proc_create_single("powerpc/rtas/sensors", 0444, NULL,
247                         ppc_rtas_sensors_show);
248         proc_create("powerpc/rtas/frequency", 0644, NULL,
249                     &ppc_rtas_tone_freq_proc_ops);
250         proc_create("powerpc/rtas/volume", 0644, NULL,
251                     &ppc_rtas_tone_volume_proc_ops);
252         proc_create_single("powerpc/rtas/rmo_buffer", 0400, NULL,
253                         ppc_rtas_rmo_buf_show);
254         return 0;
255 }
256
257 __initcall(proc_rtas_init);
258
259 static int parse_number(const char __user *p, size_t count, u64 *val)
260 {
261         char buf[40];
262         char *end;
263
264         if (count > 39)
265                 return -EINVAL;
266
267         if (copy_from_user(buf, p, count))
268                 return -EFAULT;
269
270         buf[count] = 0;
271
272         *val = simple_strtoull(buf, &end, 10);
273         if (*end && *end != '\n')
274                 return -EINVAL;
275
276         return 0;
277 }
278
279 /* ****************************************************************** */
280 /* POWER-ON-TIME                                                      */
281 /* ****************************************************************** */
282 static ssize_t ppc_rtas_poweron_write(struct file *file,
283                 const char __user *buf, size_t count, loff_t *ppos)
284 {
285         struct rtc_time tm;
286         time64_t nowtime;
287         int error = parse_number(buf, count, &nowtime);
288         if (error)
289                 return error;
290
291         power_on_time = nowtime; /* save the time */
292
293         rtc_time64_to_tm(nowtime, &tm);
294
295         error = rtas_call(rtas_token("set-time-for-power-on"), 7, 1, NULL, 
296                         tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
297                         tm.tm_hour, tm.tm_min, tm.tm_sec, 0 /* nano */);
298         if (error)
299                 printk(KERN_WARNING "error: setting poweron time returned: %s\n", 
300                                 ppc_rtas_process_error(error));
301         return count;
302 }
303 /* ****************************************************************** */
304 static int ppc_rtas_poweron_show(struct seq_file *m, void *v)
305 {
306         if (power_on_time == 0)
307                 seq_printf(m, "Power on time not set\n");
308         else
309                 seq_printf(m, "%lu\n",power_on_time);
310         return 0;
311 }
312
313 /* ****************************************************************** */
314 /* PROGRESS                                                           */
315 /* ****************************************************************** */
316 static ssize_t ppc_rtas_progress_write(struct file *file,
317                 const char __user *buf, size_t count, loff_t *ppos)
318 {
319         unsigned long hex;
320
321         if (count >= MAX_LINELENGTH)
322                 count = MAX_LINELENGTH -1;
323         if (copy_from_user(progress_led, buf, count)) { /* save the string */
324                 return -EFAULT;
325         }
326         progress_led[count] = 0;
327
328         /* Lets see if the user passed hexdigits */
329         hex = simple_strtoul(progress_led, NULL, 10);
330
331         rtas_progress ((char *)progress_led, hex);
332         return count;
333
334         /* clear the line */
335         /* rtas_progress("                   ", 0xffff);*/
336 }
337 /* ****************************************************************** */
338 static int ppc_rtas_progress_show(struct seq_file *m, void *v)
339 {
340         if (progress_led[0])
341                 seq_printf(m, "%s\n", progress_led);
342         return 0;
343 }
344
345 /* ****************************************************************** */
346 /* CLOCK                                                              */
347 /* ****************************************************************** */
348 static ssize_t ppc_rtas_clock_write(struct file *file,
349                 const char __user *buf, size_t count, loff_t *ppos)
350 {
351         struct rtc_time tm;
352         time64_t nowtime;
353         int error = parse_number(buf, count, &nowtime);
354         if (error)
355                 return error;
356
357         rtc_time64_to_tm(nowtime, &tm);
358         error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL, 
359                         tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
360                         tm.tm_hour, tm.tm_min, tm.tm_sec, 0);
361         if (error)
362                 printk(KERN_WARNING "error: setting the clock returned: %s\n", 
363                                 ppc_rtas_process_error(error));
364         return count;
365 }
366 /* ****************************************************************** */
367 static int ppc_rtas_clock_show(struct seq_file *m, void *v)
368 {
369         int ret[8];
370         int error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);
371
372         if (error) {
373                 printk(KERN_WARNING "error: reading the clock returned: %s\n", 
374                                 ppc_rtas_process_error(error));
375                 seq_printf(m, "0");
376         } else { 
377                 unsigned int year, mon, day, hour, min, sec;
378                 year = ret[0]; mon  = ret[1]; day  = ret[2];
379                 hour = ret[3]; min  = ret[4]; sec  = ret[5];
380                 seq_printf(m, "%lld\n",
381                                 mktime64(year, mon, day, hour, min, sec));
382         }
383         return 0;
384 }
385
386 /* ****************************************************************** */
387 /* SENSOR STUFF                                                       */
388 /* ****************************************************************** */
389 static int ppc_rtas_sensors_show(struct seq_file *m, void *v)
390 {
391         int i,j;
392         int state, error;
393         int get_sensor_state = rtas_token("get-sensor-state");
394
395         seq_printf(m, "RTAS (RunTime Abstraction Services) Sensor Information\n");
396         seq_printf(m, "Sensor\t\tValue\t\tCondition\tLocation\n");
397         seq_printf(m, "********************************************************\n");
398
399         if (ppc_rtas_find_all_sensors() != 0) {
400                 seq_printf(m, "\nNo sensors are available\n");
401                 return 0;
402         }
403
404         for (i=0; i<sensors.quant; i++) {
405                 struct individual_sensor *p = &sensors.sensor[i];
406                 char rstr[64];
407                 const char *loc;
408                 int llen, offs;
409
410                 sprintf (rstr, SENSOR_PREFIX"%04d", p->token);
411                 loc = of_get_property(rtas_node, rstr, &llen);
412
413                 /* A sensor may have multiple instances */
414                 for (j = 0, offs = 0; j <= p->quant; j++) {
415                         error = rtas_call(get_sensor_state, 2, 2, &state, 
416                                           p->token, j);
417
418                         ppc_rtas_process_sensor(m, p, state, error, loc);
419                         seq_putc(m, '\n');
420                         if (loc) {
421                                 offs += strlen(loc) + 1;
422                                 loc += strlen(loc) + 1;
423                                 if (offs >= llen)
424                                         loc = NULL;
425                         }
426                 }
427         }
428         return 0;
429 }
430
431 /* ****************************************************************** */
432
433 static int ppc_rtas_find_all_sensors(void)
434 {
435         const unsigned int *utmp;
436         int len, i;
437
438         utmp = of_get_property(rtas_node, "rtas-sensors", &len);
439         if (utmp == NULL) {
440                 printk (KERN_ERR "error: could not get rtas-sensors\n");
441                 return 1;
442         }
443
444         sensors.quant = len / 8;      /* int + int */
445
446         for (i=0; i<sensors.quant; i++) {
447                 sensors.sensor[i].token = *utmp++;
448                 sensors.sensor[i].quant = *utmp++;
449         }
450         return 0;
451 }
452
453 /* ****************************************************************** */
454 /*
455  * Builds a string of what rtas returned
456  */
457 static char *ppc_rtas_process_error(int error)
458 {
459         switch (error) {
460                 case SENSOR_CRITICAL_HIGH:
461                         return "(critical high)";
462                 case SENSOR_WARNING_HIGH:
463                         return "(warning high)";
464                 case SENSOR_NORMAL:
465                         return "(normal)";
466                 case SENSOR_WARNING_LOW:
467                         return "(warning low)";
468                 case SENSOR_CRITICAL_LOW:
469                         return "(critical low)";
470                 case SENSOR_SUCCESS:
471                         return "(read ok)";
472                 case SENSOR_HW_ERROR:
473                         return "(hardware error)";
474                 case SENSOR_BUSY:
475                         return "(busy)";
476                 case SENSOR_NOT_EXIST:
477                         return "(non existent)";
478                 case SENSOR_DR_ENTITY:
479                         return "(dr entity removed)";
480                 default:
481                         return "(UNKNOWN)";
482         }
483 }
484
485 /* ****************************************************************** */
486 /*
487  * Builds a string out of what the sensor said
488  */
489
490 static void ppc_rtas_process_sensor(struct seq_file *m,
491         struct individual_sensor *s, int state, int error, const char *loc)
492 {
493         /* Defined return vales */
494         const char * key_switch[]        = { "Off\t", "Normal\t", "Secure\t", 
495                                                 "Maintenance" };
496         const char * enclosure_switch[]  = { "Closed", "Open" };
497         const char * lid_status[]        = { " ", "Open", "Closed" };
498         const char * power_source[]      = { "AC\t", "Battery", 
499                                                 "AC & Battery" };
500         const char * battery_remaining[] = { "Very Low", "Low", "Mid", "High" };
501         const char * epow_sensor[]       = { 
502                 "EPOW Reset", "Cooling warning", "Power warning",
503                 "System shutdown", "System halt", "EPOW main enclosure",
504                 "EPOW power off" };
505         const char * battery_cyclestate[]  = { "None", "In progress", 
506                                                 "Requested" };
507         const char * battery_charging[]    = { "Charging", "Discharging",
508                                                 "No current flow" };
509         const char * ibm_drconnector[]     = { "Empty", "Present", "Unusable", 
510                                                 "Exchange" };
511
512         int have_strings = 0;
513         int num_states = 0;
514         int temperature = 0;
515         int unknown = 0;
516
517         /* What kind of sensor do we have here? */
518         
519         switch (s->token) {
520                 case KEY_SWITCH:
521                         seq_printf(m, "Key switch:\t");
522                         num_states = sizeof(key_switch) / sizeof(char *);
523                         if (state < num_states) {
524                                 seq_printf(m, "%s\t", key_switch[state]);
525                                 have_strings = 1;
526                         }
527                         break;
528                 case ENCLOSURE_SWITCH:
529                         seq_printf(m, "Enclosure switch:\t");
530                         num_states = sizeof(enclosure_switch) / sizeof(char *);
531                         if (state < num_states) {
532                                 seq_printf(m, "%s\t", 
533                                                 enclosure_switch[state]);
534                                 have_strings = 1;
535                         }
536                         break;
537                 case THERMAL_SENSOR:
538                         seq_printf(m, "Temp. (C/F):\t");
539                         temperature = 1;
540                         break;
541                 case LID_STATUS:
542                         seq_printf(m, "Lid status:\t");
543                         num_states = sizeof(lid_status) / sizeof(char *);
544                         if (state < num_states) {
545                                 seq_printf(m, "%s\t", lid_status[state]);
546                                 have_strings = 1;
547                         }
548                         break;
549                 case POWER_SOURCE:
550                         seq_printf(m, "Power source:\t");
551                         num_states = sizeof(power_source) / sizeof(char *);
552                         if (state < num_states) {
553                                 seq_printf(m, "%s\t", 
554                                                 power_source[state]);
555                                 have_strings = 1;
556                         }
557                         break;
558                 case BATTERY_VOLTAGE:
559                         seq_printf(m, "Battery voltage:\t");
560                         break;
561                 case BATTERY_REMAINING:
562                         seq_printf(m, "Battery remaining:\t");
563                         num_states = sizeof(battery_remaining) / sizeof(char *);
564                         if (state < num_states)
565                         {
566                                 seq_printf(m, "%s\t", 
567                                                 battery_remaining[state]);
568                                 have_strings = 1;
569                         }
570                         break;
571                 case BATTERY_PERCENTAGE:
572                         seq_printf(m, "Battery percentage:\t");
573                         break;
574                 case EPOW_SENSOR:
575                         seq_printf(m, "EPOW Sensor:\t");
576                         num_states = sizeof(epow_sensor) / sizeof(char *);
577                         if (state < num_states) {
578                                 seq_printf(m, "%s\t", epow_sensor[state]);
579                                 have_strings = 1;
580                         }
581                         break;
582                 case BATTERY_CYCLESTATE:
583                         seq_printf(m, "Battery cyclestate:\t");
584                         num_states = sizeof(battery_cyclestate) / 
585                                         sizeof(char *);
586                         if (state < num_states) {
587                                 seq_printf(m, "%s\t", 
588                                                 battery_cyclestate[state]);
589                                 have_strings = 1;
590                         }
591                         break;
592                 case BATTERY_CHARGING:
593                         seq_printf(m, "Battery Charging:\t");
594                         num_states = sizeof(battery_charging) / sizeof(char *);
595                         if (state < num_states) {
596                                 seq_printf(m, "%s\t", 
597                                                 battery_charging[state]);
598                                 have_strings = 1;
599                         }
600                         break;
601                 case IBM_SURVEILLANCE:
602                         seq_printf(m, "Surveillance:\t");
603                         break;
604                 case IBM_FANRPM:
605                         seq_printf(m, "Fan (rpm):\t");
606                         break;
607                 case IBM_VOLTAGE:
608                         seq_printf(m, "Voltage (mv):\t");
609                         break;
610                 case IBM_DRCONNECTOR:
611                         seq_printf(m, "DR connector:\t");
612                         num_states = sizeof(ibm_drconnector) / sizeof(char *);
613                         if (state < num_states) {
614                                 seq_printf(m, "%s\t", 
615                                                 ibm_drconnector[state]);
616                                 have_strings = 1;
617                         }
618                         break;
619                 case IBM_POWERSUPPLY:
620                         seq_printf(m, "Powersupply:\t");
621                         break;
622                 default:
623                         seq_printf(m,  "Unknown sensor (type %d), ignoring it\n",
624                                         s->token);
625                         unknown = 1;
626                         have_strings = 1;
627                         break;
628         }
629         if (have_strings == 0) {
630                 if (temperature) {
631                         seq_printf(m, "%4d /%4d\t", state, cel_to_fahr(state));
632                 } else
633                         seq_printf(m, "%10d\t", state);
634         }
635         if (unknown == 0) {
636                 seq_printf(m, "%s\t", ppc_rtas_process_error(error));
637                 get_location_code(m, s, loc);
638         }
639 }
640
641 /* ****************************************************************** */
642
643 static void check_location(struct seq_file *m, const char *c)
644 {
645         switch (c[0]) {
646                 case LOC_PLANAR:
647                         seq_printf(m, "Planar #%c", c[1]);
648                         break;
649                 case LOC_CPU:
650                         seq_printf(m, "CPU #%c", c[1]);
651                         break;
652                 case LOC_FAN:
653                         seq_printf(m, "Fan #%c", c[1]);
654                         break;
655                 case LOC_RACKMOUNTED:
656                         seq_printf(m, "Rack #%c", c[1]);
657                         break;
658                 case LOC_VOLTAGE:
659                         seq_printf(m, "Voltage #%c", c[1]);
660                         break;
661                 case LOC_LCD:
662                         seq_printf(m, "LCD #%c", c[1]);
663                         break;
664                 case '.':
665                         seq_printf(m, "- %c", c[1]);
666                         break;
667                 default:
668                         seq_printf(m, "Unknown location");
669                         break;
670         }
671 }
672
673
674 /* ****************************************************************** */
675 /* 
676  * Format: 
677  * ${LETTER}${NUMBER}[[-/]${LETTER}${NUMBER} [ ... ] ]
678  * the '.' may be an abbreviation
679  */
680 static void check_location_string(struct seq_file *m, const char *c)
681 {
682         while (*c) {
683                 if (isalpha(*c) || *c == '.')
684                         check_location(m, c);
685                 else if (*c == '/' || *c == '-')
686                         seq_printf(m, " at ");
687                 c++;
688         }
689 }
690
691
692 /* ****************************************************************** */
693
694 static void get_location_code(struct seq_file *m, struct individual_sensor *s,
695                 const char *loc)
696 {
697         if (!loc || !*loc) {
698                 seq_printf(m, "---");/* does not have a location */
699         } else {
700                 check_location_string(m, loc);
701         }
702         seq_putc(m, ' ');
703 }
704 /* ****************************************************************** */
705 /* INDICATORS - Tone Frequency                                        */
706 /* ****************************************************************** */
707 static ssize_t ppc_rtas_tone_freq_write(struct file *file,
708                 const char __user *buf, size_t count, loff_t *ppos)
709 {
710         u64 freq;
711         int error = parse_number(buf, count, &freq);
712         if (error)
713                 return error;
714
715         rtas_tone_frequency = freq; /* save it for later */
716         error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL,
717                         TONE_FREQUENCY, 0, freq);
718         if (error)
719                 printk(KERN_WARNING "error: setting tone frequency returned: %s\n", 
720                                 ppc_rtas_process_error(error));
721         return count;
722 }
723 /* ****************************************************************** */
724 static int ppc_rtas_tone_freq_show(struct seq_file *m, void *v)
725 {
726         seq_printf(m, "%lu\n", rtas_tone_frequency);
727         return 0;
728 }
729 /* ****************************************************************** */
730 /* INDICATORS - Tone Volume                                           */
731 /* ****************************************************************** */
732 static ssize_t ppc_rtas_tone_volume_write(struct file *file,
733                 const char __user *buf, size_t count, loff_t *ppos)
734 {
735         u64 volume;
736         int error = parse_number(buf, count, &volume);
737         if (error)
738                 return error;
739
740         if (volume > 100)
741                 volume = 100;
742         
743         rtas_tone_volume = volume; /* save it for later */
744         error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL,
745                         TONE_VOLUME, 0, volume);
746         if (error)
747                 printk(KERN_WARNING "error: setting tone volume returned: %s\n", 
748                                 ppc_rtas_process_error(error));
749         return count;
750 }
751 /* ****************************************************************** */
752 static int ppc_rtas_tone_volume_show(struct seq_file *m, void *v)
753 {
754         seq_printf(m, "%lu\n", rtas_tone_volume);
755         return 0;
756 }
757
758 /**
759  * ppc_rtas_rmo_buf_show() - Describe RTAS-addressable region for user space.
760  *
761  * Base + size description of a range of RTAS-addressable memory set
762  * aside for user space to use as work area(s) for certain RTAS
763  * functions. User space accesses this region via /dev/mem. Apart from
764  * security policies, the kernel does not arbitrate or serialize
765  * access to this region, and user space must ensure that concurrent
766  * users do not interfere with each other.
767  */
768 static int ppc_rtas_rmo_buf_show(struct seq_file *m, void *v)
769 {
770         seq_printf(m, "%016lx %x\n", rtas_rmo_buf, RTAS_USER_REGION_SIZE);
771         return 0;
772 }