#define MODULE #define __KERNEL__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // para get_ds(), set_fs() /* Prototipos de funciones de servicio del driver */ static int led_open(struct inode *, struct file *); static ssize_t led_read(struct file *file, char *buffer, size_t count, loff_t *pos); static int led_release(struct inode *inode, struct file *file); static ssize_t led_write(struct file *filp, const char *buf, size_t count, loff_t *pos); extern void *sys_call_table[]; static int (*mi_mknod)(const char *, int, int); static int (*mi_unlink)(const char *); static int (*mi_chmod)(const char * , mode_t); /* Registra cada función que será suministrada por el driver a los usuarios que lo utilicen */ static struct file_operations driver_fops = { owner: THIS_MODULE, open: led_open, release: led_release, read: led_read, write: led_write, }; static int estado=0; /* Función de inicialización del módulo */ int init_module(void) { mode_t mode; dev_t dev_id; mi_mknod=sys_call_table[__NR_mknod]; mi_unlink=sys_call_table[__NR_unlink]; mi_chmod=sys_call_table[__NR_chmod]; //request_region(0x60, 0x10, "led"); /* Registrar el driver con el major number 10 y el nombre "driver" */ if (register_chrdev(55, "led", &driver_fops)) return -EIO; set_fs( get_ds() ); mi_unlink( "/dev/led" ); mode = S_IFCHR; dev_id = MKDEV( 55, 0 ); mi_mknod( "/dev/led", mode, dev_id ); mode = 0666; mi_chmod( "/dev/led", mode ); return 0; } /* Función de descarga del módulo */ void cleanup_module(void) { //release_region(0x60,0x10); /* Deregistra el driver */ unregister_chrdev(55, "led"); } /* Esto es solo una prueba de demostración (la función imprime sólo un mensaje) */ static int led_open(struct inode *inode, struct file *file) { MOD_INC_USE_COUNT; printk("<1> Función que `open' el driver\n"); return 0; } static int led_release(struct inode *inode, struct file *file) { MOD_DEC_USE_COUNT; return 0; } static ssize_t led_read(struct file *file, char *buffer, size_t count, loff_t *pos) { // Detectar si ya hemos terminado if (*pos>0) return 0; // Hacer la salida e incrementar contador *buffer=estado; ++*pos; return 1; } static ssize_t led_write(struct file *filp, const char *buf, size_t count, loff_t *pos) { estado=buf[0]&7; while (inb(KBD_STATUS_REG) & KBD_STAT_IBF) mdelay(1); cli(); while (inb(KBD_STATUS_REG) & KBD_STAT_IBF) mdelay(1); // Salida: comando de set leds outb(KBD_CMD_SET_LEDS, KBD_DATA_REG); mdelay(1); while (inb(KBD_STATUS_REG) & KBD_STAT_IBF) mdelay(1); mdelay(1); // Salida: valor de los leds outb(estado, KBD_DATA_REG); mdelay(1); sti(); while (inb(KBD_STATUS_REG) & KBD_STAT_IBF) mdelay(1); mdelay(1); return 1; }