0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/errno.h>
0017 #include <linux/sched.h>
0018 #include <linux/proc_fs.h>
0019 #include <linux/stat.h>
0020 #include <linux/ctype.h>
0021 #include <linux/time.h>
0022 #include <linux/string.h>
0023 #include <linux/init.h>
0024 #include <linux/seq_file.h>
0025 #include <linux/bitops.h>
0026 #include <linux/rtc.h>
0027 #include <linux/of.h>
0028
0029 #include <linux/uaccess.h>
0030 #include <asm/processor.h>
0031 #include <asm/io.h>
0032 #include <asm/rtas.h>
0033 #include <asm/machdep.h> /* for ppc_md */
0034 #include <asm/time.h>
0035
0036
0037 #define KEY_SWITCH 0x0001
0038 #define ENCLOSURE_SWITCH 0x0002
0039 #define THERMAL_SENSOR 0x0003
0040 #define LID_STATUS 0x0004
0041 #define POWER_SOURCE 0x0005
0042 #define BATTERY_VOLTAGE 0x0006
0043 #define BATTERY_REMAINING 0x0007
0044 #define BATTERY_PERCENTAGE 0x0008
0045 #define EPOW_SENSOR 0x0009
0046 #define BATTERY_CYCLESTATE 0x000a
0047 #define BATTERY_CHARGING 0x000b
0048
0049
0050 #define IBM_SURVEILLANCE 0x2328
0051 #define IBM_FANRPM 0x2329
0052 #define IBM_VOLTAGE 0x232a
0053 #define IBM_DRCONNECTOR 0x232b
0054 #define IBM_POWERSUPPLY 0x232c
0055
0056
0057 #define SENSOR_CRITICAL_HIGH 13
0058 #define SENSOR_WARNING_HIGH 12
0059 #define SENSOR_NORMAL 11
0060 #define SENSOR_WARNING_LOW 10
0061 #define SENSOR_CRITICAL_LOW 9
0062 #define SENSOR_SUCCESS 0
0063 #define SENSOR_HW_ERROR -1
0064 #define SENSOR_BUSY -2
0065 #define SENSOR_NOT_EXIST -3
0066 #define SENSOR_DR_ENTITY -9000
0067
0068
0069 #define LOC_SCSI_DEV_ADDR 'A'
0070 #define LOC_SCSI_DEV_LOC 'B'
0071 #define LOC_CPU 'C'
0072 #define LOC_DISKETTE 'D'
0073 #define LOC_ETHERNET 'E'
0074 #define LOC_FAN 'F'
0075 #define LOC_GRAPHICS 'G'
0076
0077 #define LOC_IO_ADAPTER 'I'
0078
0079 #define LOC_KEYBOARD 'K'
0080 #define LOC_LCD 'L'
0081 #define LOC_MEMORY 'M'
0082 #define LOC_NV_MEMORY 'N'
0083 #define LOC_MOUSE 'O'
0084 #define LOC_PLANAR 'P'
0085 #define LOC_OTHER_IO 'Q'
0086 #define LOC_PARALLEL 'R'
0087 #define LOC_SERIAL 'S'
0088 #define LOC_DEAD_RING 'T'
0089 #define LOC_RACKMOUNTED 'U'
0090 #define LOC_VOLTAGE 'V'
0091 #define LOC_SWITCH_ADAPTER 'W'
0092 #define LOC_OTHER 'X'
0093 #define LOC_FIRMWARE 'Y'
0094 #define LOC_SCSI 'Z'
0095
0096
0097 #define TONE_FREQUENCY 0x0001
0098 #define TONE_VOLUME 0x0002
0099 #define SYSTEM_POWER_STATE 0x0003
0100 #define WARNING_LIGHT 0x0004
0101 #define DISK_ACTIVITY_LIGHT 0x0005
0102 #define HEX_DISPLAY_UNIT 0x0006
0103 #define BATTERY_WARNING_TIME 0x0007
0104 #define CONDITION_CYCLE_REQUEST 0x0008
0105 #define SURVEILLANCE_INDICATOR 0x2328
0106 #define DR_ACTION 0x2329
0107 #define DR_INDICATOR 0x232a
0108
0109
0110
0111
0112 #define MAX_SENSORS 17
0113 #define MAX_LINELENGTH 256
0114 #define SENSOR_PREFIX "ibm,sensor-"
0115 #define cel_to_fahr(x) ((x*9/5)+32)
0116
0117 struct individual_sensor {
0118 unsigned int token;
0119 unsigned int quant;
0120 };
0121
0122 struct rtas_sensors {
0123 struct individual_sensor sensor[MAX_SENSORS];
0124 unsigned int quant;
0125 };
0126
0127
0128 static struct rtas_sensors sensors;
0129 static struct device_node *rtas_node = NULL;
0130 static unsigned long power_on_time = 0;
0131 static char progress_led[MAX_LINELENGTH];
0132
0133 static unsigned long rtas_tone_frequency = 1000;
0134 static unsigned long rtas_tone_volume = 0;
0135
0136
0137
0138 static int ppc_rtas_sensors_show(struct seq_file *m, void *v);
0139 static int ppc_rtas_clock_show(struct seq_file *m, void *v);
0140 static ssize_t ppc_rtas_clock_write(struct file *file,
0141 const char __user *buf, size_t count, loff_t *ppos);
0142 static int ppc_rtas_progress_show(struct seq_file *m, void *v);
0143 static ssize_t ppc_rtas_progress_write(struct file *file,
0144 const char __user *buf, size_t count, loff_t *ppos);
0145 static int ppc_rtas_poweron_show(struct seq_file *m, void *v);
0146 static ssize_t ppc_rtas_poweron_write(struct file *file,
0147 const char __user *buf, size_t count, loff_t *ppos);
0148
0149 static ssize_t ppc_rtas_tone_freq_write(struct file *file,
0150 const char __user *buf, size_t count, loff_t *ppos);
0151 static int ppc_rtas_tone_freq_show(struct seq_file *m, void *v);
0152 static ssize_t ppc_rtas_tone_volume_write(struct file *file,
0153 const char __user *buf, size_t count, loff_t *ppos);
0154 static int ppc_rtas_tone_volume_show(struct seq_file *m, void *v);
0155 static int ppc_rtas_rmo_buf_show(struct seq_file *m, void *v);
0156
0157 static int poweron_open(struct inode *inode, struct file *file)
0158 {
0159 return single_open(file, ppc_rtas_poweron_show, NULL);
0160 }
0161
0162 static const struct proc_ops ppc_rtas_poweron_proc_ops = {
0163 .proc_open = poweron_open,
0164 .proc_read = seq_read,
0165 .proc_lseek = seq_lseek,
0166 .proc_write = ppc_rtas_poweron_write,
0167 .proc_release = single_release,
0168 };
0169
0170 static int progress_open(struct inode *inode, struct file *file)
0171 {
0172 return single_open(file, ppc_rtas_progress_show, NULL);
0173 }
0174
0175 static const struct proc_ops ppc_rtas_progress_proc_ops = {
0176 .proc_open = progress_open,
0177 .proc_read = seq_read,
0178 .proc_lseek = seq_lseek,
0179 .proc_write = ppc_rtas_progress_write,
0180 .proc_release = single_release,
0181 };
0182
0183 static int clock_open(struct inode *inode, struct file *file)
0184 {
0185 return single_open(file, ppc_rtas_clock_show, NULL);
0186 }
0187
0188 static const struct proc_ops ppc_rtas_clock_proc_ops = {
0189 .proc_open = clock_open,
0190 .proc_read = seq_read,
0191 .proc_lseek = seq_lseek,
0192 .proc_write = ppc_rtas_clock_write,
0193 .proc_release = single_release,
0194 };
0195
0196 static int tone_freq_open(struct inode *inode, struct file *file)
0197 {
0198 return single_open(file, ppc_rtas_tone_freq_show, NULL);
0199 }
0200
0201 static const struct proc_ops ppc_rtas_tone_freq_proc_ops = {
0202 .proc_open = tone_freq_open,
0203 .proc_read = seq_read,
0204 .proc_lseek = seq_lseek,
0205 .proc_write = ppc_rtas_tone_freq_write,
0206 .proc_release = single_release,
0207 };
0208
0209 static int tone_volume_open(struct inode *inode, struct file *file)
0210 {
0211 return single_open(file, ppc_rtas_tone_volume_show, NULL);
0212 }
0213
0214 static const struct proc_ops ppc_rtas_tone_volume_proc_ops = {
0215 .proc_open = tone_volume_open,
0216 .proc_read = seq_read,
0217 .proc_lseek = seq_lseek,
0218 .proc_write = ppc_rtas_tone_volume_write,
0219 .proc_release = single_release,
0220 };
0221
0222 static int ppc_rtas_find_all_sensors(void);
0223 static void ppc_rtas_process_sensor(struct seq_file *m,
0224 struct individual_sensor *s, int state, int error, const char *loc);
0225 static char *ppc_rtas_process_error(int error);
0226 static void get_location_code(struct seq_file *m,
0227 struct individual_sensor *s, const char *loc);
0228 static void check_location_string(struct seq_file *m, const char *c);
0229 static void check_location(struct seq_file *m, const char *c);
0230
0231 static int __init proc_rtas_init(void)
0232 {
0233 if (!machine_is(pseries))
0234 return -ENODEV;
0235
0236 rtas_node = of_find_node_by_name(NULL, "rtas");
0237 if (rtas_node == NULL)
0238 return -ENODEV;
0239
0240 proc_create("powerpc/rtas/progress", 0644, NULL,
0241 &ppc_rtas_progress_proc_ops);
0242 proc_create("powerpc/rtas/clock", 0644, NULL,
0243 &ppc_rtas_clock_proc_ops);
0244 proc_create("powerpc/rtas/poweron", 0644, NULL,
0245 &ppc_rtas_poweron_proc_ops);
0246 proc_create_single("powerpc/rtas/sensors", 0444, NULL,
0247 ppc_rtas_sensors_show);
0248 proc_create("powerpc/rtas/frequency", 0644, NULL,
0249 &ppc_rtas_tone_freq_proc_ops);
0250 proc_create("powerpc/rtas/volume", 0644, NULL,
0251 &ppc_rtas_tone_volume_proc_ops);
0252 proc_create_single("powerpc/rtas/rmo_buffer", 0400, NULL,
0253 ppc_rtas_rmo_buf_show);
0254 return 0;
0255 }
0256
0257 __initcall(proc_rtas_init);
0258
0259 static int parse_number(const char __user *p, size_t count, u64 *val)
0260 {
0261 char buf[40];
0262
0263 if (count > 39)
0264 return -EINVAL;
0265
0266 if (copy_from_user(buf, p, count))
0267 return -EFAULT;
0268
0269 buf[count] = 0;
0270
0271 return kstrtoull(buf, 10, val);
0272 }
0273
0274
0275
0276
0277 static ssize_t ppc_rtas_poweron_write(struct file *file,
0278 const char __user *buf, size_t count, loff_t *ppos)
0279 {
0280 struct rtc_time tm;
0281 time64_t nowtime;
0282 int error = parse_number(buf, count, &nowtime);
0283 if (error)
0284 return error;
0285
0286 power_on_time = nowtime;
0287
0288 rtc_time64_to_tm(nowtime, &tm);
0289
0290 error = rtas_call(rtas_token("set-time-for-power-on"), 7, 1, NULL,
0291 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
0292 tm.tm_hour, tm.tm_min, tm.tm_sec, 0 );
0293 if (error)
0294 printk(KERN_WARNING "error: setting poweron time returned: %s\n",
0295 ppc_rtas_process_error(error));
0296 return count;
0297 }
0298
0299 static int ppc_rtas_poweron_show(struct seq_file *m, void *v)
0300 {
0301 if (power_on_time == 0)
0302 seq_printf(m, "Power on time not set\n");
0303 else
0304 seq_printf(m, "%lu\n",power_on_time);
0305 return 0;
0306 }
0307
0308
0309
0310
0311 static ssize_t ppc_rtas_progress_write(struct file *file,
0312 const char __user *buf, size_t count, loff_t *ppos)
0313 {
0314 unsigned long hex;
0315
0316 if (count >= MAX_LINELENGTH)
0317 count = MAX_LINELENGTH -1;
0318 if (copy_from_user(progress_led, buf, count)) {
0319 return -EFAULT;
0320 }
0321 progress_led[count] = 0;
0322
0323
0324 hex = simple_strtoul(progress_led, NULL, 10);
0325
0326 rtas_progress ((char *)progress_led, hex);
0327 return count;
0328
0329
0330
0331 }
0332
0333 static int ppc_rtas_progress_show(struct seq_file *m, void *v)
0334 {
0335 if (progress_led[0])
0336 seq_printf(m, "%s\n", progress_led);
0337 return 0;
0338 }
0339
0340
0341
0342
0343 static ssize_t ppc_rtas_clock_write(struct file *file,
0344 const char __user *buf, size_t count, loff_t *ppos)
0345 {
0346 struct rtc_time tm;
0347 time64_t nowtime;
0348 int error = parse_number(buf, count, &nowtime);
0349 if (error)
0350 return error;
0351
0352 rtc_time64_to_tm(nowtime, &tm);
0353 error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL,
0354 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
0355 tm.tm_hour, tm.tm_min, tm.tm_sec, 0);
0356 if (error)
0357 printk(KERN_WARNING "error: setting the clock returned: %s\n",
0358 ppc_rtas_process_error(error));
0359 return count;
0360 }
0361
0362 static int ppc_rtas_clock_show(struct seq_file *m, void *v)
0363 {
0364 int ret[8];
0365 int error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);
0366
0367 if (error) {
0368 printk(KERN_WARNING "error: reading the clock returned: %s\n",
0369 ppc_rtas_process_error(error));
0370 seq_printf(m, "0");
0371 } else {
0372 unsigned int year, mon, day, hour, min, sec;
0373 year = ret[0]; mon = ret[1]; day = ret[2];
0374 hour = ret[3]; min = ret[4]; sec = ret[5];
0375 seq_printf(m, "%lld\n",
0376 mktime64(year, mon, day, hour, min, sec));
0377 }
0378 return 0;
0379 }
0380
0381
0382
0383
0384 static int ppc_rtas_sensors_show(struct seq_file *m, void *v)
0385 {
0386 int i,j;
0387 int state, error;
0388 int get_sensor_state = rtas_token("get-sensor-state");
0389
0390 seq_printf(m, "RTAS (RunTime Abstraction Services) Sensor Information\n");
0391 seq_printf(m, "Sensor\t\tValue\t\tCondition\tLocation\n");
0392 seq_printf(m, "********************************************************\n");
0393
0394 if (ppc_rtas_find_all_sensors() != 0) {
0395 seq_printf(m, "\nNo sensors are available\n");
0396 return 0;
0397 }
0398
0399 for (i=0; i<sensors.quant; i++) {
0400 struct individual_sensor *p = &sensors.sensor[i];
0401 char rstr[64];
0402 const char *loc;
0403 int llen, offs;
0404
0405 sprintf (rstr, SENSOR_PREFIX"%04d", p->token);
0406 loc = of_get_property(rtas_node, rstr, &llen);
0407
0408
0409 for (j = 0, offs = 0; j <= p->quant; j++) {
0410 error = rtas_call(get_sensor_state, 2, 2, &state,
0411 p->token, j);
0412
0413 ppc_rtas_process_sensor(m, p, state, error, loc);
0414 seq_putc(m, '\n');
0415 if (loc) {
0416 offs += strlen(loc) + 1;
0417 loc += strlen(loc) + 1;
0418 if (offs >= llen)
0419 loc = NULL;
0420 }
0421 }
0422 }
0423 return 0;
0424 }
0425
0426
0427
0428 static int ppc_rtas_find_all_sensors(void)
0429 {
0430 const unsigned int *utmp;
0431 int len, i;
0432
0433 utmp = of_get_property(rtas_node, "rtas-sensors", &len);
0434 if (utmp == NULL) {
0435 printk (KERN_ERR "error: could not get rtas-sensors\n");
0436 return 1;
0437 }
0438
0439 sensors.quant = len / 8;
0440
0441 for (i=0; i<sensors.quant; i++) {
0442 sensors.sensor[i].token = *utmp++;
0443 sensors.sensor[i].quant = *utmp++;
0444 }
0445 return 0;
0446 }
0447
0448
0449
0450
0451
0452 static char *ppc_rtas_process_error(int error)
0453 {
0454 switch (error) {
0455 case SENSOR_CRITICAL_HIGH:
0456 return "(critical high)";
0457 case SENSOR_WARNING_HIGH:
0458 return "(warning high)";
0459 case SENSOR_NORMAL:
0460 return "(normal)";
0461 case SENSOR_WARNING_LOW:
0462 return "(warning low)";
0463 case SENSOR_CRITICAL_LOW:
0464 return "(critical low)";
0465 case SENSOR_SUCCESS:
0466 return "(read ok)";
0467 case SENSOR_HW_ERROR:
0468 return "(hardware error)";
0469 case SENSOR_BUSY:
0470 return "(busy)";
0471 case SENSOR_NOT_EXIST:
0472 return "(non existent)";
0473 case SENSOR_DR_ENTITY:
0474 return "(dr entity removed)";
0475 default:
0476 return "(UNKNOWN)";
0477 }
0478 }
0479
0480
0481
0482
0483
0484
0485 static void ppc_rtas_process_sensor(struct seq_file *m,
0486 struct individual_sensor *s, int state, int error, const char *loc)
0487 {
0488
0489 const char * key_switch[] = { "Off\t", "Normal\t", "Secure\t",
0490 "Maintenance" };
0491 const char * enclosure_switch[] = { "Closed", "Open" };
0492 const char * lid_status[] = { " ", "Open", "Closed" };
0493 const char * power_source[] = { "AC\t", "Battery",
0494 "AC & Battery" };
0495 const char * battery_remaining[] = { "Very Low", "Low", "Mid", "High" };
0496 const char * epow_sensor[] = {
0497 "EPOW Reset", "Cooling warning", "Power warning",
0498 "System shutdown", "System halt", "EPOW main enclosure",
0499 "EPOW power off" };
0500 const char * battery_cyclestate[] = { "None", "In progress",
0501 "Requested" };
0502 const char * battery_charging[] = { "Charging", "Discharging",
0503 "No current flow" };
0504 const char * ibm_drconnector[] = { "Empty", "Present", "Unusable",
0505 "Exchange" };
0506
0507 int have_strings = 0;
0508 int num_states = 0;
0509 int temperature = 0;
0510 int unknown = 0;
0511
0512
0513
0514 switch (s->token) {
0515 case KEY_SWITCH:
0516 seq_printf(m, "Key switch:\t");
0517 num_states = sizeof(key_switch) / sizeof(char *);
0518 if (state < num_states) {
0519 seq_printf(m, "%s\t", key_switch[state]);
0520 have_strings = 1;
0521 }
0522 break;
0523 case ENCLOSURE_SWITCH:
0524 seq_printf(m, "Enclosure switch:\t");
0525 num_states = sizeof(enclosure_switch) / sizeof(char *);
0526 if (state < num_states) {
0527 seq_printf(m, "%s\t",
0528 enclosure_switch[state]);
0529 have_strings = 1;
0530 }
0531 break;
0532 case THERMAL_SENSOR:
0533 seq_printf(m, "Temp. (C/F):\t");
0534 temperature = 1;
0535 break;
0536 case LID_STATUS:
0537 seq_printf(m, "Lid status:\t");
0538 num_states = sizeof(lid_status) / sizeof(char *);
0539 if (state < num_states) {
0540 seq_printf(m, "%s\t", lid_status[state]);
0541 have_strings = 1;
0542 }
0543 break;
0544 case POWER_SOURCE:
0545 seq_printf(m, "Power source:\t");
0546 num_states = sizeof(power_source) / sizeof(char *);
0547 if (state < num_states) {
0548 seq_printf(m, "%s\t",
0549 power_source[state]);
0550 have_strings = 1;
0551 }
0552 break;
0553 case BATTERY_VOLTAGE:
0554 seq_printf(m, "Battery voltage:\t");
0555 break;
0556 case BATTERY_REMAINING:
0557 seq_printf(m, "Battery remaining:\t");
0558 num_states = sizeof(battery_remaining) / sizeof(char *);
0559 if (state < num_states)
0560 {
0561 seq_printf(m, "%s\t",
0562 battery_remaining[state]);
0563 have_strings = 1;
0564 }
0565 break;
0566 case BATTERY_PERCENTAGE:
0567 seq_printf(m, "Battery percentage:\t");
0568 break;
0569 case EPOW_SENSOR:
0570 seq_printf(m, "EPOW Sensor:\t");
0571 num_states = sizeof(epow_sensor) / sizeof(char *);
0572 if (state < num_states) {
0573 seq_printf(m, "%s\t", epow_sensor[state]);
0574 have_strings = 1;
0575 }
0576 break;
0577 case BATTERY_CYCLESTATE:
0578 seq_printf(m, "Battery cyclestate:\t");
0579 num_states = sizeof(battery_cyclestate) /
0580 sizeof(char *);
0581 if (state < num_states) {
0582 seq_printf(m, "%s\t",
0583 battery_cyclestate[state]);
0584 have_strings = 1;
0585 }
0586 break;
0587 case BATTERY_CHARGING:
0588 seq_printf(m, "Battery Charging:\t");
0589 num_states = sizeof(battery_charging) / sizeof(char *);
0590 if (state < num_states) {
0591 seq_printf(m, "%s\t",
0592 battery_charging[state]);
0593 have_strings = 1;
0594 }
0595 break;
0596 case IBM_SURVEILLANCE:
0597 seq_printf(m, "Surveillance:\t");
0598 break;
0599 case IBM_FANRPM:
0600 seq_printf(m, "Fan (rpm):\t");
0601 break;
0602 case IBM_VOLTAGE:
0603 seq_printf(m, "Voltage (mv):\t");
0604 break;
0605 case IBM_DRCONNECTOR:
0606 seq_printf(m, "DR connector:\t");
0607 num_states = sizeof(ibm_drconnector) / sizeof(char *);
0608 if (state < num_states) {
0609 seq_printf(m, "%s\t",
0610 ibm_drconnector[state]);
0611 have_strings = 1;
0612 }
0613 break;
0614 case IBM_POWERSUPPLY:
0615 seq_printf(m, "Powersupply:\t");
0616 break;
0617 default:
0618 seq_printf(m, "Unknown sensor (type %d), ignoring it\n",
0619 s->token);
0620 unknown = 1;
0621 have_strings = 1;
0622 break;
0623 }
0624 if (have_strings == 0) {
0625 if (temperature) {
0626 seq_printf(m, "%4d /%4d\t", state, cel_to_fahr(state));
0627 } else
0628 seq_printf(m, "%10d\t", state);
0629 }
0630 if (unknown == 0) {
0631 seq_printf(m, "%s\t", ppc_rtas_process_error(error));
0632 get_location_code(m, s, loc);
0633 }
0634 }
0635
0636
0637
0638 static void check_location(struct seq_file *m, const char *c)
0639 {
0640 switch (c[0]) {
0641 case LOC_PLANAR:
0642 seq_printf(m, "Planar #%c", c[1]);
0643 break;
0644 case LOC_CPU:
0645 seq_printf(m, "CPU #%c", c[1]);
0646 break;
0647 case LOC_FAN:
0648 seq_printf(m, "Fan #%c", c[1]);
0649 break;
0650 case LOC_RACKMOUNTED:
0651 seq_printf(m, "Rack #%c", c[1]);
0652 break;
0653 case LOC_VOLTAGE:
0654 seq_printf(m, "Voltage #%c", c[1]);
0655 break;
0656 case LOC_LCD:
0657 seq_printf(m, "LCD #%c", c[1]);
0658 break;
0659 case '.':
0660 seq_printf(m, "- %c", c[1]);
0661 break;
0662 default:
0663 seq_printf(m, "Unknown location");
0664 break;
0665 }
0666 }
0667
0668
0669
0670
0671
0672
0673
0674
0675 static void check_location_string(struct seq_file *m, const char *c)
0676 {
0677 while (*c) {
0678 if (isalpha(*c) || *c == '.')
0679 check_location(m, c);
0680 else if (*c == '/' || *c == '-')
0681 seq_printf(m, " at ");
0682 c++;
0683 }
0684 }
0685
0686
0687
0688
0689 static void get_location_code(struct seq_file *m, struct individual_sensor *s,
0690 const char *loc)
0691 {
0692 if (!loc || !*loc) {
0693 seq_printf(m, "---");
0694 } else {
0695 check_location_string(m, loc);
0696 }
0697 seq_putc(m, ' ');
0698 }
0699
0700
0701
0702 static ssize_t ppc_rtas_tone_freq_write(struct file *file,
0703 const char __user *buf, size_t count, loff_t *ppos)
0704 {
0705 u64 freq;
0706 int error = parse_number(buf, count, &freq);
0707 if (error)
0708 return error;
0709
0710 rtas_tone_frequency = freq;
0711 error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL,
0712 TONE_FREQUENCY, 0, freq);
0713 if (error)
0714 printk(KERN_WARNING "error: setting tone frequency returned: %s\n",
0715 ppc_rtas_process_error(error));
0716 return count;
0717 }
0718
0719 static int ppc_rtas_tone_freq_show(struct seq_file *m, void *v)
0720 {
0721 seq_printf(m, "%lu\n", rtas_tone_frequency);
0722 return 0;
0723 }
0724
0725
0726
0727 static ssize_t ppc_rtas_tone_volume_write(struct file *file,
0728 const char __user *buf, size_t count, loff_t *ppos)
0729 {
0730 u64 volume;
0731 int error = parse_number(buf, count, &volume);
0732 if (error)
0733 return error;
0734
0735 if (volume > 100)
0736 volume = 100;
0737
0738 rtas_tone_volume = volume;
0739 error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL,
0740 TONE_VOLUME, 0, volume);
0741 if (error)
0742 printk(KERN_WARNING "error: setting tone volume returned: %s\n",
0743 ppc_rtas_process_error(error));
0744 return count;
0745 }
0746
0747 static int ppc_rtas_tone_volume_show(struct seq_file *m, void *v)
0748 {
0749 seq_printf(m, "%lu\n", rtas_tone_volume);
0750 return 0;
0751 }
0752
0753
0754
0755
0756
0757
0758
0759
0760
0761
0762
0763 static int ppc_rtas_rmo_buf_show(struct seq_file *m, void *v)
0764 {
0765 seq_printf(m, "%016lx %x\n", rtas_rmo_buf, RTAS_USER_REGION_SIZE);
0766 return 0;
0767 }