rendered paste body1) module code
/* **************** LF339:1.0 s_09/lab6_misc.c **************** */
/*
* The code herein is: Copyright the Linux Foundation, 2011
*
* This Copyright is retained for the purpose of protecting free
* redistribution of source.
*
* URL: http://training.linuxfoundation.org
* email: trainingquestions@linuxfoundation.org
*
* The primary maintainer for this code is Jerry Cooperstein
* The CONTRIBUTORS file (distributed with this
* file) lists those known to have contributed to the source.
*
* This code is distributed under Version 2 of the GNU General Public
* License, which you should have received with the source.
*
*/
/*
* Using the misc API (full solution)
*
* Implement your fullest driver from above with the misc API.
*
* Once again a second solution is given which includes the same
* header file previously used.
*
@*/
#include <linux/module.h> /* for modules */
#include <linux/fs.h> /* file_operations */
#include <linux/uaccess.h> /* copy_(to,from)_user */
#include <linux/init.h> /* module_init, module_exit */
#include <linux/slab.h> /* kmalloc */
#include <linux/miscdevice.h>
#include <linux/mm.h>
#define MYDEV_NAME "mycdrv"
static char *ramdisk;
static size_t ramdisk_size = (16 * PAGE_SIZE);
static int my_map(struct file *file, struct vm_area_struct *vma)
{
unsigned long pfn, len;
printk("in my_map \n");
/* need to get the pfn for remap_pfn_range -- either of these two follwoing methods will work */
pfn = virt_to_phys(ramdisk + vma->vm_pgoff) >> PAGE_SHIFT;
printk("pfn %ld \n", pfn);
len = vma->vm_end - vma->vm_start;
printk("length = %ld \n", len);
if (remap_pfn_range(vma, vma->vm_start, pfn, len,
vma->vm_page_prot)) {
printk("remap failed \n");
return -EAGAIN;
}
printk("map is done \n");
return 0;
}
static int mycdrv_open(struct inode *inode, struct file *file)
{
static int counter = 0;
printk(KERN_INFO " attempting to open device: %s:\n", MYDEV_NAME);
printk(KERN_INFO " MAJOR number = %d, MINOR number = %d\n",
imajor(inode), iminor(inode));
counter++;
printk(KERN_INFO " successfully open device: %s:\n\n", MYDEV_NAME);
printk(KERN_INFO "I have been opened %d times since being loaded\n",
counter);
printk(KERN_INFO "ref=%d\n", module_refcount(THIS_MODULE));
return 0;
}
static int mycdrv_release(struct inode *inode, struct file *file)
{
printk(KERN_INFO " CLOSING device: %s:\n\n", MYDEV_NAME);
return 0;
}
static ssize_t
mycdrv_read(struct file *file, char __user * buf, size_t lbuf, loff_t * ppos)
{
int nbytes, maxbytes, bytes_to_do;
maxbytes = ramdisk_size - *ppos;
bytes_to_do = maxbytes > lbuf ? lbuf : maxbytes;
if (bytes_to_do == 0)
printk(KERN_INFO "Reached end of the device on a read");
nbytes = bytes_to_do - copy_to_user(buf, ramdisk + *ppos, bytes_to_do);
*ppos += nbytes;
printk(KERN_INFO "\n Leaving the READ function, nbytes=%d, pos=%d\n",
nbytes, (int)*ppos);
return nbytes;
}
static ssize_t
mycdrv_write(struct file *file, const char __user * buf, size_t lbuf,
loff_t * ppos)
{
int nbytes, maxbytes, bytes_to_do;
maxbytes = ramdisk_size - *ppos;
bytes_to_do = maxbytes > lbuf ? lbuf : maxbytes;
if (bytes_to_do == 0)
printk(KERN_INFO "Reached end of the device on a write");
nbytes =
bytes_to_do - copy_from_user(ramdisk + *ppos, buf, bytes_to_do);
*ppos += nbytes;
printk(KERN_INFO "\n Leaving the WRITE function, nbytes=%d, pos=%d\n",
nbytes, (int)*ppos);
return nbytes;
}
static loff_t mycdrv_lseek(struct file *file, loff_t offset, int orig)
{
loff_t testpos;
switch (orig) {
case SEEK_SET:
testpos = offset;
break;
case SEEK_CUR:
testpos = file->f_pos + offset;
break;
case SEEK_END:
testpos = ramdisk_size + offset;
break;
default:
return -EINVAL;
}
testpos = testpos < ramdisk_size ? testpos : ramdisk_size;
testpos = testpos >= 0 ? testpos : 0;
file->f_pos = testpos;
printk(KERN_INFO "Seeking to pos=%ld\n", (long)testpos);
return testpos;
}
static const struct file_operations mycdrv_fops = {
.owner = THIS_MODULE,
.read = mycdrv_read,
.write = mycdrv_write,
.open = mycdrv_open,
.release = mycdrv_release,
.llseek = mycdrv_lseek,
.mmap = my_map,
};
static struct miscdevice my_misc_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = MYDEV_NAME,
.fops = &mycdrv_fops,
};
static int __init my_init(void)
{
ramdisk = kzalloc(ramdisk_size, GFP_KERNEL);
printk("ramdisk %p \n", ramdisk);
if (misc_register(&my_misc_device)) {
printk(KERN_WARNING "Culdn't register device misc, "
"%d.\n", my_misc_device.minor);
return -EBUSY;
}
printk("ramdisk[0]=%d, ramdisk[1]=%d, ramdisk[8191]=%d, ramdisk[8192]=%d \n",
ramdisk[0], ramdisk[1], ramdisk[8191], ramdisk[8192]);
printk(KERN_INFO "\nSucceeded in registering character device %s\n",
MYDEV_NAME);
return 0;
}
static void __exit my_exit(void)
{
int i;
misc_deregister(&my_misc_device);
printk(KERN_INFO "\ndevice unregistered\n");
//printk("info in ramdisk %s \n", ramdisk);
printk("ramdisk[0]=%d, ramdisk[1]=%d, ramdisk[8191]=%d, ramdisk[8192]=%d \n",
ramdisk[0], ramdisk[1], ramdisk[8191], ramdisk[8192]);
kfree(ramdisk);
}
module_init(my_init);
module_exit(my_exit);
MODULE_AUTHOR("Jerry Cooperstein");
MODULE_LICENSE("GPL v2");
2) test code
/* **************** LF339:1.0 s_18/lab1_ioctl_data_test.c **************** */
/*
* The code herein is: Copyright the Linux Foundation, 2011
*
* This Copyright is retained for the purpose of protecting free
* redistribution of source.
*
* URL: http://training.linuxfoundation.org
* email: trainingquestions@linuxfoundation.org
*
* The primary maintainer for this code is Jerry Cooperstein
* The CONTRIBUTORS file (distributed with this
* file) lists those known to have contributed to the source.
*
* This code is distributed under Version 2 of the GNU General Public
* License, which you should have received with the source.
*
*/
/*
* Using ioctl's to pass data (User-space application)
@*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <string.h>
#include <sys/mman.h>
struct my_data {
int i;
long x;
char s[256];
} my_data;
#define MYIOC_TYPE 'k'
int main(int argc, char *argv[])
{
int fd, rc;
int MY_IOCTL;
int page_size;
int abc = 'M';
char *nodename = "/dev/mycdrv";
char *uptr = NULL;
/* open the device node */
if (argc > 1)
nodename = argv[1];
fd = open(nodename, O_RDWR);
printf(" I opened the device node, file descriptor = %d\n", fd);
page_size = getpagesize();
printf("page size = %d \n", page_size);
uptr = mmap(NULL, 2 * page_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
printf("user space ptr %p \n", uptr);
//memcpy(uptr,"SATHYA", 7);
printf("HAHA is %d \n", abc);
memset(uptr,abc,8193);
munmap(uptr, 2 * page_size);
close(fd);
}