diff options
Diffstat (limited to 'linux/openslug-kernel-2.6.9/nslu2-io.c')
-rw-r--r-- | linux/openslug-kernel-2.6.9/nslu2-io.c | 263 |
1 files changed, 180 insertions, 83 deletions
diff --git a/linux/openslug-kernel-2.6.9/nslu2-io.c b/linux/openslug-kernel-2.6.9/nslu2-io.c index ad5bdc221d..53a3df7638 100644 --- a/linux/openslug-kernel-2.6.9/nslu2-io.c +++ b/linux/openslug-kernel-2.6.9/nslu2-io.c @@ -1,13 +1,16 @@ //============================================================================= // -// nslu2-io.c version 0.1.0 +// n2-io.c version 0.1.7 // Author: Karen Spearel <kas11 at tampabay.rr.com> // please report problems/bugs directly to the address above // +// Boilerplate to be added "real soon now"...it is and has always been GPL'ed per +// MODULE_LICENSE but is offered without warrantee of any sort..use at your own risk +// // NOTE: THIS IS INCOMPLETE. INCLUDED ONLY TO KEEP FROM BREAKING THE BUILD, // IT BEEPS AND SENDS A MESSAGE TO /proc/poweroff. EVENTUALLY IT -// WILL TALK TO THE n2_pbuttond DAEMON. EVENTUALLY THE LED DRIVER -// WILL TALK TO SOME USERLAND APP BUT ***NOT*** THE NASTY SETLEDS. +// WILL TALK TO THE n2_pbd DAEMON. EVENTUALLY THE LED DRIVER +// WILL TALK TO SOME USERLAND APP BUT ***NOT*** SET_LEDS. // //============================================================================= // GPIO Function State @@ -22,12 +25,9 @@ //============================================================================= // this driver is N2 specific and is purposely designed to do the minimum // necessary to provide the necessary services given the limited memory resources -// of the N2. As OpenSlug develops, addition features will be added as -// suggested by community leadership. +// of the N2. As OpenN2 develops, addition features will be added as +// suggested by the community. // -// The Userland apps such as SetLeds are just to crufty to bother with. -// This driver makes no attempt to do so...one day a Userland app will appear -// ...until then, this does very little. //============================================================================= #include <linux/config.h> @@ -53,39 +53,10 @@ #include <asm/hardware.h> #include <asm-arm/irq.h> #include <asm-arm/delay.h> +#include <asm-arm/signal.h> + -// Print kernel error -#define P_ERROR(args...) \ - printk(KERN_ERR DRV_NAME ": " args) -// Print kernel warning -#define P_WARN(args...) \ - printk(KERN_WARNING DRV_NAME ": " args) -// Print kernel notice -#define P_NOTICE(args...) \ - printk(KERN_NOTICE DRV_NAME ": " args) -// Print kernel info -#define P_INFO(args...) \ - printk(KERN_INFO DRV_NAME ": " args) -// Print verbose message. Enabled/disabled by 'log_level' param -#define P_VERBOSE(args...) \ - if (log_level >= 1) printk(DRV_NAME ": " args) -// Print debug message. Enabled/disabled by 'log_level' param -#define P_DEBUG(args...) \ - if (log_level >= 2) { \ - printk("%s: %s()\n", DRV_NAME, __FUNCTION__); \ - printk(args); } - -#ifdef DEBUG -// Print trace message -#define TRACE \ - if (log_level >= 2) printk("%s: %s(): line %d\n", \ - DRV_NAME, __FUNCTION__, __LINE__) -#else -// no trace -#define TRACE -#endif - -#define VERSION "0.1.1" +#define VERSION "0.1.7" #define N2RB_MAJOR 60 #define N2PB_MAJOR 61 @@ -121,22 +92,27 @@ #define PWR_OFF_STR "poweroff" -// ioctls -- THESE NEED TO BE PROPERLY DEFINED +// ioctls -- 'M" is used for sound cards...we don't got one so it seems safe -#define N2LM_ON 0 -#define N2LM_OFF 1 -#define N2LM_BLINK 2 -#define N2LM_ALT 3 -#define N2LM_ALL_ON 4 -#define N2LM_ALL_OFF 5 +#define N2BZ_BEEP_STOP _IO('M',0) //stop multi-beep at end of audible +#define N2BZ_BEEP _IO('M',1) //one beep at current defaults +#define N2BZ_BEEPS _IOW('M',3,long) //param beeps at current defaults +#define N2BZ_TONESET _IOW('M',4,long) //set tone: range is high=250 to low=2000 +#define N2BZ_ONTIME _IOW('M',5,long) //ontime for multi-beeps in jiffies +#define N2BZ_SILENTTIME _IOW('M',6,long) //offtime for multi-beeps in jiffies +#define N2BZ_REPEATCNT _IOW('M',7,long) //number of repeats for multi-beeps 0 = forever +#define N2BZ_COMBINED _IOW('M',8,long) //combine all params in a long + +#define N2LM_OFF _IOW('M',32,long) +#define N2LM_ON _IOW('M',33,long) +#define N2LM_BLINK _IOW('M',34,long) +#define N2LM_ALT _IOW('M',35,long) +#define N2LM_ALL_ON _IO('M',36) +#define N2LM_ALL_OFF _IO('M',37) #define PHYS_LEDS 4 #define BLINK_DELAY 25 -static int n2lm_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); - - - // OR Masks to turn these LEDs ON #define RS_RED_ON 0x00000001 //0b0000 0000 0000 0010 @@ -175,8 +151,12 @@ static int n2lm_ioctl(struct inode * inode, struct file * file, unsigned int cm #define LED_DISK2 3 #define LED_ALL 4 -static long init_jiffy = 0; //jiffies at init time -static int rb_presses = 0; //number of reset button presses +static unsigned long init_jiffy = 0; //jiffies at init time +static unsigned long rb_presses = 0; //number of reset button presses +static unsigned long ontime = 50; +static unsigned long offtime = 450; +static unsigned long bz_repeatcnt = 10; +static unsigned long tone = 1000; DECLARE_WAIT_QUEUE_HEAD(n2rb_waitq); DECLARE_WAIT_QUEUE_HEAD(n2pb_waitq); @@ -187,7 +167,7 @@ static struct timer_list n2lm_d1_timer; //drive 1 static struct timer_list n2lm_d2_timer; //drive 2 static struct timer_list n2rb_timer; static struct timer_list n2pb_timer; - +static struct timer_list n2bz_timer; //beeper //================================================================================================== // @@ -240,25 +220,21 @@ static void n2lm_timer_start(unsigned long led) switch(led) { case LED_RS_RED: n2lm_rsr_timer.expires = jiffies + BLINK_DELAY; - n2lm_rsr_timer.function = n2lm_rsr_handler; add_timer(&n2lm_rsr_timer); break; case LED_RS_GRN: n2lm_rsg_timer.expires = jiffies + BLINK_DELAY; - n2lm_rsg_timer.function = n2lm_rsg_handler; add_timer(&n2lm_rsg_timer); break; case LED_DISK1: n2lm_d1_timer.expires = jiffies + BLINK_DELAY; - n2lm_d1_timer.function = n2lm_d1_handler; add_timer(&n2lm_d1_timer); break; case LED_DISK2: - n2lm_d2_timer.expires = jiffies + BLINK_DELAY; - n2lm_d2_timer.function = n2lm_d2_handler; + n2lm_d2_timer.expires = jiffies + BLINK_DELAY; add_timer(&n2lm_d2_timer); break; @@ -306,7 +282,7 @@ static void n2lm_timer_stop_all(void) static void n2lm_ledon(unsigned long led) { - printk("ledon: %ld\n", led); + printk(KERN_DEBUG "ledon: %ld\n", led); switch (led) { case LED_RS_RED: @@ -421,7 +397,7 @@ static struct file_operations n2lm_fops = { // important should be haprepening. //================================================================================================== -static void n2_beep(int tone_delay, int duration) +static void n2_buzz(int tone_delay, int duration) { int i; @@ -437,6 +413,82 @@ static void n2_beep(int tone_delay, int duration) return; } +//================================================================================================= + +// this handles the buzzer duty cycle +static void n2bz_handler(unsigned long data) +{ + if (--bz_repeatcnt > 0) { //if just one beep left to do + n2bz_timer.expires = jiffies + ontime + offtime; //next timeout + add_timer(&n2bz_timer); //reinit timer + } + n2_buzz(tone/2, ontime); + printk(KERN_DEBUG "Count = %d\tOntime = %d\n", bz_repeatcnt, ontime); + return; +} + +//================================================================================================== + +static int n2bz_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long param) +{ + switch (cmd) { + case N2BZ_BEEP: + n2_buzz(tone/2, ontime); + break; + + case N2BZ_BEEP_STOP: + del_timer(&n2bz_timer); + break; + + case N2BZ_BEEPS: + if (param == 0) + bz_repeatcnt = 0xffffffff; + else + bz_repeatcnt = param; + n2bz_handler(0); + break; + + case N2BZ_TONESET: + if (param >= 250 && param <= 2000) + tone = param; + break; + + case N2BZ_ONTIME: + if (param > 4 && param < 201) + ontime = param; + break; + + case N2BZ_SILENTTIME: + if (param > ontime) //enforce a reasonable duty cycle + offtime = param; + else + offtime = ontime; + break; + + case N2BZ_REPEATCNT: + if (param == 0) + bz_repeatcnt = 0xffffffff; + else + bz_repeatcnt = param; + break; + + case N2BZ_COMBINED: + bz_repeatcnt = (param & 0xF0000000) >> 28; //repeat 1 - 16 + ontime = (param & 0x0FF00000) >> 20; //ontime 1 - 256 jiffies + offtime = (param & 0x000FFF00) >> 8; //offtime 1 - 4095 jiffies + tone = (param & 0x000000FF) << 4; //tone (1 - 255) * 16 + break; + + default: + break; + } + return NOERR; +} + +static struct file_operations n2bz_fops = { + .owner = THIS_MODULE, + .ioctl = n2bz_ioctl, +}; //================================================================================================== @@ -446,11 +498,12 @@ static irqreturn_t n2pb_handler (int irq, void *dev_id, struct pt_regs *regs) wake_up(&n2pb_waitq); remove_proc_entry(PWR_OFF_STR, NULL); //no parent - n2_beep(N2_BEEP_PITCH_MED, N2_BEEP_DUR_MED); + n2_buzz(N2_BEEP_PITCH_MED, N2_BEEP_DUR_MED); ret = create_proc_entry(PWR_OFF_STR, 0, NULL); + printk(KERN_DEBUG "cpe ret = %p\n", ret); -// WARNING: This is RUDE...it unconditionally pulls the power plug -// your data will be at risk...since this is just a test system +// WARNING: This is RUDE...it unconditionally pulls the power plug. +// Your data will be at risk...since this is just a test system // I am leaving it enabled...eventually userland needs to get the // message, do an orderly shutdown and use an ioctl or something in // /proc/powerdowm to actually have us pull the plug. @@ -458,7 +511,6 @@ static irqreturn_t n2pb_handler (int irq, void *dev_id, struct pt_regs *regs) *IXP4XX_GPIO_GPOER &= ~GPIO_PO_BM; // enable the pwr cntl gpio *IXP4XX_GPIO_GPOUTR |= GPIO_PO_BM; // do the deed - printk(KERN_DEBUG "cpe ret = %p\n", ret); return IRQ_HANDLED; } @@ -469,7 +521,7 @@ static irqreturn_t n2pb_handler (int irq, void *dev_id, struct pt_regs *regs) // int i; // // for (i = 0; i < rb_presses; i++) -// n2_beep(N2_BEEP_PITCH_MED,N2_BEEP_DUR_SHORT); +// n2_buzz(N2_BEEP_PITCH_MED,N2_BEEP_DUR_SHORT); // return; //} // @@ -477,23 +529,55 @@ static irqreturn_t n2pb_handler (int irq, void *dev_id, struct pt_regs *regs) // does nothing -- waiting for userland to define // This thing is sorta braindead...edge triggered IRQs aren't available in the drivers yet...so // we hang in a loop until the button is no longer pressed + +struct testr { + int ctl; + long param; +}; + static irqreturn_t n2rb_handler (int irq, void *dev_id, struct pt_regs *regs) { - unsigned long test[] = { 5,0, 0,0, 1,0, 0,1, 1,1, 0,2, 1,2, 0,3, 1,3, 2,0, 1,0, 2,1, 1,1, 2,2, 1,2, 2,3, 1,3, 5,0, 3,1, 5,0, 4,0 }; - - printk(KERN_DEBUG "Reset Entry IRQ=%d Presses= %d Jiffies= %08lx\n", irq, rb_presses, jiffies); + static struct testr test[] = { + N2LM_ALL_OFF,0, + N2LM_ON,0, + N2LM_OFF,0, + N2LM_ON,1, + N2LM_ALL_OFF,1, + N2LM_ON,2, + N2LM_OFF,2, + N2LM_ON,3, + N2LM_OFF,3, + N2LM_BLINK,0, + N2LM_OFF,0, + N2LM_BLINK,1, + N2LM_OFF,1, + N2LM_BLINK,2, + N2LM_OFF,2, + N2LM_BLINK,3, + N2LM_OFF,3, + N2LM_ALL_OFF,0, + N2LM_ALT,1, + N2LM_OFF,1, + N2LM_ALL_ON,0 + }; + + printk("Reset Entry IRQ =%d Presses = %d Jiffies = %08lx\tIO = %x\tIOW = %x\n", irq, rb_presses, jiffies, (int)_IO('M',rb_presses), (int)_IOW('M',rb_presses,long)); wake_up(&n2rb_waitq); while ((*IXP4XX_GPIO_GPINR & GPIO_RB_BM) == 0) ; //wait for button release - if (rb_presses == 21) { + if (rb_presses > 20) rb_presses = 0; - } - n2lm_ioctl(NULL,NULL,test[rb_presses*2], test[rb_presses*2+1]); - rb_presses++; - + tone = (rb_presses * 50) + 200; + ontime = (rb_presses*10) + 100; + offtime = 500 - (rb_presses*20); + printk("Ontime = %d\tOfftime = %d\tTone = %d\n",ontime,offtime,tone); + rb_presses++; + + n2bz_ioctl(NULL,NULL, N2BZ_BEEPS, rb_presses); + n2lm_ioctl(NULL,NULL, test[rb_presses].ctl, test[rb_presses].param); // if (rb_presses == 0) { // init_jiffy = jiffies; // init_timer (&n2rb_timer); @@ -518,6 +602,7 @@ static irqreturn_t n2rb_handler (int irq, void *dev_id, struct pt_regs *regs) printk(KERN_DEBUG "Reset Exit IRQ=%d Presses= %d Jiffies= %08lx\n", irq, rb_presses, jiffies); return IRQ_HANDLED; + } //================================================================================================== @@ -572,14 +657,21 @@ static void n2iom_initarch(void) init_timer(&n2lm_rsr_timer); init_timer(&n2lm_d1_timer); init_timer(&n2lm_d2_timer); - init_timer(&n2rb_timer); - init_timer(&n2pb_timer); +// init_timer(&n2rb_timer); +// init_timer(&n2pb_timer); + init_timer(&n2bz_timer); + n2lm_rsr_timer.function = n2lm_rsr_handler; + n2lm_rsg_timer.function = n2lm_rsg_handler; + n2lm_d2_timer.function = n2lm_d2_handler; + n2lm_d1_timer.function = n2lm_d1_handler; + n2bz_timer.function = n2bz_handler; + n2lm_rsr_timer.data = n2lm_rsg_timer.data = n2lm_d1_timer.data = n2lm_d2_timer.data = n2bz_timer.data = 0; *IXP4XX_GPIO_GPOER &= 0xfffffff0; //enable gpio 0-3 *IXP4XX_GPIO_GPOUTR |= 0x00000003; //turn off the leds *IXP4XX_GPIO_GPOUTR &= 0xfffffffc; n2lm_ledon(LED_ALL); - n2_beep(N2_BEEP_PITCH_MED, N2_BEEP_DUR_SHORT); + n2_buzz(N2_BEEP_PITCH_MED, N2_BEEP_DUR_SHORT); n2lm_ledoff(LED_ALL); return; @@ -589,24 +681,29 @@ static void n2iom_initarch(void) static int __init n2iom_init(void) { - printk(KERN_INFO "NSLU2 Misc I/O Driver Version %s (C) Karen Spearel\n", VERSION); + printk(KERN_INFO "OpenN2 Misc I/O Driver Version %s\n", VERSION); init_jiffy = jiffies; printk(KERN_DEBUG "init_jiffy=%ld\n",init_jiffy); n2iom_initarch(); - if (register_chrdev(N2RB_MAJOR, "n2_rb", &n2pb_fops) < NOERR) { + if (register_chrdev(N2RB_MAJOR, "n2_rbm", &n2pb_fops) < NOERR) { printk(KERN_DEBUG "Reset Button Major %d not available\n", N2RB_MAJOR); return -EBUSY; } - if (register_chrdev(N2PB_MAJOR, "n2_pb", &n2rb_fops) < NOERR) { + if (register_chrdev(N2PB_MAJOR, "n2_pbm", &n2rb_fops) < NOERR) { printk(KERN_DEBUG "Power Button Major %d not available\n", N2PB_MAJOR); return -EBUSY; } - if (register_chrdev(N2LM_MAJOR, "n2_leds", &n2lm_fops) < NOERR) { + if (register_chrdev(N2LM_MAJOR, "n2_ledm", &n2lm_fops) < NOERR) { printk(KERN_DEBUG "Led Manager Major %d not available\n", N2LM_MAJOR); return -EBUSY; } + if (register_chrdev(N2BZ_MAJOR, "n2_bzm", &n2bz_fops) < NOERR) { + printk(KERN_DEBUG "Buzzer Major %d not available\n", N2BZ_MAJOR); + return -EBUSY; + } + if (request_irq(N2RB_IRQ, &n2rb_handler, SA_INTERRUPT, "n2_rb", NULL) < NOERR) { printk(KERN_DEBUG "Reset Button IRQ %d not available\n", N2RB_IRQ); return -EIO; @@ -643,9 +740,9 @@ module_init (n2iom_init); module_exit (n2iom_exit); MODULE_AUTHOR("Karen Spearel <kas11@tampabay.rr.com>"); -MODULE_DESCRIPTION("NSLU2 Buttons/LEDs IO Driver"); +MODULE_DESCRIPTION("OpenN2 Buttons/LEDs IO Driver"); MODULE_LICENSE("GPL"); static int debug = 7; module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Debugging enabled = 1"); +MODULE_PARM_DESC(debug, "Debugging enabled = 8"); |