《精通linux设备驱动程序开发》第五章-字符设备驱动程序
==================================================================
注意:在官网源程序中,在/dev/下建立 设备节点,这句话有问题,导致
-
device_create(cmos_class, NULL, MKDEV(MAJOR(cmos_dev_number), i),
- "cmos%d", i);
我在建立节点的时候,只能建立 /dev/cmos0 而不能建立/dev/cmos1
-
#include <linux/init.h>
-
#include <linux/kernel.h>
-
#include <linux/module.h>
-
#include <linux/fs.h>
-
#include <linux/cdev.h>
-
#include <linux/types.h>
-
#include <linux/slab.h>//kmalloc()
-
#include <asm/uaccess.h>//copy_from_user
-
#include <linux/pci.h>
-
-
#define NUM_CMOS_BANKS 2
-
-
/* Per-device (per-bank) structure */
-
struct cmos_dev {
-
unsigned short current_pointer; /* Current pointer within the
-
bank */
-
unsigned int size; /* Size of the bank */
-
int bank_number; /* CMOS bank number */
-
struct cdev cdev; /* The cdev structure */
-
char name[10]; /* Name of I/O region */
-
/* ... */ /* Mutexes, spinlocks, wait
-
queues, .. */
-
};
-
struct cmos_dev *cmos_devp[NUM_CMOS_BANKS];
-
-
static struct file_operations cmos_fops = {
-
.owner = THIS_MODULE, /* Owner *///<linux/fs.h>
-
#if 0
-
.open = cmos_open, /* Open method */
-
.release = cmos_release, /* Release method */
-
.read = cmos_read, /* Read method */
-
.write = cmos_write, /* Write method */
-
.llseek = cmos_llseek, /* Seek method */
-
.ioctl = cmos_ioctl, /* Ioctl method */
-
#endif
-
};
-
-
static dev_t cmos_dev_number; /* Allotted device number */
-
struct class *cmos_class; /* Tie with the device model */
-
-
#define CMOS_BANK_SIZE (0xFF*8)
-
#define DEVICE_NAME "ywxcmos"
-
#define CMOS_BANK0_INDEX_PORT 0x70
-
#define CMOS_BANK0_DATA_PORT 0x71
-
#define CMOS_BANK1_INDEX_PORT 0x72
-
#define CMOS_BANK1_DATA_PORT 0x73
-
-
-
unsigned char addrports[NUM_CMOS_BANKS] = {CMOS_BANK0_INDEX_PORT,
-
CMOS_BANK1_INDEX_PORT,};
-
unsigned char dataports[NUM_CMOS_BANKS] = {CMOS_BANK0_DATA_PORT,
-
CMOS_BANK1_DATA_PORT,};
-
-
static int __init cmos_init(void)
-
{
-
int i;
-
int ret;
-
if(alloc_chrdev_region(&cmos_dev_number, 0,2, DEVICE_NAME) < 0) // register 2 dev
-
{
-
printk(KERN_DEBUG "Can't register device\n");
-
return -1;
-
}
-
//sys/class/ywxcmos_class/
-
cmos_class = class_create(THIS_MODULE, "ywxcmos_class");
-
-
-
for(i = 0; i < NUM_CMOS_BANKS; i++)
-
{
-
cmos_devp[i] = kmalloc(sizeof(struct cmos_dev), GFP_KERNEL);
-
if (!cmos_devp[i])
-
{
-
printk("Bad Kmalloc\n");
-
return -ENOMEM;
-
}
-
-
sprintf(cmos_devp[i]->name, "ywxcmos%d", i);
-
-
//proc/ioports cmoso cmos1
-
release_region(addrports[i], 2);////////add me
-
-
if(!(request_region(addrports[i], 2, cmos_devp[i]->name)))
-
{
-
printk("ywxcmos: I/O port 0x%x is not free.\n", addrports[i]);
-
return -EIO;
-
}
-
-
cmos_devp[i]->bank_number = i;
-
cdev_init(&cmos_devp[i]->cdev, &cmos_fops);
-
cmos_devp[i]->cdev.owner = THIS_MODULE;
-
ret = cdev_add(&cmos_devp[i]->cdev, (cmos_dev_number + i), 1);
-
if(ret)
-
{
-
printk("Bad cdev\n");
-
return ret;
-
}
-
}
-
-
//dev/ywxcmos0 /dev/ywxcmos1
-
device_create(cmos_class, NULL, MKDEV(MAJOR(cmos_dev_number), 0),NULL,"ywxcmos0");
-
device_create(cmos_class, NULL, MKDEV(MAJOR(cmos_dev_number), 1),NULL,"ywxcmos1");
-
printk("ywxCMOS Driver Initialized.\n");
-
return 0;
-
}
-
-
/* Driver Exit */
-
static void __exit cmos_cleanup(void)
-
{
-
int i;
-
-
printk("exit starting...\n");
-
/* Release the major number */
-
unregister_chrdev_region((cmos_dev_number), NUM_CMOS_BANKS);
-
-
/* Release I/O region */
-
for(i=0; i<NUM_CMOS_BANKS; i++)
-
{
-
device_destroy (cmos_class, MKDEV(MAJOR(cmos_dev_number), i));
-
release_region(addrports[i], 2);
-
cdev_del(&cmos_devp[i]->cdev);
-
kfree(cmos_devp[i]);
-
}
-
-
/* Destroy cmos_class */
-
class_destroy(cmos_class);
-
printk("exit finished..\n");
-
}
-
-
MODULE_LICENSE("GPL");
-
-
module_init(cmos_init);
- module_exit(cmos_cleanup);
显示测试:
-
ywx@ywx:~/Desktop/module/jingtong/cmos$ sudo insmod ./cmos.ko
-
ywx@ywx:~/Desktop/module/jingtong/cmos$ ls /dev/ywxcmos*
-
/dev/ywxcmos0 /dev/ywxcmos1 在/dev/下新建了设备节点
-
ywx@ywx:~/Desktop/module/jingtong/cmos$ cat /proc/devices | grep ywx
-
250 ywxcmos 这是动态分配的主设备号
-
ywx@ywx:~/Desktop/module/jingtong/cmos$ ls /sys/class/ywxcmos_class/
-
ywxcmos0 ywxcmos1在/sys/class/下新建了 ywxcmos_class 设备类
-
ywx@ywx:~/Desktop/module/jingtong/cmos$ grep cmos /proc/ioports
-
0070-0071 : ywxcmos0 io分配的内存 request_region
-
0072-0073 : ywxcmos1
-
ywx@ywx:~/Desktop/module/jingtong/cmos$ sudo rmmod cmos
-
ywx@ywx:~/Desktop/module/jingtong/cmos$ dmesg | tail -5
-
[ 521.275943] [<c0217d85>] ? sys_close+0x75/0xc0
-
[ 521.275947] [<c05cc204>] syscall_call+0x7/0xb
-
[ 521.282050] ywxCMOS Driver Initialized.
-
[ 610.405604] exit starting...
- [ 610.410214] exit finished..
==================================================================
参考资料:
精通linux设备驱动程序开发 笔记之九
精通linux设备驱动程序开发官网
listing05.1.html