* [parisc-linux] [patch] /proc interface for LED/LCD
@ 2001-10-06 20:42 Randolph Chung
2001-10-06 21:49 ` Helge Deller
[not found] ` <E15pzKV-0000ZU-00@gandalf.tausq.org>
0 siblings, 2 replies; 7+ messages in thread
From: Randolph Chung @ 2001-10-06 20:42 UTC (permalink / raw)
To: parisc-linux
hi all,
the attached patch creates a /proc interface for boxes with LED/LCD
support. For example:
legolas:/home/randolph# ls -l /proc/pdc/
total 0
-rw-r--r-- 1 root root 0 Oct 6 13:35 lcd
-rw-r--r-- 1 root root 0 Oct 6 13:35 led
legolas:/home/randolph# cat /proc/pdc/led
Heartbeat: 1
Disk IO: 1
LAN Rx/Tx: 1
legolas:/home/randolph# cat /proc/pdc/lcd
Linux 2.4.9-pa40
legolas:/home/randolph# echo -n "debian/rules" > /proc/pdc/lcd
("debian/rules" appears on the LCD on the chassis....)
legolas:/home/randolph# cat /proc/pdc/lcd
debian/rules
legolas:/home/randolph# echo > /proc/pdc/lcd
(Chassis reverts to original Linux version display)
legolas:/home/randolph# cat /proc/pdc/lcd
Linux 2.4.9-pa40
legolas:/home/randolph# echo "1 1 0" > /proc/pdc/led
(invalid strings will cause an error to go to your kernel log)
legolas:/home/randolph# cat /proc/pdc/led
Heartbeat: 1
Disk IO: 1
LAN Rx/Tx: 0
I've only tested it on a c3000 (only machine i have with led/lcd
support). Would appreciate if folks can try it on other machines and let
me know if it works :)
This also requires a small fix to arch/parisc/kernel/firmware.c which i
checked into cvs this morning.
enjoy! :)
randolph
--
@..@ http://www.TauSq.org/
(----)
( >__< )
^^ ~~ ^^
Index: arch/parisc/kernel/led.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/led.c,v
retrieving revision 1.22
diff -u -r1.22 led.c
--- led.c 2001/08/14 16:54:52 1.22
+++ led.c 2001/10/06 20:31:47
@@ -4,6 +4,7 @@
* (c) Copyright 2000 Red Hat Software
* (c) Copyright 2000 Helge Deller <hdeller@redhat.com>
* (c) Copyright 2001 Helge Deller <deller@gmx.de>
+ * (c) Copyright 2001 Randolph Chung <tausq@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -11,9 +12,8 @@
* (at your option) any later version.
*
* TODO:
- * - LCD functionality is mostly untested (lack of hardware :-()
- * - add procfs entry to (maybe partially) enable & disable LEDs
* - speed-up calculations with inlined assembler
+ * - interface to write to second row of LCD from /proc
*/
#include <linux/config.h>
@@ -28,6 +28,8 @@
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/reboot.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
#include <asm/io.h>
#include <asm/gsc.h>
#include <asm/processor.h>
@@ -35,16 +37,20 @@
#include <asm/param.h> /* HZ */
#include <asm/led.h>
#include <asm/pdc.h>
+#include <asm/uaccess.h>
/* The control of the LEDs and LCDs on PARISC-machines have to be done
completely in software. The necessary calculations are done in a tasklet
which is scheduled at every timer interrupt and since the calculations
may consume relatively much CPU-time some of the calculations can be
- turned off with the following defines */
-#undef NO_HEARTBEAT
-#undef NO_DISKIO
-#undef NO_LAN_RXTX
+ turned off with the following variables (controlled via procfs) */
+static int led_type = -1;
+static int led_heartbeat = 1;
+static int led_diskio = 1;
+static int led_lanrxtx = 1;
+static char lcd_text[32] = {0};
+
#if 0
#define DPRINTK(x) printk x
#else
@@ -110,6 +116,132 @@
/* ptr to LCD/LED-specific function */
static void (*led_func_ptr) (unsigned char);
+#define LED_HASLCD 1
+#define LED_NOLCD 0
+#ifdef CONFIG_PROC_FS
+static int led_proc_read(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+{
+ char *out = page;
+ int len;
+
+ switch ((long)data)
+ {
+ case LED_NOLCD:
+ out += sprintf(out, "Heartbeat: %d\n", led_heartbeat);
+ out += sprintf(out, "Disk IO: %d\n", led_diskio);
+ out += sprintf(out, "LAN Rx/Tx: %d\n", led_lanrxtx);
+ break;
+ case LED_HASLCD:
+ out += sprintf(out, "%s\n", lcd_text);
+ break;
+ default:
+ *eof = 1;
+ return 0;
+ }
+
+ len = out - page - off;
+ if (len < count) {
+ *eof = 1;
+ if (len <= 0) return 0;
+ } else {
+ len = count;
+ }
+ *start = page + off;
+ return len;
+}
+
+static int led_proc_write(struct file *file, const char *buf,
+ unsigned long count, void *data)
+{
+ const char *cur = NULL;
+ char lbuf[count];
+ int d;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
+ lcopy_from_user(lbuf, buf, count);
+ cur = lbuf;
+
+ /* skip initial spaces */
+ while (*cur && isspace(*cur))
+ {
+ cur++;
+ }
+
+ switch ((long)data)
+ {
+ case LED_NOLCD:
+ d = *cur++ - '0';
+ if (d != 0 && d != 1) goto parse_error;
+ led_heartbeat = d;
+
+ if (*cur++ != ' ') goto parse_error;
+
+ d = *cur++ - '0';
+ if (d != 0 && d != 1) goto parse_error;
+ led_diskio = d;
+
+ if (*cur++ != ' ') goto parse_error;
+
+ d = *cur++ - '0';
+ if (d != 0 && d != 1) goto parse_error;
+ led_lanrxtx = d;
+
+ break;
+ case LED_HASLCD:
+ if (*cur == 0)
+ {
+ /* reset to default */
+ lcd_print("Linux " UTS_RELEASE);
+ }
+ else
+ {
+ lcd_print(cur);
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ return count;
+
+parse_error:
+ if ((long)data == LED_NOLCD)
+ printk(KERN_CRIT "Parse error: expect \"n n n\" (n == 0 or 1) for heartbeat,\ndisk io and lan tx/rx indicators\n");
+ return -EINVAL;
+}
+
+static int __init led_create_procfs(void)
+{
+ struct proc_dir_entry *proc_pdc_root = NULL;
+ struct proc_dir_entry *ent;
+
+ if (led_type == -1) return -1;
+
+ proc_pdc_root = proc_mkdir("pdc", 0);
+ if (!proc_pdc_root) return -1;
+ ent = create_proc_entry("led", S_IFREG|S_IRUGO|S_IWUSR, proc_pdc_root);
+ if (!ent) return -1;
+ ent->nlink = 1;
+ ent->data = (void *)LED_NOLCD; /* LED */
+ ent->read_proc = led_proc_read;
+ ent->write_proc = led_proc_write;
+
+ if (led_type == LED_HASLCD)
+ {
+ ent = create_proc_entry("lcd", S_IFREG|S_IRUGO|S_IWUSR, proc_pdc_root);
+ if (!ent) return -1;
+ ent->nlink = 1;
+ ent->data = (void *)LED_HASLCD; /* LCD */
+ ent->read_proc = led_proc_read;
+ ent->write_proc = led_proc_write;
+ }
+
+ return 0;
+}
+#endif
/*
**
@@ -208,7 +340,6 @@
** (analog to dev_get_info() from net/core/dev.c)
**
*/
-#ifndef NO_LAN_RXTX
static unsigned long led_net_rx_counter, led_net_tx_counter;
static void led_get_net_stats(int addvalue)
@@ -244,7 +375,6 @@
rx_total_last += rx_total;
tx_total_last += tx_total;
}
-#endif /* NO_LAN_RXTX */
/*
@@ -255,7 +385,6 @@
** (analog to linux/fs/proc/proc_misc.c)
**
*/
-#ifndef NO_DISKIO
static unsigned long led_diskio_counter;
static void led_get_diskio_stats(int addvalue)
@@ -280,7 +409,6 @@
diskio_total_last += total;
}
-#endif /* NO_DISKIO */
@@ -315,49 +443,52 @@
if (++count_HZ == HZ)
count_HZ = 0;
-#ifndef NO_HEARTBEAT
- /* flash heartbeat-LED like a real heart (2 x short then a long delay) */
- if (count_HZ<HEARTBEAT_LEN ||
- (count_HZ>=HEARTBEAT_2ND_RANGE_START && count_HZ<HEARTBEAT_2ND_RANGE_END))
- currentleds |= LED_HEARTBEAT;
- else
- currentleds &= ~LED_HEARTBEAT;
-#endif
+ if (led_heartbeat)
+ {
+ /* flash heartbeat-LED like a real heart (2 x short then a long delay) */
+ if (count_HZ<HEARTBEAT_LEN ||
+ (count_HZ>=HEARTBEAT_2ND_RANGE_START && count_HZ<HEARTBEAT_2ND_RANGE_END))
+ currentleds |= LED_HEARTBEAT;
+ else
+ currentleds &= ~LED_HEARTBEAT;
+ }
/* gather network and diskio statistics and flash LEDs respectively */
-#ifndef NO_LAN_RXTX
- if ((count & 31) == 0)
- led_get_net_stats(30);
-
- if (led_net_rx_counter) {
- led_net_rx_counter--;
- currentleds |= LED_LAN_RCV;
- }
- else
- currentleds &= ~LED_LAN_RCV;
-
- if (led_net_tx_counter) {
- led_net_tx_counter--;
- currentleds |= LED_LAN_TX;
+ if (led_lanrxtx)
+ {
+ if ((count & 31) == 0)
+ led_get_net_stats(30);
+
+ if (led_net_rx_counter) {
+ led_net_rx_counter--;
+ currentleds |= LED_LAN_RCV;
+ }
+ else
+ currentleds &= ~LED_LAN_RCV;
+
+ if (led_net_tx_counter) {
+ led_net_tx_counter--;
+ currentleds |= LED_LAN_TX;
+ }
+ else
+ currentleds &= ~LED_LAN_TX;
+ }
+
+ if (led_diskio)
+ {
+ /* avoid to calculate diskio-stats at same irq as netio-stats ! */
+ if ((count & 31) == 15)
+ led_get_diskio_stats(30);
+
+ if (led_diskio_counter) {
+ led_diskio_counter--;
+ currentleds |= LED_DISK_IO;
+ }
+ else
+ currentleds &= ~LED_DISK_IO;
}
- else
- currentleds &= ~LED_LAN_TX;
-#endif
-#ifndef NO_DISKIO
- /* avoid to calculate diskio-stats at same irq as netio-stats ! */
- if ((count & 31) == 15)
- led_get_diskio_stats(30);
-
- if (led_diskio_counter) {
- led_diskio_counter--;
- currentleds |= LED_DISK_IO;
- }
- else
- currentleds &= ~LED_DISK_IO;
-#endif
-
/* update the LCD/LEDs */
if (currentleds != lastleds) {
led_func_ptr(currentleds);
@@ -435,12 +566,14 @@
LCD_CMD_REG , LCD_DATA_REG);
led_func_ptr = led_LCD_driver;
lcd_print( "Linux " UTS_RELEASE );
+ led_type = LED_HASLCD;
break;
case DISPLAY_MODEL_LASI:
LED_DATA_REG = data_reg;
led_func_ptr = led_LASI_driver;
printk(KERN_INFO "LED display at %p registered\n", LED_DATA_REG);
+ led_type = LED_NOLCD;
break;
case DISPLAY_MODEL_OLD_ASP:
@@ -448,6 +581,7 @@
led_func_ptr = led_ASP_driver;
printk(KERN_INFO "LED (ASP-style) display at %p registered\n",
LED_DATA_REG);
+ led_type = LED_NOLCD;
break;
default:
@@ -509,6 +643,9 @@
if (!led_func_ptr || lcd_info.model != DISPLAY_MODEL_LCD)
return 0;
+ /* copy display string to buffer for procfs */
+ strncpy(lcd_text, str, sizeof(lcd_text)-1);
+
/* temporarily disable the led tasklet */
tasklet_disable(&led_tasklet);
@@ -619,3 +756,7 @@
lcd_info.model = DISPLAY_MODEL_NONE;
return 1;
}
+
+#ifdef CONFIG_PROC_FS
+module_init(led_create_procfs)
+#endif
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [parisc-linux] [patch] /proc interface for LED/LCD
2001-10-06 20:42 [parisc-linux] [patch] /proc interface for LED/LCD Randolph Chung
@ 2001-10-06 21:49 ` Helge Deller
[not found] ` <E15pzKV-0000ZU-00@gandalf.tausq.org>
1 sibling, 0 replies; 7+ messages in thread
From: Helge Deller @ 2001-10-06 21:49 UTC (permalink / raw)
To: Randolph Chung, parisc-linux
On Saturday 06 October 2001 22:42, Randolph Chung wrote:
> hi all,
>
> the attached patch creates a /proc interface for boxes with LED/LCD
> support. For example:
> ......
> I've only tested it on a c3000 (only machine i have with led/lcd
> support). Would appreciate if folks can try it on other machines and let
> me know if it works :)
Hi Randolph,
Nice patch !
I've tested it on my 715/64 (with LEDs) and on the c3k (w/ LCD).
On the 715/64 your patch works as expected, but on my c3k I neither
get anything on the LCD nor the /proc/pdc/lcd file.
I know that this doesn't happen due to your patch because I
didn't got the LCD to work before applying your patch too.
As far as I debugged it until now the pdc_chassis_info() call in
led_init() now returns -10 (PDC_INVALID_ARG) as result code, so maybe
something other is busted here.
Maybe you have any idea ?
All tests were done with the same 32bit kernel binary on both machines
and with your patch to inventory.c applied. I never tested a 64bit kernel
in case this should be relevant.
Helge
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [parisc-linux] [patch] /proc interface for LED/LCD
[not found] ` <E15pzKV-0000ZU-00@gandalf.tausq.org>
@ 2001-10-06 22:34 ` Randolph Chung
2001-10-07 6:56 ` Helge Deller
0 siblings, 1 reply; 7+ messages in thread
From: Randolph Chung @ 2001-10-06 22:34 UTC (permalink / raw)
To: Helge Deller; +Cc: parisc-linux
> I know that this doesn't happen due to your patch because I
> didn't got the LCD to work before applying your patch too.
> As far as I debugged it until now the pdc_chassis_info() call in
> led_init() now returns -10 (PDC_INVALID_ARG) as result code, so maybe
> something other is busted here.
> Maybe you have any idea ?
In my other post I mentioned you also need a fix to firmware.c .. did
you pick that up too?
randolph
--
@..@ http://www.TauSq.org/
(----)
( >__< )
^^ ~~ ^^
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [parisc-linux] [patch] /proc interface for LED/LCD
2001-10-06 22:34 ` Randolph Chung
@ 2001-10-07 6:56 ` Helge Deller
2001-10-09 7:10 ` Randolph Chung
2001-10-10 5:58 ` Randolph Chung
0 siblings, 2 replies; 7+ messages in thread
From: Helge Deller @ 2001-10-07 6:56 UTC (permalink / raw)
To: Randolph Chung; +Cc: parisc-linux
On Sunday 07 October 2001 00:34, Randolph Chung wrote:
> > I know that this doesn't happen due to your patch because I
> > didn't got the LCD to work before applying your patch too.
> > As far as I debugged it until now the pdc_chassis_info() call in
> > led_init() now returns -10 (PDC_INVALID_ARG) as result code, so maybe
> > something other is busted here.
> > Maybe you have any idea ?
>
> In my other post I mentioned you also need a fix to firmware.c .. did
> you pick that up too?
>
> randolph
Yes, I did. Unfortunately I mentioned inventory.c, but originally meant
firmware.c in my previous mail.
Helge
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [parisc-linux] [patch] /proc interface for LED/LCD
2001-10-07 6:56 ` Helge Deller
@ 2001-10-09 7:10 ` Randolph Chung
2001-10-10 5:58 ` Randolph Chung
1 sibling, 0 replies; 7+ messages in thread
From: Randolph Chung @ 2001-10-09 7:10 UTC (permalink / raw)
To: Helge Deller; +Cc: parisc-linux
> > In my other post I mentioned you also need a fix to firmware.c .. did
> > you pick that up too?
> Yes, I did. Unfortunately I mentioned inventory.c, but originally meant
> firmware.c in my previous mail.
Hrm, ok, both Grant and I also reproduced this failure with a 32-bit
kernel on a c3k. with 64-bit it's fine... looks like something odd
happening with the PDC_CHASSIS_INFO call :-(
I can't find any documentation for this hversion-specific pdc call to
fetch the led/lcd info. Can anyone point me to some docs? I can try to
debug it some more.
randolph
--
@..@ http://www.TauSq.org/
(----)
( >__< )
^^ ~~ ^^
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [parisc-linux] [patch] /proc interface for LED/LCD
2001-10-07 6:56 ` Helge Deller
2001-10-09 7:10 ` Randolph Chung
@ 2001-10-10 5:58 ` Randolph Chung
2001-10-10 7:49 ` Grant Grundler
1 sibling, 1 reply; 7+ messages in thread
From: Randolph Chung @ 2001-10-10 5:58 UTC (permalink / raw)
To: Helge Deller; +Cc: parisc-linux
> Yes, I did. Unfortunately I mentioned inventory.c, but originally meant
> firmware.c in my previous mail.
looks like there was another small fix needed for firmware.c. Please try
the latest one. It now works for me for both 64-bit and 32-bit kernels.
randolph
--
@..@ http://www.TauSq.org/
(----)
( >__< )
^^ ~~ ^^
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [parisc-linux] [patch] /proc interface for LED/LCD
2001-10-10 5:58 ` Randolph Chung
@ 2001-10-10 7:49 ` Grant Grundler
0 siblings, 0 replies; 7+ messages in thread
From: Grant Grundler @ 2001-10-10 7:49 UTC (permalink / raw)
To: Randolph Chung; +Cc: Helge Deller, parisc-linux
Randolph Chung wrote:
> looks like there was another small fix needed for firmware.c. Please try
> the latest one. It now works for me for both 64-bit and 32-bit kernels.
works for me :^)
grant
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2001-10-10 7:53 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-10-06 20:42 [parisc-linux] [patch] /proc interface for LED/LCD Randolph Chung
2001-10-06 21:49 ` Helge Deller
[not found] ` <E15pzKV-0000ZU-00@gandalf.tausq.org>
2001-10-06 22:34 ` Randolph Chung
2001-10-07 6:56 ` Helge Deller
2001-10-09 7:10 ` Randolph Chung
2001-10-10 5:58 ` Randolph Chung
2001-10-10 7:49 ` Grant Grundler
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox