📄 led_sw.c
字号:
/* joy_wudan 2007/12/ */
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/devfs_fs_kernel.h>
#include <asm/irq.h>
#include <asm/frvirq.h>
#include <asm/uaccess.h>
#include <asm/smplock.h>
#include "LED_SW.h"
/*functions*/
void delay(void);
int init_module(void);
void cleanup_module(void);
static void sw_handler(int irq, void *dev_id, struct pt_regs *regs);
static int device_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
static inline void write_tarboio_register(volatile unsigned char *x, unsigned char v);
static inline u8 read_tarboio_register(volatile unsigned char *x);
static inline u16 read_tarboio_register_sw(volatile unsigned short *x);
static int device_release(struct inode *inode, struct file *file);
static int device_open(struct inode *inode, struct file *file);
static void sw_task(unsigned long data);
DECLARE_TASKLET(sw_tasklet,sw_task, 0);
static int Device_Open = 0,led_i=0,led_j=0,led_k=0,led_l=0,led_m=0;
static struct file_operations fops = {
ioctl : device_ioctl,
open: device_open,
release: device_release,
};
int init_module(void)
{
register_chrdev(Major, DEVICE_NAME, &fops);
request_irq(IRQ_SW2_6,sw_handler,SA_INTERRUPT, "fr400_sw", NULL);
request_irq(IRQ_SW9 ,sw_handler,SA_INTERRUPT, "fr400_sw", NULL);
request_irq(IRQ_SW8 ,sw_handler,SA_INTERRUPT, "fr400_sw", NULL);
disable_irq(IRQ_SW2_6);
disable_irq(IRQ_SW9);
disable_irq(IRQ_SW8);
return 0;
}
void cleanup_module(void)
{
unregister_chrdev(Major, DEVICE_NAME);
free_irq(IRQ_SW2_6,NULL);
free_irq(IRQ_SW9,NULL);
free_irq(IRQ_SW8,NULL);
}
static int device_open(struct inode *inode, struct file *file)
{
return 0;
}
static int device_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
unsigned char temp;
unsigned short sw;
switch(cmd)
{
/* cmd for write :*/
case LED8_SET:
temp=read_tarboio_register(LED_ADDR);
write_tarboio_register(LED_ADDR,temp);
break;
case LED7_SET:
temp=read_tarboio_register(LED_ADDR);
write_tarboio_register(LED_ADDR,(temp|0x02));
break;
case LED6_SET:
temp=read_tarboio_register(LED_ADDR);
write_tarboio_register(LED_ADDR,(temp|0x04));
break;
temp=read_tarboio_register(LED_ADDR);
write_tarboio_register(LED_ADDR,(temp|0x08));
break;
case LED4_SET:
temp=read_tarboio_register(LED_ADDR);
write_tarboio_register(LED_ADDR,(temp|0x10));
break;
case LED3_SET:
temp=read_tarboio_register(LED_ADDR);
write_tarboio_register(LED_ADDR,(temp|0x20));
break;
case LED2_SET:
temp=read_tarboio_register(LED_ADDR);
write_tarboio_register(LED_ADDR,(temp|0x40));
case LED_CLR:
write_tarboio_register(LED_ADDR,0x00);
break;
case LED_SET:
write_tarboio_register(LED_ADDR,0x7F);
break;
case SW_READ:
sw=read_tarboio_register_sw(SW_ADDR);
*(unsigned short *)arg=((~sw)& 0x7FFF);
break;
case DISABLE_IRQ:
disable_irq(IRQ_SW2_6);
disable_irq(IRQ_SW9);
disable_irq(IRQ_SW8);
break;
case ENABLE_IRQ:
enable_irq(IRQ_SW2_6);
enable_irq(IRQ_SW9);
enable_irq(IRQ_SW8);
break;
default:printk(" LED: invalid command.\n");
return -EINVAL;
break;
}
}
static int device_release(struct inode *inode, struct file *file)
{
Device_Open --; /* We're now ready for our next caller */
return 0;
}
static void sw_handler(int irq, void *dev_id, struct pt_regs *regs)
{
disable_irq(IRQ_SW2_6);
disable_irq(IRQ_SW9);
disable_irq(IRQ_SW8);
tasklet_schedule(&sw_tasklet);
}
static void sw_task(unsigned long data)
{
static int led_i=0,led_j=0,led_k=0,led_l=0,led_m=0;
unsigned short sw;
unsigned char temp;
sw=read_tarboio_register_sw(SW_ADDR);
sw=((~sw)& 0x7FFF) ;
switch (sw)
{
case 0x4000 :
if((led_i%2)==0)
{
temp=read_tarboio_register(LED_ADDR);
write_tarboio_register(LED_ADDR,(temp|0x01));
}
else
{
temp=read_tarboio_register(LED_ADDR);
write_tarboio_register(LED_ADDR,(temp&0xFE));
}
led_i++;
break;
case 0x2000:
if((led_j%2)==0)
{
temp=read_tarboio_register(LED_ADDR);
write_tarboio_register(LED_ADDR,(temp|0x02));
}
else
{
temp=read_tarboio_register(LED_ADDR);
write_tarboio_register(LED_ADDR,(temp&0xFD));
}
led_j++;
break;
case 0x1000:
if((led_k%2)==0)
{
temp=read_tarboio_register(LED_ADDR);
write_tarboio_register(LED_ADDR,(temp|0x04));
}
else
{
temp=read_tarboio_register(LED_ADDR);
write_tarboio_register(LED_ADDR,(temp&0xFB));
}
led_k++;
break;
case 0x0800:
if((led_l%2)==0)
{
temp=read_tarboio_register(LED_ADDR);
write_tarboio_register(LED_ADDR,(temp|0x08));
}
else
{
temp=read_tarboio_register(LED_ADDR);
write_tarboio_register(LED_ADDR,(temp&0xF7));
}
led_l++;
break;
case 0x0400:
if((led_m%2)==0)
{
temp=read_tarboio_register(LED_ADDR);
write_tarboio_register(LED_ADDR,(temp|0x10));
}
else
{
temp=read_tarboio_register(LED_ADDR);
write_tarboio_register(LED_ADDR,(temp&0xEF));
}
led_m++;
break;
default:
printk("unsupported sw\n");
}
delay();
enable_irq(IRQ_SW2_6);
enable_irq(IRQ_SW9);
enable_irq(IRQ_SW8);
}
static inline u8 read_tarboio_register(volatile unsigned char *x)
{
unsigned char v;
v = *((volatile unsigned char *)(x));
__asm__ __volatile__("membar");
return v;
}
static inline u16 read_tarboio_register_sw(volatile unsigned short *x)
{
unsigned short v;
v = *((volatile unsigned short *)(x));
__asm__ __volatile__("membar");
return v;
}
static inline void write_tarboio_register(volatile unsigned char*x, unsigned char v)
{
*((volatile unsigned char*)(x)) = (v);
__asm__ __volatile__("membar");
}
void delay(void)
{
int i=0,j=0,a;
for(i=0;i<3000;i++)
{
for(j=0;j<1000;j++)
{
a=10/10;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -