/* Compile and load the GFN driver module by using the commands, cc -Wall -O2 -c -DMODULE -D__KERNEL__ -o gfn.o gfn2.c rmmod gfn - to remove the existing one insmod gfn.o */ #include #include #include #include #define GFN_MAJOR 60 #define BASE 0x378 #define DATAPORT (BASE) #define STATPORT (BASE+1) #define CONPORT (BASE+2) #define IRQENBIT 0x10 #define IRQBIT 0x40 // The ioctl commads #define GETSTATUS 1000 #define SETCONPORT 1001 int gfn_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { u8 data; switch(cmd) { case GETSTATUS: data = inb(STATPORT); printk("IOCTL GETSTATUS: to user %x hex\n",data); if(copy_to_user((u8 *) arg, &data, 1)) return -EFAULT; break; case SETCONPORT: if(copy_from_user(&data, (u8 *) arg, 1)) return -EFAULT; printk("IOCTL SETCONPORT: from user %x hex\n",data); outb(data, CONPORT); break; } return 0; } static ssize_t gfn_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { u8 data; if (copy_from_user(&data, buf, sizeof(data))) return -EFAULT; printk("Data from user %x hex\n", data); outb(data, DATAPORT); return 0; } static ssize_t gfn_read(struct file *file, char *buffer, size_t count, loff_t *ppos) { u8 data; data = inb(STATPORT); // read the printer status port printk("data = %x hex\n", data); // for debugging only // transfer data from kernel address space to user address space if(copy_to_user( buffer, &data, sizeof(u8))) return -EFAULT; return 0; } static int gfn_open(struct inode * inode, struct file * file) { printk("GFN open: Usage = %d\n", MOD_IN_USE); MOD_INC_USE_COUNT; return 0; } static int gfn_release(struct inode * inode, struct file * file) { MOD_DEC_USE_COUNT; printk("GFN release: Usage = %d\n", MOD_IN_USE); return 0; } struct file_operations gfn_fops = { owner: THIS_MODULE, open: gfn_open, release: gfn_release, write: gfn_write, read: gfn_read, ioctl: gfn_ioctl }; int init_module(void) { if (register_chrdev(GFN_MAJOR,"gfn",&gfn_fops)) { printk("gfn: Failed to get major %d\n", GFN_MAJOR); return -EIO; } printk("Registered device gfn: major %d\n",GFN_MAJOR); return 0; } void cleanup_module(void) { printk("Freed resources: MOD_IN_USE = %d\n", MOD_IN_USE); unregister_chrdev(GFN_MAJOR,"gfn"); printk("Unregistered device gfn: major %d\n",GFN_MAJOR); }