1
2
3
4
5
6
7
8
9
10
11
12
13
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
24#include <asm/uaccess.h>
25#include <asm/bitops.h>
26#include <asm/processor.h>
27#include <asm/io.h>
28#include <asm/prom.h>
29#include <asm/rtas.h>
30#include <asm/machdep.h>
31#include <asm/time.h>
32
33
34#define KEY_SWITCH 0x0001
35#define ENCLOSURE_SWITCH 0x0002
36#define THERMAL_SENSOR 0x0003
37#define LID_STATUS 0x0004
38#define POWER_SOURCE 0x0005
39#define BATTERY_VOLTAGE 0x0006
40#define BATTERY_REMAINING 0x0007
41#define BATTERY_PERCENTAGE 0x0008
42#define EPOW_SENSOR 0x0009
43#define BATTERY_CYCLESTATE 0x000a
44#define BATTERY_CHARGING 0x000b
45
46
47#define IBM_SURVEILLANCE 0x2328
48#define IBM_FANRPM 0x2329
49#define IBM_VOLTAGE 0x232a
50#define IBM_DRCONNECTOR 0x232b
51#define IBM_POWERSUPPLY 0x232c
52#define IBM_INTQUEUE 0x232d
53
54
55#define SENSOR_CRITICAL_HIGH 13
56#define SENSOR_WARNING_HIGH 12
57#define SENSOR_NORMAL 11
58#define SENSOR_WARNING_LOW 10
59#define SENSOR_CRITICAL_LOW 9
60#define SENSOR_SUCCESS 0
61#define SENSOR_HW_ERROR -1
62#define SENSOR_BUSY -2
63#define SENSOR_NOT_EXIST -3
64#define SENSOR_DR_ENTITY -9000
65
66
67#define LOC_SCSI_DEV_ADDR 'A'
68#define LOC_SCSI_DEV_LOC 'B'
69#define LOC_CPU 'C'
70#define LOC_DISKETTE 'D'
71#define LOC_ETHERNET 'E'
72#define LOC_FAN 'F'
73#define LOC_GRAPHICS 'G'
74
75#define LOC_IO_ADAPTER 'I'
76
77#define LOC_KEYBOARD 'K'
78#define LOC_LCD 'L'
79#define LOC_MEMORY 'M'
80#define LOC_NV_MEMORY 'N'
81#define LOC_MOUSE 'O'
82#define LOC_PLANAR 'P'
83#define LOC_OTHER_IO 'Q'
84#define LOC_PARALLEL 'R'
85#define LOC_SERIAL 'S'
86#define LOC_DEAD_RING 'T'
87#define LOC_RACKMOUNTED 'U'
88#define LOC_VOLTAGE 'V'
89#define LOC_SWITCH_ADAPTER 'W'
90#define LOC_OTHER 'X'
91#define LOC_FIRMWARE 'Y'
92#define LOC_SCSI 'Z'
93
94
95#define TONE_FREQUENCY 0x0001
96#define TONE_VOLUME 0x0002
97#define SYSTEM_POWER_STATE 0x0003
98#define WARNING_LIGHT 0x0004
99#define DISK_ACTIVITY_LIGHT 0x0005
100#define HEX_DISPLAY_UNIT 0x0006
101#define BATTERY_WARNING_TIME 0x0007
102#define CONDITION_CYCLE_REQUEST 0x0008
103#define SURVEILLANCE_INDICATOR 0x2328
104#define DR_ACTION 0x2329
105#define DR_INDICATOR 0x232a
106
107#define GLOBAL_INTERRUPT_QUEUE 0x232d
108
109
110
111#define MAX_SENSORS 17
112#define MAX_LINELENGTH 256
113#define SENSOR_PREFIX "ibm,sensor-"
114#define cel_to_fahr(x) ((x*9/5)+32)
115
116
117
118static struct rtas_sensors sensors;
119static struct device_node *rtas_node = NULL;
120static unsigned long power_on_time = 0;
121static char progress_led[MAX_LINELENGTH];
122
123static unsigned long rtas_tone_frequency = 1000;
124static unsigned long rtas_tone_volume = 0;
125static unsigned int open_token = 0;
126
127static int set_time_for_power_on = RTAS_UNKNOWN_SERVICE;
128static int set_time_of_day = RTAS_UNKNOWN_SERVICE;
129static int get_sensor_state = RTAS_UNKNOWN_SERVICE;
130static int set_indicator = RTAS_UNKNOWN_SERVICE;
131
132extern struct proc_dir_entry *proc_ppc64_root;
133extern struct proc_dir_entry *rtas_proc_dir;
134extern spinlock_t proc_ppc64_lock;
135
136
137struct individual_sensor {
138 unsigned int token;
139 unsigned int quant;
140};
141
142struct rtas_sensors {
143 struct individual_sensor sensor[MAX_SENSORS];
144 unsigned int quant;
145};
146
147
148
149static int ppc_rtas_sensor_read(char * buf, char ** start, off_t off,
150 int count, int *eof, void *data);
151static ssize_t ppc_rtas_clock_read(struct file * file, char * buf,
152 size_t count, loff_t *ppos);
153static ssize_t ppc_rtas_clock_write(struct file * file, const char * buf,
154 size_t count, loff_t *ppos);
155static ssize_t ppc_rtas_progress_read(struct file * file, char * buf,
156 size_t count, loff_t *ppos);
157static ssize_t ppc_rtas_progress_write(struct file * file, const char * buf,
158 size_t count, loff_t *ppos);
159static ssize_t ppc_rtas_poweron_read(struct file * file, char * buf,
160 size_t count, loff_t *ppos);
161static ssize_t ppc_rtas_poweron_write(struct file * file, const char * buf,
162 size_t count, loff_t *ppos);
163
164static ssize_t ppc_rtas_tone_freq_write(struct file * file, const char * buf,
165 size_t count, loff_t *ppos);
166static ssize_t ppc_rtas_tone_freq_read(struct file * file, char * buf,
167 size_t count, loff_t *ppos);
168static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf,
169 size_t count, loff_t *ppos);
170static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf,
171 size_t count, loff_t *ppos);
172static int ppc_rtas_errinjct_open(struct inode *inode, struct file *file);
173static int ppc_rtas_errinjct_release(struct inode *inode, struct file *file);
174static ssize_t ppc_rtas_errinjct_write(struct file * file, const char * buf,
175 size_t count, loff_t *ppos);
176static ssize_t ppc_rtas_errinjct_read(struct file *file, char *buf,
177 size_t count, loff_t *ppos);
178
179struct file_operations ppc_rtas_poweron_operations = {
180 .read = ppc_rtas_poweron_read,
181 .write = ppc_rtas_poweron_write
182};
183struct file_operations ppc_rtas_progress_operations = {
184 .read = ppc_rtas_progress_read,
185 .write = ppc_rtas_progress_write
186};
187
188struct file_operations ppc_rtas_clock_operations = {
189 .read = ppc_rtas_clock_read,
190 .write = ppc_rtas_clock_write
191};
192
193struct file_operations ppc_rtas_tone_freq_operations = {
194 .read = ppc_rtas_tone_freq_read,
195 .write = ppc_rtas_tone_freq_write
196};
197struct file_operations ppc_rtas_tone_volume_operations = {
198 .read = ppc_rtas_tone_volume_read,
199 .write = ppc_rtas_tone_volume_write
200};
201
202struct file_operations ppc_rtas_errinjct_operations = {
203 .open = ppc_rtas_errinjct_open,
204 .read = ppc_rtas_errinjct_read,
205 .write = ppc_rtas_errinjct_write,
206 .release = ppc_rtas_errinjct_release
207};
208
209int ppc_rtas_find_all_sensors (void);
210int ppc_rtas_process_sensor(struct individual_sensor s, int state,
211 int error, char * buf);
212char * ppc_rtas_process_error(int error);
213int get_location_code(struct individual_sensor s, char * buf);
214int check_location_string (char *c, char * buf);
215int check_location (char *c, int idx, char * buf);
216
217
218
219
220void proc_rtas_init(void)
221{
222 struct proc_dir_entry *entry;
223 int display_character;
224 int errinjct_token;
225
226 rtas_node = find_devices("rtas");
227 if ((rtas_node == NULL) || (systemcfg->platform == PLATFORM_ISERIES_LPAR)) {
228 return;
229 }
230
231 spin_lock(&proc_ppc64_lock);
232 if (proc_ppc64_root == NULL) {
233 proc_ppc64_root = proc_mkdir("ppc64", 0);
234 if (!proc_ppc64_root) {
235 spin_unlock(&proc_ppc64_lock);
236 return;
237 }
238 }
239 spin_unlock(&proc_ppc64_lock);
240
241 if (rtas_proc_dir == NULL) {
242 rtas_proc_dir = proc_mkdir("rtas", proc_ppc64_root);
243 }
244
245 if (rtas_proc_dir == NULL) {
246 printk(KERN_ERR "Failed to create /proc/ppc64/rtas in rtas_init\n");
247 return;
248 }
249
250
251
252
253
254
255 set_time_of_day = rtas_token("set-time-of-day");
256 if (set_time_of_day != RTAS_UNKNOWN_SERVICE) {
257 entry=create_proc_entry("clock",S_IRUGO|S_IWUSR,rtas_proc_dir);
258 if (entry) entry->proc_fops = &ppc_rtas_clock_operations;
259 }
260
261 set_time_for_power_on = rtas_token("set-time-for-power-on");
262 if (set_time_for_power_on != RTAS_UNKNOWN_SERVICE) {
263 entry=create_proc_entry("poweron",S_IWUSR|S_IRUGO,rtas_proc_dir);
264 if (entry) entry->proc_fops = &ppc_rtas_poweron_operations;
265 }
266
267 get_sensor_state = rtas_token("get-sensor-state");
268 if (get_sensor_state != RTAS_UNKNOWN_SERVICE) {
269 create_proc_read_entry("sensors", S_IRUGO, rtas_proc_dir,
270 ppc_rtas_sensor_read, NULL);
271 }
272
273 set_indicator = rtas_token("set-indicator");
274 if (set_indicator != RTAS_UNKNOWN_SERVICE) {
275 entry=create_proc_entry("frequency",S_IWUSR|S_IRUGO,rtas_proc_dir);
276 if (entry) entry->proc_fops = &ppc_rtas_tone_freq_operations;
277
278 entry=create_proc_entry("volume",S_IWUSR|S_IRUGO,rtas_proc_dir);
279 if (entry) entry->proc_fops = &ppc_rtas_tone_volume_operations;
280 }
281
282 display_character = rtas_token("display-character");
283 if ((display_character != RTAS_UNKNOWN_SERVICE) ||
284 (set_indicator != RTAS_UNKNOWN_SERVICE)) {
285 entry=create_proc_entry("progress",S_IRUGO|S_IWUSR,rtas_proc_dir);
286 if (entry) entry->proc_fops = &ppc_rtas_progress_operations;
287 }
288
289#ifdef CONFIG_RTAS_ERRINJCT
290 errinjct_token = rtas_token("ibm,errinjct");
291 if (errinjct_token != RTAS_UNKNOWN_SERVICE) {
292 entry=create_proc_entry("errinjct",S_IWUSR|S_IRUGO,rtas_proc_dir);
293 if (entry) entry->proc_fops = &ppc_rtas_errinjct_operations;
294 }
295#endif
296
297}
298
299
300
301
302static ssize_t ppc_rtas_poweron_write(struct file * file, const char * buf,
303 size_t count, loff_t *ppos)
304{
305 char stkbuf[40];
306 struct rtc_time tm;
307 unsigned long nowtime;
308 char *dest;
309 int error;
310
311 if (39 < count)
312 count = 39;
313 if (copy_from_user(stkbuf, buf, count))
314 return -EFAULT;
315
316 stkbuf[count] = 0;
317 nowtime = simple_strtoul(stkbuf, &dest, 10);
318 if (*dest != '\0' && *dest != '\n') {
319 printk("ppc_rtas_poweron_write: Invalid time\n");
320 return count;
321 }
322 power_on_time = nowtime;
323
324 to_tm(nowtime, &tm);
325
326 error = rtas_call(set_time_for_power_on, 7, 1, NULL,
327 tm.tm_year, tm.tm_mon, tm.tm_mday,
328 tm.tm_hour, tm.tm_min, tm.tm_sec, 0 );
329 if (error != 0)
330 printk(KERN_WARNING "error: setting poweron time returned: %s\n",
331 ppc_rtas_process_error(error));
332 return count;
333}
334
335static ssize_t ppc_rtas_poweron_read(struct file * file, char * buf,
336 size_t count, loff_t *ppos)
337{
338 char stkbuf[40];
339 int n;
340 loff_t pos = *ppos;
341
342 if (power_on_time == 0)
343 n = snprintf(stkbuf, 40, "Power on time not set\n");
344 else
345 n = snprintf(stkbuf, 40, "%lu\n", power_on_time);
346
347 int sn = strlen(stkbuf) +1;
348 if (pos != (unsigned)pos || pos >= sn)
349 return 0;
350 if (n > sn - pos)
351 n = sn - pos;
352 if (n > count)
353 n = count;
354 if (copy_to_user(buf, stkbuf + pos, n))
355 return -EFAULT;
356 *ppos = pos + n;
357 return n;
358}
359
360
361
362
363static ssize_t ppc_rtas_progress_write(struct file * file, const char * buf,
364 size_t count, loff_t *ppos)
365{
366 unsigned long hex;
367
368 if (count >= MAX_LINELENGTH)
369 count = MAX_LINELENGTH -1;
370 if (copy_from_user(progress_led, buf, count))
371 return -EFAULT;
372
373 progress_led[count] = 0;
374
375
376 hex = simple_strtoul(progress_led, NULL, 10);
377
378 ppc_md.progress((char *)progress_led, hex);
379 return count;
380
381
382}
383
384static ssize_t ppc_rtas_progress_read(struct file * file, char * buf,
385 size_t count, loff_t *ppos)
386{
387 int n = 0, sn;
388 loff_t pos = *ppos;
389
390 if (progress_led == NULL)
391 return 0;
392
393 char * tmpbuf = kmalloc(MAX_LINELENGTH, GFP_KERNEL);
394 if (!tmpbuf) {
395 printk(KERN_ERR "error: kmalloc failed\n");
396 return -ENOMEM;
397 }
398 n = sprintf (tmpbuf, "%s\n", progress_led);
399
400 sn = strlen (tmpbuf) +1;
401 if (pos != (unsigned)pos || pos >= sn) {
402 kfree(tmpbuf);
403 return 0;
404 }
405 if (n > sn - pos)
406 n = sn - pos;
407 if (n > count)
408 n = count;
409 if (copy_to_user(buf, tmpbuf + pos, n)) {
410 kfree(tmpbuf);
411 return -EFAULT;
412 }
413 kfree(tmpbuf);
414 *ppos = pos + n;
415 return n;
416}
417
418
419
420
421static ssize_t ppc_rtas_clock_write(struct file * file, const char * buf,
422 size_t count, loff_t *ppos)
423{
424 char stkbuf[40];
425 struct rtc_time tm;
426 unsigned long nowtime;
427 char *dest;
428 int error;
429
430 if (39 < count)
431 count = 39;
432 if (copy_from_user(stkbuf, buf, count))
433 return -EFAULT;
434
435 stkbuf[count] = 0;
436 nowtime = simple_strtoul(stkbuf, &dest, 10);
437 if (*dest != '\0' && *dest != '\n') {
438 printk("ppc_rtas_clock_write: Invalid time\n");
439 return count;
440 }
441
442 to_tm(nowtime, &tm);
443 error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL,
444 tm.tm_year, tm.tm_mon, tm.tm_mday,
445 tm.tm_hour, tm.tm_min, tm.tm_sec, 0);
446 if (error != 0)
447 printk(KERN_WARNING "error: setting the clock returned: %s\n",
448 ppc_rtas_process_error(error));
449 return count;
450}
451
452static ssize_t ppc_rtas_clock_read(struct file * file, char * buf,
453 size_t count, loff_t *ppos)
454{
455 unsigned int year, mon, day, hour, min, sec;
456 unsigned long *ret = kmalloc(4*8, GFP_KERNEL);
457 int n, error;
458 loff_t pos = *ppos;
459
460 error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);
461
462 year = ret[0]; mon = ret[1]; day = ret[2];
463 hour = ret[3]; min = ret[4]; sec = ret[5];
464
465 char stkbuf[40];
466
467 if (error != 0){
468 printk(KERN_WARNING "error: reading the clock returned: %s\n",
469 ppc_rtas_process_error(error));
470 n = snprintf(stkbuf, 40, "0");
471 } else {
472 n = snprintf(stkbuf, 40, "%lu\n", mktime(year, mon, day, hour, min, sec));
473 }
474 kfree(ret);
475
476 int sn = strlen(stkbuf) +1;
477 if (pos != (unsigned)pos || pos >= sn)
478 return 0;
479 if (n > sn - pos)
480 n = sn - pos;
481 if (n > count)
482 n = count;
483 if (copy_to_user(buf, stkbuf + pos, n))
484 return -EFAULT;
485
486 *ppos = pos + n;
487 return n;
488}
489
490
491
492
493static int ppc_rtas_sensor_read(char * buf, char ** start, off_t off,
494 int count, int *eof, void *data)
495{
496 int i,j,n;
497 unsigned long ret;
498 int state, error;
499 char *buffer;
500
501 if (count < 0)
502 return -EINVAL;
503
504
505 buffer = kmalloc(MAX_LINELENGTH*MAX_SENSORS, GFP_KERNEL);
506
507 if (!buffer)
508 return -ENOMEM;
509
510 memset(buffer, 0, MAX_LINELENGTH*MAX_SENSORS);
511
512 n = sprintf ( buffer , "RTAS (RunTime Abstraction Services) Sensor Information\n");
513 n += sprintf ( buffer+n, "%-17s\t%-15s\t%-15s\tLocation\n", "Sensor", "Value", "Condition");
514 n += sprintf ( buffer+n, "***************************************************************************\n");
515
516 if (ppc_rtas_find_all_sensors() != 0) {
517 n += sprintf ( buffer+n, "\nNo sensors are available\n");
518 goto return_string;
519 }
520
521 for (i=0; i<sensors.quant; i++) {
522 j = sensors.sensor[i].quant;
523
524 while (j >= 0) {
525
526 error = rtas_call(get_sensor_state, 2, 2, &ret,
527 sensors.sensor[i].token,
528 sensors.sensor[i].quant - j);
529
530 state = (int) ret;
531 n += ppc_rtas_process_sensor(sensors.sensor[i], state,
532 error, buffer+n );
533 n += sprintf (buffer+n, "\n");
534 j--;
535 }
536 }
537
538return_string:
539 if (off >= strlen(buffer)) {
540 *eof = 1;
541 kfree(buffer);
542 return 0;
543 }
544 if (n > strlen(buffer) - off)
545 n = strlen(buffer) - off;
546 if (n > count)
547 n = count;
548 else
549 *eof = 1;
550
551 memcpy(buf, buffer + off, n);
552 *start = buf;
553 kfree(buffer);
554 return n;
555}
556
557
558
559int ppc_rtas_find_all_sensors (void)
560{
561 unsigned int *utmp;
562 int len, i;
563
564 utmp = (unsigned int *) get_property(rtas_node, "rtas-sensors", &len);
565 if (utmp == NULL) {
566 printk (KERN_ERR "error: could not get rtas-sensors\n");
567 return 1;
568 }
569
570 sensors.quant = len / 8;
571
572 for (i=0; i<sensors.quant; i++) {
573 sensors.sensor[i].token = *utmp++;
574 sensors.sensor[i].quant = *utmp++;
575 }
576 return 0;
577}
578
579
580
581
582
583char * ppc_rtas_process_error(int error)
584{
585 switch (error) {
586 case SENSOR_CRITICAL_HIGH:
587 return "(critical high)";
588 case SENSOR_WARNING_HIGH:
589 return "(warning high)";
590 case SENSOR_NORMAL:
591 return "(normal)";
592 case SENSOR_WARNING_LOW:
593 return "(warning low)";
594 case SENSOR_CRITICAL_LOW:
595 return "(critical low)";
596 case SENSOR_SUCCESS:
597 return "(read ok)";
598 case SENSOR_HW_ERROR:
599 return "(hardware error)";
600 case SENSOR_BUSY:
601 return "(busy)";
602 case SENSOR_NOT_EXIST:
603 return "(non existant)";
604 case SENSOR_DR_ENTITY:
605 return "(dr entity removed)";
606 default:
607 return "(UNKNOWN)";
608 }
609}
610
611
612
613
614
615
616int ppc_rtas_process_sensor(struct individual_sensor s, int state,
617 int error, char * buf)
618{
619
620 const char * key_switch[] = { "Off", "Normal", "Secure", "Maintenance" };
621 const char * enclosure_switch[] = { "Closed", "Open" };
622 const char * lid_status[] = { " ", "Open", "Closed" };
623 const char * power_source[] = { "AC", "Battery", "AC & Battery" };
624 const char * battery_remaining[] = { "Very Low", "Low", "Mid", "High" };
625 const char * epow_sensor[] = {
626 "EPOW Reset", "Cooling warning", "Power warning",
627 "System shutdown", "System halt", "EPOW main enclosure",
628 "EPOW power off" };
629 const char * battery_cyclestate[] = { "None", "In progress", "Requested" };
630 const char * battery_charging[] = { "Charging", "Discharching", "No current flow" };
631 const char * ibm_drconnector[] = { "Empty", "Present" };
632 const char * ibm_intqueue[] = { "Disabled", "Enabled" };
633
634 int temperature = 0;
635 int unknown = 0;
636 int n = 0;
637 char *label_string = NULL;
638 const char **value_arr = NULL;
639 int value_arrsize = 0;
640
641
642
643 switch (s.token) {
644 case KEY_SWITCH:
645 label_string = "Key switch:";
646 value_arrsize = sizeof(key_switch)/sizeof(char *);
647 value_arr = key_switch;
648 break;
649 case ENCLOSURE_SWITCH:
650 label_string = "Enclosure switch:";
651 value_arrsize = sizeof(enclosure_switch)/sizeof(char *);
652 value_arr = enclosure_switch;
653 break;
654 case THERMAL_SENSOR:
655 label_string = "Temp. (°C/°F):";
656 temperature = 1;
657 break;
658 case LID_STATUS:
659 label_string = "Lid status:";
660 value_arrsize = sizeof(lid_status)/sizeof(char *);
661 value_arr = lid_status;
662 break;
663 case POWER_SOURCE:
664 label_string = "Power source:";
665 value_arrsize = sizeof(power_source)/sizeof(char *);
666 value_arr = power_source;
667 break;
668 case BATTERY_VOLTAGE:
669 label_string = "Battery voltage:";
670 break;
671 case BATTERY_REMAINING:
672 label_string = "Battery remaining:";
673 value_arrsize = sizeof(battery_remaining)/sizeof(char *);
674 value_arr = battery_remaining;
675 break;
676 case BATTERY_PERCENTAGE:
677 label_string = "Battery percentage:";
678 break;
679 case EPOW_SENSOR:
680 label_string = "EPOW Sensor:";
681 value_arrsize = sizeof(epow_sensor)/sizeof(char *);
682 value_arr = epow_sensor;
683 break;
684 case BATTERY_CYCLESTATE:
685 label_string = "Battery cyclestate:";
686 value_arrsize = sizeof(battery_cyclestate)/sizeof(char *);
687 value_arr = battery_cyclestate;
688 break;
689 case BATTERY_CHARGING:
690 label_string = "Battery Charging:";
691 value_arrsize = sizeof(battery_charging)/sizeof(char *);
692 value_arr = battery_charging;
693 break;
694 case IBM_SURVEILLANCE:
695 label_string = "Surveillance:";
696 break;
697 case IBM_FANRPM:
698 label_string = "Fan (rpm):";
699 break;
700 case IBM_VOLTAGE:
701 label_string = "Voltage (mv):";
702 break;
703 case IBM_DRCONNECTOR:
704 label_string = "DR connector:";
705 value_arrsize = sizeof(ibm_drconnector)/sizeof(char *);
706 value_arr = ibm_drconnector;
707 break;
708 case IBM_POWERSUPPLY:
709 label_string = "Powersupply:";
710 break;
711 case IBM_INTQUEUE:
712 label_string = "Interrupt queue:";
713 value_arrsize = sizeof(ibm_intqueue)/sizeof(char *);
714 value_arr = ibm_intqueue;
715 break;
716 default:
717 n += sprintf(buf+n, "Unkown sensor (type %d), ignoring it\n",
718 s.token);
719 unknown = 1;
720 break;
721 }
722
723 if (label_string)
724 n += sprintf(buf+n, "%-17s\t", label_string);
725
726 if (value_arr && state >= 0 && state < value_arrsize) {
727 n += sprintf(buf+n, "%-15s\t", value_arr[state]);
728 } else {
729 if (temperature) {
730 n += sprintf(buf+n, "%2d / %2d \t", state, cel_to_fahr(state));
731 } else
732 n += sprintf(buf+n, "%-10d\t", state);
733 }
734 if (unknown == 0) {
735 n += sprintf ( buf+n, "%-15s\t", ppc_rtas_process_error(error));
736 n += get_location_code(s, buf+n);
737 }
738 return n;
739}
740
741
742
743int check_location (char *c, int idx, char * buf)
744{
745 int n = 0;
746
747 switch (*(c+idx)) {
748 case LOC_PLANAR:
749 n += sprintf ( buf, "Planar #%c", *(c+idx+1));
750 break;
751 case LOC_CPU:
752 n += sprintf ( buf, "CPU #%c", *(c+idx+1));
753 break;
754 case LOC_FAN:
755 n += sprintf ( buf, "Fan #%c", *(c+idx+1));
756 break;
757 case LOC_RACKMOUNTED:
758 n += sprintf ( buf, "Rack #%c", *(c+idx+1));
759 break;
760 case LOC_VOLTAGE:
761 n += sprintf ( buf, "Voltage #%c", *(c+idx+1));
762 break;
763 case LOC_LCD:
764 n += sprintf ( buf, "LCD #%c", *(c+idx+1));
765 break;
766 case '.':
767 n += sprintf ( buf, "- %c", *(c+idx+1));
768 default:
769 n += sprintf ( buf, "Unknown location");
770 break;
771 }
772 return n;
773}
774
775
776
777
778
779
780
781
782int check_location_string (char *c, char *buf)
783{
784 int n=0,i=0;
785
786 while (c[i]) {
787 if (isalpha(c[i]) || c[i] == '.') {
788 n += check_location(c, i, buf+n);
789 }
790 else if (c[i] == '/' || c[i] == '-')
791 n += sprintf(buf+n, " at ");
792 i++;
793 }
794 return n;
795}
796
797
798
799
800int get_location_code(struct individual_sensor s, char * buffer)
801{
802 char rstr[512], tmp[10], tmp2[10];
803 int n=0, i=0, llen, len;
804
805 char *ret;
806
807 static int pos = 0;
808
809
810
811 n = sprintf(tmp, "%d", s.token);
812 len = strlen(tmp);
813 while (strlen(tmp) < 4)
814 n += sprintf (tmp+n, "0");
815
816
817 while (tmp[i]) {
818 if (i<len)
819 tmp2[4-len+i] = tmp[i];
820 else
821 tmp2[3-i] = tmp[i];
822 i++;
823 }
824 tmp2[4] = '\0';
825
826 sprintf (rstr, SENSOR_PREFIX"%s", tmp2);
827
828 ret = (char *) get_property(rtas_node, rstr, &llen);
829
830 n=0;
831 if (ret == NULL || ret[0] == '\0') {
832 n += sprintf ( buffer+n, "--- ");
833 } else {
834 char t[50];
835 ret += pos;
836
837 n += check_location_string(ret, buffer + n);
838 n += sprintf ( buffer+n, " ");
839
840 snprintf( t, 50, "%s ", ret);
841
842 pos += strlen(t);
843 if (pos >= llen) pos=0;
844 }
845 return n;
846}
847
848
849
850static ssize_t ppc_rtas_tone_freq_write(struct file * file, const char * buf,
851 size_t count, loff_t *ppos)
852{
853 char stkbuf[40];
854 unsigned long freq;
855 char *dest;
856 int error;
857
858 if (39 < count)
859 count = 39;
860 if (copy_from_user(stkbuf, buf, count))
861 return -EFAULT;
862
863 stkbuf[count] = 0;
864 freq = simple_strtoul(stkbuf, &dest, 10);
865 if (*dest != '\0' && *dest != '\n') {
866 printk("ppc_rtas_tone_freq_write: Invalid tone freqency\n");
867 return count;
868 }
869 if (freq < 0) freq = 0;
870 rtas_tone_frequency = freq;
871 error = rtas_call(set_indicator, 3, 1, NULL,
872 TONE_FREQUENCY, 0, freq);
873 if (error != 0)
874 printk(KERN_WARNING "error: setting tone frequency returned: %s\n",
875 ppc_rtas_process_error(error));
876 return count;
877}
878
879static ssize_t ppc_rtas_tone_freq_read(struct file * file, char * buf,
880 size_t count, loff_t *ppos)
881{
882 int n, sn;
883 char stkbuf[40];
884 loff_t pos = *ppos;
885
886 n = snprintf(stkbuf, 40, "%lu\n", rtas_tone_frequency);
887
888 sn = strlen(stkbuf) +1;
889 if (pos != (unsigned)pos || pos >= sn)
890 return 0;
891 if (n > sn - pos)
892 n = sn - pos;
893 if (n > count)
894 n = count;
895 if (copy_to_user(buf, stkbuf + pos, n))
896 return -EFAULT;
897
898 *ppos = pos + n;
899 return n;
900}
901
902
903
904static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf,
905 size_t count, loff_t *ppos)
906{
907 char stkbuf[40];
908 unsigned long volume;
909 char *dest;
910 int error;
911
912 if (39 < count)
913 count = 39;
914 if (copy_from_user(stkbuf, buf, count))
915 return -EFAULT;
916
917 stkbuf[count] = 0;
918 volume = simple_strtoul(stkbuf, &dest, 10);
919 if (*dest != '\0' && *dest != '\n') {
920 printk("ppc_rtas_tone_volume_write: Invalid tone volume\n");
921 return count;
922 }
923 if (volume < 0) volume = 0;
924 if (volume > 100) volume = 100;
925
926 rtas_tone_volume = volume;
927 error = rtas_call(set_indicator, 3, 1, NULL,
928 TONE_VOLUME, 0, volume);
929 if (error != 0)
930 printk(KERN_WARNING "error: setting tone volume returned: %s\n",
931 ppc_rtas_process_error(error));
932 return count;
933}
934
935static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf,
936 size_t count, loff_t *ppos)
937{
938 int n, sn;
939 char stkbuf[40];
940 loff_t pos = *ppos;
941
942 n = snprintf(stkbuf, 40, "%lu\n", rtas_tone_volume);
943 sn = strlen(stkbuf) +1;
944 if (pos != (unsigned)pos || pos >= sn)
945 return 0;
946 if (n > sn - pos)
947 n = sn - pos;
948 if (n > count)
949 n = count;
950 if (copy_to_user(buf, stkbuf + pos, n))
951 return -EFAULT;
952
953 *ppos = pos + n;
954 return n;
955}
956
957
958
959
960static int ppc_rtas_errinjct_open(struct inode *inode, struct file *file)
961{
962 int rc;
963
964
965
966
967 if (open_token) {
968 return -EAGAIN;
969 }
970 rc = rtas_errinjct_open();
971 if (rc < 0) {
972 return -EIO;
973 }
974 open_token = rc;
975
976 return 0;
977}
978
979static ssize_t ppc_rtas_errinjct_write(struct file * file, const char * buf,
980 size_t count, loff_t *ppos)
981{
982 char * tmpbuf;
983 char * ei_token;
984 char * workspace = NULL;
985 size_t max_len;
986 int token_len;
987 int rc;
988
989
990 if (count < ERRINJCT_TOKEN_LEN) {
991 max_len = count;
992 } else {
993 max_len = ERRINJCT_TOKEN_LEN;
994 }
995
996 tmpbuf = (char *) kmalloc(max_len, GFP_KERNEL);
997 if (!tmpbuf) {
998 printk(KERN_WARNING "error: kmalloc failed\n");
999 return -ENOMEM;
1000 }
1001 if (copy_from_user (tmpbuf, buf, max_len)) {
1002 kfree(tmpbuf);
1003 return -EFAULT;
1004 }
1005 token_len = strnlen(tmpbuf, max_len);
1006 token_len++;
1007
1008 ei_token = (char *)kmalloc(token_len, GFP_KERNEL);
1009 if (!ei_token) {
1010 printk(KERN_WARNING "error: kmalloc failed\n");
1011 kfree(tmpbuf);
1012 return -ENOMEM;
1013 }
1014
1015 strncpy(ei_token, tmpbuf, token_len);
1016
1017 if (count > token_len + WORKSPACE_SIZE) {
1018 count = token_len + WORKSPACE_SIZE;
1019 }
1020
1021 buf += token_len;
1022
1023
1024 if (count > token_len) {
1025
1026 if ((count - token_len) > WORKSPACE_SIZE) {
1027 max_len = WORKSPACE_SIZE;
1028 } else {
1029 max_len = count - token_len;
1030 }
1031
1032 workspace = (char *)kmalloc(max_len, GFP_KERNEL);
1033 if (!workspace) {
1034 printk(KERN_WARNING "error: failed kmalloc\n");
1035 kfree(tmpbuf);
1036 kfree(ei_token);
1037 return -ENOMEM;
1038 }
1039
1040 memcpy(workspace, tmpbuf, max_len);
1041 }
1042
1043 rc = rtas_errinjct(open_token, ei_token, workspace);
1044
1045 if (count > token_len) {
1046 kfree(workspace);
1047 }
1048 kfree(ei_token);
1049 kfree(tmpbuf);
1050
1051 return rc < 0 ? rc : count;
1052}
1053
1054static int ppc_rtas_errinjct_release(struct inode *inode, struct file *file)
1055{
1056 int rc;
1057
1058 rc = rtas_errinjct_close(open_token);
1059 if (rc) {
1060 return rc;
1061 }
1062 open_token = 0;
1063 return 0;
1064}
1065
1066static ssize_t ppc_rtas_errinjct_read(struct file *file, char *buf,
1067 size_t count, loff_t *ppos)
1068{
1069 char * buffer;
1070 int i, sn;
1071 int n = 0;
1072 loff_t pos = *ppos;
1073
1074 int m = MAX_ERRINJCT_TOKENS * (ERRINJCT_TOKEN_LEN+1);
1075 buffer = (char *)kmalloc(m, GFP_KERNEL);
1076 if (!buffer) {
1077 printk(KERN_ERR "error: kmalloc failed\n");
1078 return -ENOMEM;
1079 }
1080
1081 for (i = 0; i < MAX_ERRINJCT_TOKENS && ei_token_list[i].value; i++) {
1082 n += snprintf(buffer+n, m-n, ei_token_list[i].name);
1083 n += snprintf(buffer+n, m-n, "\n");
1084 }
1085
1086 sn = strlen(buffer) +1;
1087 if (pos != (unsigned)pos || pos >= sn) {
1088 kfree(buffer);
1089 return 0;
1090 }
1091 if (n > sn - pos)
1092 n = sn - pos;
1093
1094 if (n > count)
1095 n = count;
1096
1097 if (copy_to_user(buf, buffer + pos, n)) {
1098 kfree(buffer);
1099 return -EFAULT;
1100 }
1101
1102 *ppos = pos + n;
1103
1104 kfree(buffer);
1105 return n;
1106}
1107