root@jcjung:/dev# mknod sample c 250 10
sample_drv.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/mman.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/page.h>
#include "sample.h"
#define DEV_NAME "sample device"
#define DEV_MAJOR 0
#define DEV_ADDR 0x80000000
#define DEV_SIZE 0x8000
int sam_open(struct inode *inode, struct file *filp) {
int m,n;
m = MAJOR(inode->i_rdev);
n = MINOR(inode->i_rdev);
printk("Sample driver: open\n");
printk("--> major : %d, minor : %d\n", m, n);
return 0;
}
int sam_release(struct inode *inode, struct file *filp) {
printk("Sample driver: release\n");
return 0;
}
ssize_t sam_read(struct file *filp, char *buf, size_t cnt, loff_t *pos) {
char data[] = "12345678901234567890";
copy_to_user(buf, data, cnt);
printk("Sample Driver: read\n");
printk("-->buf: 0x%x, cnt: 0x%x\n", buf, cnt);
return 0x11;
}
ssize_t sam_write(struct file *filp, const char *buf, size_t cnt, loff_t *pos) {
char data[80];
copy_from_user(data, buf, cnt);
printk("Sample Driver: write\n");
printk("-->buf: 0x%x, cnt: 0x%x\n", buf, cnt);
printk("from user : %s\n", data);
return 0x22;
}
int sam_ioctl(struct inode *inode, struct file *flip, unsigned int cmd, unsigned long arg) {
int size;
int rval = 0;
int wval = 10;
if (_IOC_TYPE(cmd) != SAM_MAGIC) return -EINVAL;
if (_IOC_NR(cmd) >= SAM_IOCTL_MAX) return -EINVAL;
size = _IOC_SIZE(cmd);
if (size) {
if (_IOC_DIR(cmd) & _IOC_READ) {
if (access_ok(VERIFY_WRITE, (void*)arg, size))
return -EINVAL;
}
if (_IOC_DIR(cmd) & _IOC_WRITE) {
if (access_ok(VERIFY_READ, (void*)arg, size))
return -EINVAL;
}
}
switch(cmd) {
case SAM_INIT:
printk("-->SAM_INIT\n");
break;
case SAM_READ:
printk("-->SAM_READ\n");
copy_to_user((void*)arg, &wval, sizeof(int));
break;
case SAM_WRITE:
printk("-->SAM_WRITE\n");
copy_from_user(&rval, (void*)arg, sizeof(int));
printk("-->load val : %d\n", rval);
break;
case SAM_RDWR:
printk("-->SAM_RDWR\n");
break;
}
printk("Sample driver: ioctl\n");
printk("--> cmd: 0x%x, arg: 0x%x\n", cmd, arg);
return 0x33;
}
sample_app.c
Makefile
int sam_mmap(struct file *filp, struct vm_area_struct *vma) {
printk("Sample driver: mmap\n");
remap_pfn_range(vma, vma->vm_start, DEV_ADDR >> PAGE_SHIFT, DEV_SIZE, vma->vm_page_prot);
printk("--> start: 0x%x, end: 0x%x\n", vma->vm_start, vma->vm_end);
return 0;
}
int sam_poll(struct file *filep, struct poll_table_struct *pts) {
printk("Sample driver: poll\n");
return 0;
}
struct file_operations sam_fops = {
.open = sam_open,
.release = sam_release,
.read = sam_read,
.write = sam_write,
.ioctl = sam_ioctl,
.mmap = sam_mmap,
.poll = sam_poll,
};
int major;
int sample_drv_init(void) {
major = register_chrdev(DEV_MAJOR, DEV_NAME, &sam_fops);
printk("Sample driver register\n");
printk("-->major : %d\n", major);
return major;
}
void sample_drv_exit(void) {
unregister_chrdev(major, DEV_NAME);
return 0;
}
module_init(sample_drv_init);
module_exit(sample_drv_exit);
MODULE_LICENSE("GPL");
sample_app.c
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include "sample.h"
#define DEV_ADDR 0x80000000
#define DEV_SIZE 0x8000
int main() {
int fd;
int ret;
char rbuf[80];
char wbuf[] = "abcdefghijklmnopqrst";
int rval = 0;
int wval = 80;
char *addr;
fd = open("/dev/sample", O_RDWR);
printf("fd : %d\n", fd);
ret = read(fd, rbuf, 15);
printf("read ret : 0x%x\n", rbuf);
ret = write(fd, wbuf, 15);
printf("write ret : 0x%x\n", ret);
ret = ioctl(fd, SAM_INIT);
ret = ioctl(fd, SAM_READ, &rval);
printf("ioctl ret : 0x%x\n", ret);
ret = ioctl(fd, SAM_WRITE, &wval);
printf("ioctl ret : 0x%x\n", ret);
addr = (char*)mmap(0, DEV_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, DEV_ADDR);
printf("mmap ret : 0x%x\n", addr);
close(fd);
return 0;
}
Makefile
obj-m := sample_drv.o
KDIR := /lib/modules/$(shell uname -r)/build
#KDIR := /work/kernel
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
rm -f *.0
rm -f -f *.mod.*