#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DEVICE_NAME "leds"
static unsigned long led_table [] = {
S3C2410_GPB(5),
S3C2410_GPB(6),
S3C2410_GPB(7),
S3C2410_GPB(8),
};
static unsigned int led_cfg_table [] = {
S3C2410_GPIO_OUTPUT,
S3C2410_GPIO_OUTPUT,
S3C2410_GPIO_OUTPUT,
S3C2410_GPIO_OUTPUT,
};
static int sbc2440_leds_ioctl(
struct inode *inode, // 用来记录文件的物理上的信息。因此,它和代表打开文件的file结构是不同的,一个文件可以对应多个file结构,但是只有一个inode结构。 重要成员:dev_t i_rdev 设备号
struct file *file, // 代表一个打开的文件,系统中每个打开的文件在内核空间中都有一个关联的struct file。他由内核在打开文件时创建,在文件关闭后释放 重要成员:loff_t f_ops 文件读写位置 struct file_operations *f_op
unsigned int cmd,
unsigned long arg)
{
switch(cmd) {
case 0:
case 1:
if (arg > 4) {
return -EINVAL;
}
s3c2410_gpio_setpin(led_table[arg], !cmd); //当cmd为1时,设置为零,led亮;当cmd为0时,设置为1,led灭。
return 0;
default:
return -EINVAL;
}
}
// 定义一个struct file_operations结构体
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.ioctl = sbc2440_leds_ioctl,
};
// 内核中使用struct miscdevice结构来描述一个混杂设备
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
};
static int __init dev_init(void)
{
int ret;
int i;
for (i = 0; i < 4; i++) {
/* 以s3c2410_gpio_cfgpin(S3C2410_GPB(5), S3C2410_GPIO_OUTPUT);为例子分析
* S3C2410_GPB(5)
* #define S3C2410_GPB(_nr) (S3C2410_GPIO_B_START + (_nr)) (gpio-nrs.h)
* S3C2410_GPIO_B_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_A), (枚举中定义的)
* #define S3C2410_GPIO_NEXT(__gpio) \
* ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 0)
* 则:S3C2410_GPIO_B_START = S3C2410_GPIO_A_START + S3C2410_GPIO_A_NR + CONFIG_S3C_GPIO_SPACE + 0
* S3C2410_GPIO_A_START = 0, (枚举中定义的)
* #define S3C2410_GPIO_A_NR (32)
* CONFIG_S3C_GPIO_SPACE在配置文件中定义为0
*
* 所以最后:S3C2410_GPB(5) = 0 + 32 + 0 + 0 + 5 = 37;
*
* S3C2410_GPIO_OUTPUT
* #define S3C2410_GPIO_OUTPUT (0xFFFFFFF1)
*
* void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
* 37 0xFFFFFFF1
* mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
* function &= 3; // function = 1;
* function <<= S3C2410_GPIO_OFFSET(pin)*2; function <<= ((100101) & (1111)) * 2 ; function = (1<<10)
* #define S3C2410_GPIO_OFFSET(pin) ((pin) & 31)
*
* con = __raw_readl(base + 0x00); // 将寄存器里的值读出来
* con &= ~mask; // 将值更改
* con |= function;
* __raw_writel(con, base + 0x00); // 将值写进去
*
* 将GPB5设置为输出
*
*/
s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
/*
* s3c2410_gpio_setpin(S3C2410_GPB(5), 0);为例子分析
* 37
* ocal_irq_save(flags);
dat = __raw_readl(base + 0x04);
dat &= ~(1 << offs);
dat |= to << offs;
__raw_writel(dat, base + 0x04);
*/
s3c2410_gpio_setpin(led_table[i], 0);
}
// 注册一个混杂设备驱动
ret = misc_register(&misc);
printk (DEVICE_NAME"\tinitialized\n");
return ret;
}
static void __exit dev_exit(void)
{
// 注销一个混杂设备驱动
misc_deregister(&misc);
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("FriendlyARM Inc.");
阅读(2851) | 评论(0) | 转发(0) |