/* * C-programmet eks16c.c for eksempel 16c i boka. Bruk Makefile.eks16c for å * kompilere. Dvs. du må endre navnet på Makefile.eks16c til bare * "Makefile". */ #include #include #include #include #include #include #include #include #include #include #include #define EKS16C_MINOR 200 #define EKS16C_BUFLEN 64*1024 /* Nødvendig dersom maskinen din kjører Linux versjon 2.0x eller eldre */ #if LINUX_VERSION_CODE < 0x020100 #define ioremap vremap #define iounmap vfree #define memcpy_touser memcpy_tofs #define memcpy_fromuser memcpy_fromfs #endif static char *kjerne_buffer; extern int printk(const char* fmt, ...); /* * Funksjonen som henter data brukerprogrammet sender til write() */ static int eks16c_write(struct inode *node, struct file *file, const char *buffer, int antall_tegn) { int feil; printk("eksempel16c: starter i write()\n"); feil = verify_area(VERIFY_READ, buffer, antall_tegn); if (feil) return feil; if (antall_tegn > EKS16C_BUFLEN) antall_tegn = EKS16C_BUFLEN; printk("eksempel16c: klarert for lesing fra brukerrom\n"); memcpy_fromuser(kjerne_buffer, buffer, antall_tegn); if (kjerne_buffer[0] == '1') { outb(1, 0x378); printk("eksempel16c: datalinje 0 satt til 1\n"); } else { outb(0, 0x378); printk("eksempel16c: datalinje 0 satt til 0\n"); } /* la filsystemet tro at det er snakk om en stor fil som vi skriver mere og mere data inn i */ file->f_pos += antall_tegn; return antall_tegn; } /* * Motsvarer open() # * MOD_INC_USE_COUNT indikerer at driveren er i bruk, slik at * den ikke kan fjernes (f.eks. med rmmod). */ static int eks16c_open(struct inode* ino, struct file* filep) { MOD_INC_USE_COUNT; printk("eksempel16c: i open()\n"); kjerne_buffer = (char *) vmalloc(EKS16C_BUFLEN); return 0; } /* * Motsvarer close() */ static void eks16c_close(struct inode* ino, struct file* filep) { printk("eksempel16c: i close()\n"); vfree(kjerne_buffer); MOD_DEC_USE_COUNT; } static struct file_operations eks16c_fops = { NULL, /* lseek */ NULL, /* read */ eks16c_write, NULL, /* readdir */ NULL, /* select */ NULL, /* ioctl */ NULL, /* mmap */ eks16c_open, eks16c_close, NULL, /* fsync */ NULL, /* fasync */ NULL, /* check_media_change */ NULL /* revalidate */ }; static struct miscdevice eks16c_dev = { EKS16C_MINOR, "eksempel16c", &eks16c_fops }; /* * Modul-spesifikk kode */ int init_module(void) { printk( "em.c: init_module called\n"); if (misc_register(&eks16c_dev)) { printk("eksempel16c: misc_register feilet, avslutter ...\n"); return -EIO; } else printk("eksempel16c: init_module lyktes\n"); return 0; } void cleanup_module(void) { printk("eksempel16c: cleanup_module kalt\n"); if (misc_deregister(&eks16c_dev) != 0) printk("eksempel16c: misc_deregister feilet\n"); else printk("eksempel16c: cleanup_module lyktes\n"); }