b046439bf8
SVN-Revision: 1400
851 lines
22 KiB
Diff
851 lines
22 KiB
Diff
diff -urN linux.old/drivers/char/avalanche_led/ledmod.c linux.dev/drivers/char/avalanche_led/ledmod.c
|
|
--- linux.old/drivers/char/avalanche_led/ledmod.c 1970-01-01 01:00:00.000000000 +0100
|
|
+++ linux.dev/drivers/char/avalanche_led/ledmod.c 2005-07-11 03:16:48.247012224 +0200
|
|
@@ -0,0 +1,719 @@
|
|
+#include <linux/config.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/proc_fs.h>
|
|
+#include <asm/uaccess.h>
|
|
+#include <linux/fs.h>
|
|
+#include <linux/timer.h>
|
|
+#include <linux/delay.h>
|
|
+#include <linux/spinlock.h>
|
|
+#include <asm/ar7/avalanche_regs.h>
|
|
+#include <asm/ar7/ledapp.h>
|
|
+#include <linux/module.h>
|
|
+
|
|
+#define LED_ON 1
|
|
+#define LED_OFF 2
|
|
+#define LED_BLINK 3
|
|
+#define LED_FLASH 4
|
|
+
|
|
+#define LED_BLINK_UP 5
|
|
+#define LED_BLINK_DOWN 6
|
|
+
|
|
+typedef struct state_entry {
|
|
+ unsigned char mode;
|
|
+ unsigned char led;
|
|
+ void (*handler) (struct state_entry * pState);
|
|
+ unsigned long param;
|
|
+} state_entry_t;
|
|
+
|
|
+typedef struct mod_entry {
|
|
+ state_entry_t *states[MAX_STATE_ID];
|
|
+} mod_entry_t;
|
|
+
|
|
+static mod_entry_t *modArr[MAX_MOD_ID];
|
|
+static struct proc_dir_entry *led_proc_dir, *led_file;
|
|
+
|
|
+/* index of the array is the led number HARDWARE SPECIFIC*/
|
|
+typedef struct led_data {
|
|
+ led_reg_t *led;
|
|
+ int state;
|
|
+ struct timer_list *pTimer;
|
|
+ unsigned char timer_running;
|
|
+ unsigned long param;
|
|
+} led_data_t;
|
|
+
|
|
+led_data_t led_arr[MAX_LED_ID + 1];
|
|
+/*!!! The last device is actually being used for ar7 reset to factory default */
|
|
+#if 1
|
|
+/* Ron add for adsl LED blink */
|
|
+#define GPIO_ADSL_ACT (1<<6)
|
|
+#define GPIO_ADSL_DOWN (1<<8)
|
|
+#define BLINK_FAST 5*HZ/100
|
|
+#define BLINK_SLOW 15*HZ/100
|
|
+static struct timer_list my_led_timer;
|
|
+static int my_blink_count = 0;
|
|
+static int my_mode = 1;
|
|
+void led_operation(int mod, int state);
|
|
+
|
|
+static void my_led_on(unsigned long gpio, int logic)
|
|
+{
|
|
+ if (logic > 0)
|
|
+ GPIO_DATA_OUTPUT |= gpio;
|
|
+ else
|
|
+ GPIO_DATA_OUTPUT &= ~gpio;
|
|
+
|
|
+}
|
|
+static void my_led_off(unsigned long gpio, int logic)
|
|
+{
|
|
+ if (logic > 0)
|
|
+ GPIO_DATA_OUTPUT &= ~gpio;
|
|
+ else
|
|
+ GPIO_DATA_OUTPUT |= gpio;
|
|
+
|
|
+}
|
|
+
|
|
+static void my_led_init(unsigned long gpio, int init, int logic)
|
|
+{
|
|
+ GPIO_DATA_ENABLE |= gpio;
|
|
+ GPIO_DATA_DIR &= ~gpio;
|
|
+ if (init)
|
|
+ my_led_on(gpio, logic);
|
|
+ else
|
|
+ my_led_off(gpio, logic);
|
|
+}
|
|
+
|
|
+static void my_led_blink_timer(unsigned long data)
|
|
+{
|
|
+ unsigned long gpio = GPIO_ADSL_ACT;
|
|
+ unsigned int speed = BLINK_FAST;
|
|
+ if (my_mode == 2) {
|
|
+ gpio = GPIO_ADSL_DOWN;
|
|
+ speed = BLINK_SLOW;
|
|
+ }
|
|
+ if (my_blink_count) {
|
|
+ if (GPIO_DATA_OUTPUT & gpio) {
|
|
+ GPIO_DATA_OUTPUT &= ~gpio;
|
|
+ if (my_mode != 2)
|
|
+ my_blink_count = 0;
|
|
+ } else {
|
|
+ GPIO_DATA_OUTPUT |= gpio;
|
|
+ }
|
|
+ }
|
|
+ my_led_timer.expires = jiffies + speed;
|
|
+ add_timer(&my_led_timer);
|
|
+}
|
|
+
|
|
+/* Ron add for ADSL led blink */
|
|
+#endif
|
|
+static spinlock_t config_lock;
|
|
+
|
|
+static void board_led_link_up(state_entry_t * pState);
|
|
+static void board_led_link_down(state_entry_t * pState);
|
|
+static void board_led_activity_on(state_entry_t * pState);
|
|
+static void board_led_activity_off(state_entry_t * pState);
|
|
+static void led_timer_func(unsigned long data);
|
|
+
|
|
+static ssize_t proc_read_led_fops(struct file *filp, char *buf, size_t count, loff_t * offp);
|
|
+static ssize_t proc_write_led_fops(struct file *filp, const char *buffer, size_t count, loff_t * offp);
|
|
+static int config_led(unsigned long y);
|
|
+
|
|
+struct file_operations led_fops = {
|
|
+ read:proc_read_led_fops,
|
|
+ write:proc_write_led_fops,
|
|
+};
|
|
+
|
|
+static int led_atoi(char *name)
|
|
+{
|
|
+ int val = 0;
|
|
+ for (;; name++) {
|
|
+ switch (*name) {
|
|
+ case '0'...'9':
|
|
+ val = val * 10 + (*name - '0');
|
|
+ break;
|
|
+ default:
|
|
+ return val;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static int free_memory(void)
|
|
+{
|
|
+ int i, j;
|
|
+
|
|
+ for (i = 0; i < MAX_MOD_ID; i++) {
|
|
+ if (modArr[i] != NULL) {
|
|
+ for (j = 0; j < MAX_STATE_ID; j++) {
|
|
+ if (modArr[i]->states[j] != NULL)
|
|
+ kfree(modArr[i]->states[j]);
|
|
+ }
|
|
+ kfree(modArr[i]);
|
|
+ modArr[i] = NULL;
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int led_on(state_entry_t * pState)
|
|
+{
|
|
+ if (led_arr[pState->led].led == NULL)
|
|
+ return -1;
|
|
+ led_arr[pState->led].led->onfunc(led_arr[pState->led].led->param);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int led_off(state_entry_t * pState)
|
|
+{
|
|
+ if (led_arr[pState->led].led == NULL)
|
|
+ return -1;
|
|
+ led_arr[pState->led].led->offfunc(led_arr[pState->led].led->param);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void board_led_link_up(state_entry_t * pState)
|
|
+{
|
|
+ led_arr[pState->led].state = LED_ON;
|
|
+ if (led_arr[pState->led].timer_running == 0)
|
|
+ led_on(pState);
|
|
+ return;
|
|
+}
|
|
+
|
|
+static void board_led_link_down(state_entry_t * pState)
|
|
+{
|
|
+ led_arr[pState->led].state = LED_OFF;
|
|
+ if (led_arr[pState->led].timer_running == 0)
|
|
+ led_off(pState);
|
|
+ return;
|
|
+}
|
|
+
|
|
+static void add_led_timer(state_entry_t * pState)
|
|
+{
|
|
+ led_arr[pState->led].pTimer->expires =
|
|
+ jiffies + HZ * (pState->param) / 1000;
|
|
+ led_arr[pState->led].param = pState->param;
|
|
+ led_arr[pState->led].pTimer->data = pState;
|
|
+ add_timer(led_arr[pState->led].pTimer);
|
|
+}
|
|
+
|
|
+static void board_led_activity_on(state_entry_t * pState)
|
|
+{
|
|
+ if (led_arr[pState->led].timer_running == 0) {
|
|
+ led_on(pState);
|
|
+ add_led_timer(pState);
|
|
+ led_arr[pState->led].timer_running = 1;
|
|
+ led_arr[pState->led].state = LED_BLINK_UP;
|
|
+ } else if (led_arr[pState->led].timer_running > 0xF0) {
|
|
+ led_arr[pState->led].state = LED_BLINK_UP;
|
|
+ led_arr[pState->led].pTimer->expires =
|
|
+ jiffies + HZ * (pState->param) / 1000;
|
|
+ led_arr[pState->led].param = pState->param;
|
|
+ led_arr[pState->led].pTimer->data = pState;
|
|
+ }
|
|
+ return;
|
|
+}
|
|
+
|
|
+static void board_led_activity_off(state_entry_t * pState)
|
|
+{
|
|
+ if (led_arr[pState->led].timer_running == 0) {
|
|
+ led_off(pState);
|
|
+ add_led_timer(pState);
|
|
+ led_arr[pState->led].timer_running = 1;
|
|
+ led_arr[pState->led].state = LED_BLINK_UP;
|
|
+ } else if (led_arr[pState->led].timer_running > 0xF0) {
|
|
+ led_arr[pState->led].state = LED_BLINK_UP;
|
|
+ led_arr[pState->led].pTimer->expires =
|
|
+ jiffies + HZ * (pState->param) / 1000;
|
|
+ led_arr[pState->led].param = pState->param;
|
|
+ led_arr[pState->led].pTimer->data = pState;
|
|
+ }
|
|
+ return;
|
|
+}
|
|
+
|
|
+static void board_led_link_flash(state_entry_t * pState)
|
|
+{
|
|
+ if (led_on(pState))
|
|
+ return;
|
|
+ if (led_arr[pState->led].timer_running == 0)
|
|
+ add_led_timer(pState);
|
|
+ else
|
|
+ led_arr[pState->led].param = pState->param;
|
|
+ led_arr[pState->led].timer_running = 0xFF;
|
|
+ led_arr[pState->led].state = LED_FLASH;
|
|
+ return;
|
|
+}
|
|
+
|
|
+static void led_timer_func(unsigned long data)
|
|
+{
|
|
+ state_entry_t *pState = NULL;
|
|
+ mod_entry_t *pMod = NULL;
|
|
+ unsigned int flags;
|
|
+
|
|
+ spin_lock_irqsave(&config_lock, flags);
|
|
+
|
|
+ pState = (state_entry_t *) data;
|
|
+
|
|
+ if (led_arr[pState->led].state == LED_BLINK_DOWN) {
|
|
+ led_arr[pState->led].timer_running = 0;
|
|
+ if (pState->mode == 2)
|
|
+ led_arr[pState->led].state = LED_OFF;
|
|
+ else
|
|
+ led_arr[pState->led].state = LED_ON;
|
|
+ } else if (led_arr[pState->led].state == LED_BLINK_UP) {
|
|
+ led_arr[pState->led].pTimer->expires =
|
|
+ jiffies + HZ * (led_arr[pState->led].param) / 1000;
|
|
+ led_arr[pState->led].pTimer->data = pState;
|
|
+ add_timer(led_arr[pState->led].pTimer);
|
|
+ if (pState->mode == 2) {
|
|
+ led_off(pState);
|
|
+ led_arr[pState->led].state = LED_BLINK_DOWN;
|
|
+ } else {
|
|
+ led_on(pState);
|
|
+ led_arr[pState->led].state = LED_BLINK_DOWN;
|
|
+ }
|
|
+ led_arr[pState->led].timer_running = 1;
|
|
+ } else if (led_arr[pState->led].state == LED_FLASH) {
|
|
+ led_arr[pState->led].pTimer->expires =
|
|
+ jiffies + HZ * (led_arr[pState->led].param) / 1000;
|
|
+ led_arr[pState->led].pTimer->data = pState;
|
|
+ add_timer(led_arr[pState->led].pTimer);
|
|
+
|
|
+ if (led_arr[pState->led].timer_running == 0xFF) {
|
|
+ led_off(pState);
|
|
+ led_arr[pState->led].timer_running--;
|
|
+ } else {
|
|
+ led_on(pState);
|
|
+ led_arr[pState->led].timer_running++;
|
|
+ }
|
|
+ spin_unlock_irqrestore(&config_lock, flags);
|
|
+ return;
|
|
+ } else if (led_arr[pState->led].state == LED_OFF) {
|
|
+ led_off(pState);
|
|
+ led_arr[pState->led].timer_running = 0;
|
|
+ } else if (led_arr[pState->led].state == LED_ON) {
|
|
+ led_on(pState);
|
|
+ led_arr[pState->led].timer_running = 0;
|
|
+ }
|
|
+ spin_unlock_irqrestore(&config_lock, flags);
|
|
+ return;
|
|
+}
|
|
+
|
|
+static ssize_t proc_read_led_fops(struct file *filp,
|
|
+ char *buf, size_t count, loff_t * offp)
|
|
+{
|
|
+ char *pdata = NULL;
|
|
+ int i = 0, j = 0, len = 0, totallen = 0;
|
|
+ char line[255];
|
|
+
|
|
+ if (*offp != 0)
|
|
+ return 0;
|
|
+
|
|
+ pdata = buf;
|
|
+ len += sprintf(line, "LEDS Registered for use are:");
|
|
+ for (i = 0; i < MAX_LED_ID; i++)
|
|
+ if (led_arr[i].led != NULL)
|
|
+ len += sprintf(&line[len], " %d ", i);
|
|
+ line[len++] = '\n';
|
|
+
|
|
+ copy_to_user(pdata, line, len);
|
|
+ pdata += len;
|
|
+ totallen += len;
|
|
+ len = 0;
|
|
+ len = sprintf(line, "USER MODULE INFORMATION:\n");
|
|
+ copy_to_user(pdata, line, len);
|
|
+ pdata += len;
|
|
+ totallen += len;
|
|
+ len = 0;
|
|
+ for (i = 0; i < MAX_MOD_ID; i++) {
|
|
+ if (modArr[i] != NULL) {
|
|
+ len = sprintf(line, " Module ID = %d \n", i);
|
|
+ copy_to_user(pdata, line, len);
|
|
+ pdata += len;
|
|
+ totallen += len;
|
|
+ len = 0;
|
|
+ for (j = 0; j < MAX_STATE_ID; j++) {
|
|
+ if (modArr[i]->states[j] != NULL) {
|
|
+ len = sprintf(line, " State = %d , Led = %d,", j,
|
|
+ modArr[i]->states[j]->led);
|
|
+ copy_to_user(pdata, line, len);
|
|
+ pdata += len;
|
|
+ totallen += len;
|
|
+
|
|
+ len = 0;
|
|
+ switch (modArr[i]->states[j]->mode) {
|
|
+ case 1:
|
|
+ len = sprintf(line, " Mode = OFF\n");
|
|
+ break;
|
|
+ case 2:
|
|
+ len = sprintf(line, " Mode = BLINK_ON , On Time(ms) = %d\n",
|
|
+ (unsigned int) modArr[i]->states[j]->
|
|
+ param);
|
|
+ break;
|
|
+ case 3:
|
|
+ len = sprintf(line, " Mode = BLINK_OFF , Off Time(ms) = %d\n",
|
|
+ (unsigned int) modArr[i]->states[j]->
|
|
+ param);
|
|
+ break;
|
|
+ case 4:
|
|
+ len = sprintf(line, " Mode = ON \n");
|
|
+ break;
|
|
+ case 5:
|
|
+ len = sprintf(line, " Mode = FLASH , Time Period(ms) = %d\n",
|
|
+ (unsigned int) modArr[i]->states[j]->
|
|
+ param);
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+
|
|
+ }
|
|
+ copy_to_user(pdata, line, len);
|
|
+ pdata += len;
|
|
+ totallen += len;
|
|
+
|
|
+ len = 0;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /* Return with configuration information for LEDs */
|
|
+ *offp = totallen;
|
|
+ return totallen;
|
|
+}
|
|
+
|
|
+static ssize_t proc_write_led_fops(struct file *filp, const char *buffer, size_t count, loff_t * offp)
|
|
+{
|
|
+ char *pdata = NULL, *ptemp = NULL;
|
|
+ char line[10], temp[10];
|
|
+ int i = 0;
|
|
+ int mod = 0xFFFF, state = 0xFFFF;
|
|
+ int flag = 0;
|
|
+
|
|
+ /* Check if this write is for configuring stuff */
|
|
+ if (*(int *) (buffer) == 0xFFEEDDCC) {
|
|
+ printk("<1>proc write:Calling Configuration\n");
|
|
+ config_led((unsigned long) (buffer + sizeof(int)));
|
|
+ return count;
|
|
+ }
|
|
+
|
|
+ if (count >= 10) {
|
|
+ printk("<1>proc write:Input too long,max length = %d\n", 10);
|
|
+ return count;
|
|
+ }
|
|
+ memset(temp, 0x00, 10);
|
|
+ memset(line, 0x00, 10);
|
|
+ copy_from_user(line, buffer, count);
|
|
+ line[count] = 0x00;
|
|
+ pdata = line;
|
|
+ ptemp = temp;
|
|
+ while (flag == 0) {
|
|
+ if (i > 10)
|
|
+ break;
|
|
+ if (((*pdata) >= '0') && ((*pdata) <= '9')) {
|
|
+ *ptemp = *pdata;
|
|
+ ptemp++;
|
|
+ } else if ((*pdata) == ',') {
|
|
+ *ptemp = 0x00;
|
|
+ flag = 1;
|
|
+ }
|
|
+ pdata++;
|
|
+ i++;
|
|
+ };
|
|
+ if (flag == 1)
|
|
+ mod = led_atoi(temp);
|
|
+ else
|
|
+ return count;
|
|
+
|
|
+ ptemp = temp;
|
|
+ *ptemp = 0x00;
|
|
+ flag = 0;
|
|
+ while (flag == 0) {
|
|
+ if (i > 10)
|
|
+ break;
|
|
+ if (((*pdata) >= '0') && ((*pdata) <= '9')) {
|
|
+ *ptemp = *pdata;
|
|
+ ptemp++;
|
|
+ } else if ((*pdata) == 0x00) {
|
|
+ *ptemp = 0x00;
|
|
+ flag = 1;
|
|
+ }
|
|
+ pdata++;
|
|
+ i++;
|
|
+ };
|
|
+ if (flag == 1)
|
|
+ state = led_atoi(temp);
|
|
+ else
|
|
+ return count;
|
|
+ if ((mod == 0xFFFF) || (state == 0xFFFF))
|
|
+ return count;
|
|
+ else
|
|
+ led_operation(mod, state);
|
|
+ return count;
|
|
+}
|
|
+
|
|
+static int config_led(unsigned long y)
|
|
+{
|
|
+ config_elem_t *pcfg = NULL;
|
|
+ char *pdata = NULL;
|
|
+ int i;
|
|
+ int length = 0, number = 0;
|
|
+ unsigned int flags;
|
|
+
|
|
+ spin_lock_irqsave(&config_lock, flags);
|
|
+
|
|
+ /* ioctl to configure */
|
|
+ length = *((int *) y);
|
|
+ pdata = (char *) y + sizeof(int);
|
|
+ number = (length - sizeof(int)) / sizeof(config_elem_t);
|
|
+ pcfg = (config_elem_t *) (pdata);
|
|
+
|
|
+ /* Check if an earlier configuration exists IF yes free it up */
|
|
+ free_memory();
|
|
+
|
|
+ for (i = 0; i < number; i++) {
|
|
+ /* If no structure has been allocated for the module do so */
|
|
+ if (modArr[pcfg->name] == NULL) {
|
|
+ printk("<1>module = %d\n", pcfg->name);
|
|
+ if (pcfg->name >= MAX_MOD_ID) {
|
|
+ printk
|
|
+ ("<1>Exiting Configuration: Module ID too large %d\n",
|
|
+ pcfg->name);
|
|
+ free_memory();
|
|
+ spin_unlock_irqrestore(&config_lock, flags);
|
|
+ return -1;
|
|
+ }
|
|
+ modArr[pcfg->name] = kmalloc(sizeof(mod_entry_t), GFP_KERNEL);
|
|
+ if (modArr[pcfg->name] == NULL) {
|
|
+ printk
|
|
+ ("<1>Exiting Configuration: Error in allocating memory\n");
|
|
+ free_memory();
|
|
+ spin_unlock_irqrestore(&config_lock, flags);
|
|
+ return -1;
|
|
+ }
|
|
+ memset(modArr[pcfg->name], 0x00, sizeof(mod_entry_t));
|
|
+ }
|
|
+
|
|
+ /* if no structure is allocated previously for this state
|
|
+ allocate a structure, if it's already there fill it up */
|
|
+ if (modArr[pcfg->name]->states[pcfg->state] == NULL) {
|
|
+ printk("<1>STATE = %d\n", pcfg->state);
|
|
+ if (pcfg->state >= MAX_STATE_ID) {
|
|
+ printk("<1>Exiting Configuration: State ID too large\n");
|
|
+ free_memory();
|
|
+ spin_unlock_irqrestore(&config_lock, flags);
|
|
+ return -1;
|
|
+ }
|
|
+ modArr[pcfg->name]->states[pcfg->state] =
|
|
+ kmalloc(sizeof(state_entry_t), GFP_KERNEL);
|
|
+ if (modArr[pcfg->name]->states[pcfg->state] == NULL) {
|
|
+ free_memory();
|
|
+ spin_unlock_irqrestore(&config_lock, flags);
|
|
+ return -1;
|
|
+ }
|
|
+ memset(modArr[pcfg->name]->states[pcfg->state], 0x00,
|
|
+ sizeof(state_entry_t));
|
|
+ }
|
|
+ /* Fill up the fields of the state */
|
|
+ if (pcfg->led >= MAX_LED_ID) {
|
|
+ printk("<1>led = %d\n", pcfg->led);
|
|
+ free_memory();
|
|
+ spin_unlock_irqrestore(&config_lock, flags);
|
|
+ return -1;
|
|
+ }
|
|
+ modArr[pcfg->name]->states[pcfg->state]->led = pcfg->led;
|
|
+ modArr[pcfg->name]->states[pcfg->state]->mode = pcfg->mode;
|
|
+ modArr[pcfg->name]->states[pcfg->state]->param = pcfg->param;
|
|
+ switch (pcfg->mode) {
|
|
+ case 1:
|
|
+ modArr[pcfg->name]->states[pcfg->state]->handler =
|
|
+ board_led_link_down;
|
|
+ break;
|
|
+ case 2:
|
|
+ case 3:
|
|
+ case 5:
|
|
+ if (pcfg->mode == 2)
|
|
+ modArr[pcfg->name]->states[pcfg->state]->handler =
|
|
+ board_led_activity_on;
|
|
+ else if (pcfg->mode == 3)
|
|
+ modArr[pcfg->name]->states[pcfg->state]->handler =
|
|
+ board_led_activity_off;
|
|
+ else
|
|
+ modArr[pcfg->name]->states[pcfg->state]->handler =
|
|
+ board_led_link_flash;
|
|
+ break;
|
|
+ case 4:
|
|
+ modArr[pcfg->name]->states[pcfg->state]->handler =
|
|
+ board_led_link_up;
|
|
+ break;
|
|
+ default:
|
|
+ printk("<1>Exiting Configuration: Unknown LED Mode\n");
|
|
+ free_memory();
|
|
+ spin_unlock_irqrestore(&config_lock, flags);
|
|
+ return -1;
|
|
+ }
|
|
+ pcfg++;
|
|
+ }
|
|
+ spin_unlock_irqrestore(&config_lock, flags);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+int __init led_init(void)
|
|
+{
|
|
+
|
|
+ /* Clear our memory */
|
|
+ memset(modArr, 0x00, sizeof(mod_entry_t *) * MAX_MOD_ID);
|
|
+ memset(led_arr, 0x00, sizeof(led_data_t *) * MAX_LED_ID);
|
|
+
|
|
+ /* Create spin lock for config data structure */
|
|
+ config_lock = SPIN_LOCK_UNLOCKED;
|
|
+
|
|
+#if 0
|
|
+ /* Create directory */
|
|
+ led_proc_dir = proc_mkdir("led_mod", NULL);
|
|
+ if (led_proc_dir == NULL)
|
|
+ goto out;
|
|
+#endif
|
|
+
|
|
+ /* Create adsl file */
|
|
+ led_file = create_proc_entry("led", 0777, NULL);
|
|
+ if (led_file == NULL)
|
|
+ goto led_file;
|
|
+
|
|
+ led_file->owner = THIS_MODULE;
|
|
+ led_file->proc_fops = &led_fops;
|
|
+
|
|
+ memset(modArr, 0x00, sizeof(mod_entry_t *) * MAX_MOD_ID);
|
|
+
|
|
+ /* Ron add for ADSL LED blink */
|
|
+ my_mode = 1;
|
|
+ my_led_init(GPIO_ADSL_ACT, 0, -1);
|
|
+ my_led_init(GPIO_ADSL_DOWN, 0, -1);
|
|
+ init_timer(&my_led_timer);
|
|
+ my_led_timer.function = my_led_blink_timer;
|
|
+ my_led_timer.data = 0;
|
|
+ my_led_timer.expires = jiffies + BLINK_SLOW;
|
|
+ add_timer(&my_led_timer);
|
|
+ /* Ron add for ADSL LED blink */
|
|
+ return 0;
|
|
+
|
|
+ led_file:
|
|
+ remove_proc_entry("led", NULL);
|
|
+ out:
|
|
+ return 0;
|
|
+
|
|
+}
|
|
+
|
|
+void led_exit(void)
|
|
+{
|
|
+ remove_proc_entry("led", NULL);
|
|
+}
|
|
+
|
|
+void led_operation(int mod, int state)
|
|
+{
|
|
+
|
|
+ unsigned int flags;
|
|
+
|
|
+ spin_lock_irqsave(&config_lock, flags);
|
|
+#if 1
|
|
+ /* Ron Add for ADSL LED blink */
|
|
+ //printk("mod==%d state==%d\n",mod,state);
|
|
+
|
|
+ if (mod == 1) {
|
|
+ switch (state) {
|
|
+ /* off */
|
|
+ case 1:
|
|
+ my_mode = 1;
|
|
+ my_blink_count = 0;
|
|
+ my_led_off(GPIO_ADSL_ACT, -1);
|
|
+ my_led_off(GPIO_ADSL_DOWN, -1);
|
|
+ break;
|
|
+ /* sync */
|
|
+ case 2:
|
|
+ if (my_mode == 1) {
|
|
+ my_mode = 2;
|
|
+ my_led_off(GPIO_ADSL_ACT, -1);
|
|
+ my_blink_count++;
|
|
+ }
|
|
+ break;
|
|
+ /* on */
|
|
+ case 3:
|
|
+ my_mode = 3;
|
|
+ my_blink_count = 0;
|
|
+ my_led_off(GPIO_ADSL_DOWN, -1);
|
|
+ my_led_on(GPIO_ADSL_ACT, -1);
|
|
+ break;
|
|
+ /* off */
|
|
+ case 4:
|
|
+ my_mode = 4;
|
|
+ my_led_off(GPIO_ADSL_DOWN, -1);
|
|
+ my_blink_count++;
|
|
+ break;
|
|
+ }
|
|
+ } /* Ron add for ADSL LED Blink */
|
|
+#endif
|
|
+ if ((mod >= MAX_MOD_ID) || (state >= MAX_STATE_ID)) {
|
|
+ spin_unlock_irqrestore(&config_lock, flags);
|
|
+ return;
|
|
+ }
|
|
+ if (modArr[mod] == NULL) {
|
|
+ spin_unlock_irqrestore(&config_lock, flags);
|
|
+ return;
|
|
+ }
|
|
+ if (modArr[mod]->states[state] == NULL) {
|
|
+ spin_unlock_irqrestore(&config_lock, flags);
|
|
+ return;
|
|
+ }
|
|
+ /* Call the function handler */
|
|
+ modArr[mod]->states[state]->handler(modArr[mod]->states[state]);
|
|
+
|
|
+ spin_unlock_irqrestore(&config_lock, flags);
|
|
+}
|
|
+
|
|
+void register_led_drv(int device, led_reg_t * pInfo)
|
|
+{
|
|
+ unsigned int flags;
|
|
+ struct timer_list *pTimer = NULL;
|
|
+
|
|
+ spin_lock_irqsave(&config_lock, flags);
|
|
+
|
|
+ led_arr[device].led = pInfo;
|
|
+ if (led_arr[device].led->init != 0x00)
|
|
+ led_arr[device].led->init(led_arr[device].led->param);
|
|
+ if (led_arr[device].led->offfunc != 0x00)
|
|
+ led_arr[device].led->offfunc(led_arr[device].led->param);
|
|
+
|
|
+ /* Create a timer for blinking */
|
|
+ pTimer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
|
|
+ init_timer(pTimer);
|
|
+ pTimer->function = led_timer_func;
|
|
+ pTimer->data = 0;
|
|
+ led_arr[device].pTimer = pTimer;
|
|
+ led_arr[device].timer_running = 0;
|
|
+
|
|
+ spin_unlock_irqrestore(&config_lock, flags);
|
|
+
|
|
+ return;
|
|
+}
|
|
+
|
|
+void deregister_led_drv(int device)
|
|
+{
|
|
+ unsigned int flags;
|
|
+
|
|
+ spin_lock_irqsave(&config_lock, flags);
|
|
+ led_arr[device].led = NULL;
|
|
+
|
|
+ if (led_arr[device].pTimer != NULL) {
|
|
+ del_timer(led_arr[device].pTimer);
|
|
+ kfree(led_arr[device].pTimer);
|
|
+ }
|
|
+ spin_unlock_irqrestore(&config_lock, flags);
|
|
+
|
|
+ return;
|
|
+}
|
|
+
|
|
+module_init(led_init);
|
|
+module_exit(led_exit);
|
|
+
|
|
+
|
|
+EXPORT_SYMBOL_NOVERS(led_init);
|
|
+EXPORT_SYMBOL_NOVERS(led_operation);
|
|
+EXPORT_SYMBOL_NOVERS(register_led_drv);
|
|
+EXPORT_SYMBOL_NOVERS(deregister_led_drv);
|
|
diff -urN linux.old/drivers/char/avalanche_led/Makefile linux.dev/drivers/char/avalanche_led/Makefile
|
|
--- linux.old/drivers/char/avalanche_led/Makefile 1970-01-01 01:00:00.000000000 +0100
|
|
+++ linux.dev/drivers/char/avalanche_led/Makefile 2005-07-11 02:42:24.191796312 +0200
|
|
@@ -0,0 +1,23 @@
|
|
+# File: drivers/char/avalanche_led/Makefile
|
|
+#
|
|
+# Makefile for the Linux LED device driver.
|
|
+#
|
|
+
|
|
+
|
|
+O_TARGET := avalanche_led.o
|
|
+obj-m := avalanche_led.o
|
|
+list-multi := avalanche_led.o
|
|
+
|
|
+EXTRA_CFLAGS := -I$(TOPDIR)/include/asm/ar7
|
|
+
|
|
+export-objs := ledmod.o
|
|
+
|
|
+avalanche_led-objs := ledmod.o
|
|
+
|
|
+include $(TOPDIR)/Rules.make
|
|
+
|
|
+avalanche_led.o: $(avalanche_led-objs)
|
|
+ $(LD) -r -o $@ $(avalanche_led-objs)
|
|
+
|
|
+clean:
|
|
+ rm -f core *.o *.a *.s
|
|
diff -urN linux.old/drivers/char/Config.in linux.dev/drivers/char/Config.in
|
|
--- linux.old/drivers/char/Config.in 2005-07-10 20:53:55.650624032 +0200
|
|
+++ linux.dev/drivers/char/Config.in 2005-07-10 20:50:43.556826000 +0200
|
|
@@ -133,6 +133,10 @@
|
|
fi
|
|
fi
|
|
fi
|
|
+if [ "$CONFIG_AR7" = "y" ]; then
|
|
+ bool 'Enable LED support' CONFIG_MIPS_AVALANCHE_LED
|
|
+fi
|
|
+
|
|
if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_ZORRO" = "y" ]; then
|
|
tristate 'Commodore A2232 serial support (EXPERIMENTAL)' CONFIG_A2232
|
|
fi
|
|
diff -urN linux.old/drivers/char/Makefile linux.dev/drivers/char/Makefile
|
|
--- linux.old/drivers/char/Makefile 2005-07-10 20:53:55.651623880 +0200
|
|
+++ linux.dev/drivers/char/Makefile 2005-07-10 20:50:43.556826000 +0200
|
|
@@ -190,6 +190,19 @@
|
|
obj-$(CONFIG_PCI) += keyboard.o $(KEYMAP)
|
|
endif
|
|
|
|
+#
|
|
+# Texas Intruments LED driver
|
|
+#
|
|
+ifeq ($(CONFIG_MIPS_AVALANCHE_LED),y)
|
|
+obj-$(CONFIG_MIPS_AVALANCHE_LED) += avalanche_led/avalanche_led.o
|
|
+subdir-$(CONFIG_MIPS_AVALANCHE_LED) += avalanche_led
|
|
+endif
|
|
+
|
|
+ifeq ($(CONFIG_MIPS_AVALANCHE_LED),m)
|
|
+obj-$(CONFIG_MIPS_AVALANCHE_LED) += avalanche_led/avalanche_led.o
|
|
+subdir-$(CONFIG_MIPS_AVALANCHE_LED) += avalanche_led
|
|
+endif
|
|
+
|
|
obj-$(CONFIG_HIL) += hp_keyb.o
|
|
obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
|
|
obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o
|
|
diff -urN linux.old/include/asm-mips/ar7/ledapp.h linux.dev/include/asm-mips/ar7/ledapp.h
|
|
--- linux.old/include/asm-mips/ar7/ledapp.h 1970-01-01 01:00:00.000000000 +0100
|
|
+++ linux.dev/include/asm-mips/ar7/ledapp.h 2005-07-10 20:50:43.557826000 +0200
|
|
@@ -0,0 +1,59 @@
|
|
+#ifndef __LED_APP__
|
|
+#define __LED_APP__
|
|
+
|
|
+#define CONF_FILE "/etc/led.conf"
|
|
+#define LED_PROC_FILE "/proc/led_mod/led"
|
|
+
|
|
+#define CONFIG_LED_MODULE
|
|
+
|
|
+#define MAX_MOD_ID 25
|
|
+#define MAX_STATE_ID 25
|
|
+#define MAX_LED_ID 25
|
|
+
|
|
+#define MOD_ADSL 1
|
|
+#define DEF_ADSL_IDLE 1
|
|
+#define DEF_ADSL_TRAINING 2
|
|
+#define DEF_ADSL_SYNC 3
|
|
+#define DEF_ADSL_ACTIVITY 4
|
|
+
|
|
+#define MOD_WAN 2
|
|
+#define DEF_WAN_IDLE 1
|
|
+#define DEF_WAN_NEGOTIATE 2
|
|
+#define DEF_WAN_SESSION 3
|
|
+
|
|
+#define MOD_LAN 3
|
|
+#define DEF_LAN_IDLE 1
|
|
+#define DEF_LAN_LINK_UP 2
|
|
+#define DEF_LAN_ACTIVITY 3
|
|
+
|
|
+#define MOD_WLAN 4
|
|
+#define DEF_WLAN_IDLE 1
|
|
+#define DEF_WLAN_LINK_UP 2
|
|
+#define DEF_WLAN_ACTIVITY 3
|
|
+
|
|
+#define MOD_USB 5
|
|
+#define DEF_USB_IDLE 1
|
|
+#define DEF_USB_LINK_UP 2
|
|
+#define DEF_USB_ACTIVITY 3
|
|
+
|
|
+#define MOD_ETH 6
|
|
+#define DEF_ETH_IDLE 1
|
|
+#define DEF_ETH_LINK_UP 2
|
|
+#define DEF_ETH_ACTIVITY 3
|
|
+
|
|
+typedef struct config_elem{
|
|
+ unsigned char name;
|
|
+ unsigned char state;
|
|
+ unsigned char mode;
|
|
+ unsigned char led;
|
|
+ int param;
|
|
+}config_elem_t;
|
|
+
|
|
+typedef struct led_reg{
|
|
+ unsigned int param;
|
|
+ void (*init)(unsigned long param);
|
|
+ void (*onfunc)(unsigned long param);
|
|
+ void (*offfunc)(unsigned long param);
|
|
+}led_reg_t;
|
|
+
|
|
+#endif
|