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;
}


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.*