1) 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 /* for modules */ #include /* file_operations */ #include /* copy_(to,from)_user */ #include /* module_init, module_exit */ #include /* kmalloc */ #include #include #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 #include #include #include #include #include #include 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); }