// Include the necessary header files here #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Declare some variables here // The physical base address for the custom device. // The size of memory allocated to the custom device. // This will be the virtual address used to point to custom // Modify next two statements as required/needed #define MYDEV_MAJOR 25 #define MYDEV_NAME "mydev" volatile void * devmap; volatile unsigned char * slvreg; volatile unsigned char * mastreg; // This is the routine called when a device file is read from. It is // fairly straightforward - it allocates space to hold data read from the // physical device, it reads the data from the device into the buffer, // it then copies that to the user's buffer. It returns the number of // bytes read. // Complete this function ssize_t custom_read(struct file *filp, char *buf, size_t count, loff_t *f_pos) { printk("custom_read\n"); unsigned long temp; temp = __raw_readl(????); //printk("out: 0x%x\n",temp & 0xff); return ????; } // This is the routine called when a device file is written to. Very // similar to the read routine. // Potentially useful functions: virt_to_bus(), __raw_writeb(), __raw_writel(), ssize_t custom_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos) { int ret; char str [128]; //You can use str as a place to temporarily store data unsigned long temp; printk("custom_write\n"); ret = copy_from_user(str, buf, count); if(ret != 0) { printk("copy from user failed!\n"); return -EFAULT; } /* Write to slave registers */ __raw_writel(????); /* Write to master registers */ __raw_writel(????); ... __raw_writel(????); return count; } // This is the routine called when the device is opened. // It doesn't have much to do since we are not keeping track of minor // numbers at this point. // This function is complete! int custom_open(struct inode *inode, struct file *filp) { printk("mydev:custom_open\n"); return 0; } // This is called when a device file is closed. Not much to do since // we are not keeping track of minor numbers at this point. // This function is complete! int custom_release(struct inode *inode, struct file *filp) { printk("mydev:custom_release\n"); return 0; } // The following structure is complete! struct file_operations custom_fops = { llseek: NULL, read: custom_read, write: custom_write, ioctl: NULL, open: custom_open, release: custom_release, mmap: NULL }; // This is the code that gets executed upon loading of the module. // It is called instead of init_module() because of a macro declared // at the bottom of the file. // Carefully note the difference between this and the open routine // above. When a module is loaded, nothing much should really be done // other than to do setup. It is when device files are opened, read, // written, and closed that the interesting stuff occurs. // The basic tasks for an init routine usually include: (1) do an // ioremap to get a VA for use in later talking to the module, (2) // enable interrupts for the device, and (3) registers itself to be // attached to a family of device files so that the driver will be // called later when those files are opened. // Hint: no additional lines of code needed for customInit(), simply fill in the ????s int customInit(void) { int ret; printk("mydev:customInit\n"); ret = register_chrdev(????); if (ret < 0) { printk("mydev: can't get major %d\n",MYDEV_MAJOR); return ret; } devmap = ioremap_nocache(????); slvreg = ????; mastreg = ????; return 0; } // This is the routine called when the module is unloaded. It // essentially un-does what the initialization code did. // Potentially useful functions: kfree(), iounmap(), unregister_chrdev() void customExit(void) { printk("mydev:customExit\n"); // Obvious hint-> read the description above! } // No edits needed below this line // Tell compiler to not export anything at all from this module for // use by others. EXPORT_NO_SYMBOLS; // Declare names of init and cleanup functions module_init(customInit); module_exit(customExit);