/* Definiciones e includes necesarios para los drivers */ #define MODULE #define __KERNEL__ #include #include #include /* printk() */ #include /* kmalloc() */ #include /* everything... */ #include /* error codes */ #include /* size_t */ #include #include /* O_ACCMODE */ #include #include /* cli(), *_flags */ #include /* copy_from/to_user */ #include /* inb, outb */ /* Declaracion de funciones de puertopar.c */ int puertopar_open(struct inode *inode, struct file *filp); int puertopar_release(struct inode *inode, struct file *filp); ssize_t puertopar_read(struct file *filp, char *buf, size_t count, loff_t *f_pos); ssize_t puertopar_write(struct file *filp, char *buf, size_t count, loff_t *f_pos); void cleanup_module(void); /* Estructura que declara las funciones tipicas */ /* de acceso a ficheros */ struct file_operations puertopar_fops = { read: puertopar_read, write: puertopar_write, open: puertopar_open, release: puertopar_release }; /* Variables globales del driver */ /* Numero mayor */ int puertopar_major = 61; /* Variable de control para la reserva */ /* de memoria del puerto paralelo*/ int port; int init_module(void) { int result; /* Registrando dispositivo */ result = register_chrdev(puertopar_major, "puertopar", &puertopar_fops); if (result < 0) { printk( "<1>puertopar: no puedo obtener numero mayor %d\n", puertopar_major); return result; } /* Registrando puerto */ port = check_region(0x378, 1); if (port) { printk("<1>puertopar: no puedo reservar 0x378\n"); result = port; goto fallo; } request_region(0x378, 1, "puertopar"); printk("<1>Insertando modulo\n"); return 0; fallo: cleanup_module(); return result; } void cleanup_module(void) { /* Liberamos numero mayor */ unregister_chrdev(puertopar_major, "memoria"); /* Liberando puerto */ if (!port) { release_region(0x378,1); } printk("<1>Quitando modulo\n"); } int puertopar_open(struct inode *inode, struct file *filp) { /* Aumentamos la cuenta de uso */ MOD_INC_USE_COUNT; /* Exito */ return 0; } int puertopar_release(struct inode *inode, struct file *filp) { /* Decrementamos la cuenta de uso */ MOD_DEC_USE_COUNT; /* Exito */ return 0; } ssize_t puertopar_read(struct file *filp, char *buf, size_t count, loff_t *f_pos) { /* Buffer para leer el dispositivo */ char puertopar_buffer; /* Leyendo del puerto */ puertopar_buffer = inb(0x378); /* Transferimos datos al espacio de usuario */ copy_to_user(buf,&puertopar_buffer,1); /* Cambiamos posición de lectura segun convenga */ if (*f_pos == 0) { *f_pos+=1; return 1; } else { return 0; } } ssize_t puertopar_write( struct file *filp, char *buf, size_t count, loff_t *f_pos) { char *tmp; /* Buffer para leer el dispositivo */ char puertopar_buffer; tmp=buf+count-1; copy_from_user(&puertopar_buffer,tmp,1); /* Escribiendo al puerto */ outb(puertopar_buffer,0x378); return 1; }