1 E/S Driver Impresora –Airam Godoy Hernández –Jose Yeray Suárez Perdomo.

Slides:



Advertisements
Presentaciones similares
Introducción Principios del Software E/S Principios del Hardware E/S
Advertisements

Capítulo I Gestión de E/S 1.- Gestión de E/S 2.- Hardware de E/S 3.- Software de E/S.
IBD Curso 2007 Clase 2.
Tema #10. FICHEROS.
Unidad 15 Características de C++ no relacionadas con el DOO.
DATSI, FI, UPM José M. Peña Programación en C DATSI, FI, UPM José M. Peña Programación en C.
Buffer Cache Yeray Tejera León Armiche Alonso Jiménez
Tabla de Contenido Concurrencia.
Memoria Compartida Llave de acceso Segmento Compartido 1234 estructura
Arquitectura de Sistema de E/S
FICHEROS.
Programación en C para electrónica
PROGRAMACIÓN PARALELA Tema 5: Análisis de algoritmos paralelos
Unidad 5 Listas Enlazadas Bibliografía: Algoritmos y Estructuras de datos de Aguilar y Martinez. Unidad 9 Autor: Ing Rolando Simon Titiosky.
PROTOCOLOS Y ESTANDARES DE RED
Comunicación y sincronización de procesos
Programación, Algoritmos y Estructuras de Datos
INFORMATICA I Arreglos 1 CLASE 17.
Informática II Prof. Dr. Gustavo Patiño MJ
Programación en C (Segunda Parte) DATSI, FI, UPM José M. Peña
ENTRADA / SALIDA 1.
Comunicación entre procesos en Linux
Tareas en Linux · TASK_RUNNING (0): Indica que el proceso en cuestión se está ejecutando o listo para ejecutarse. En este segundo caso, el proceso dispone.
ALGORÍTMICA Dpto. Ingeniería de Sistemas y Automática
Tema II Unidad de memoria. 2 Unidad de memoria 2.1 Definiciones y conceptos básicos Localización Capacidad Unidad de transferencia
Programación en Lenguaje Ensamblador.
Comunicación y sincronización de procesos Comunicación por tuberías.
Planificación de la Información.
Entrada / salida digital con ccs
PROGRAMACIÓN ORIENTADA A OBJETOS
Llamadas al Sistema EXIT y WAIT
MINIX FILE SYSTEM Cátedra: Diseño e Implementación de Sistemas Operativos UTN-FRSF Tomado de: Sistemas Operativos Diseño e Implementación - A.S.Tanenbaum.
¿Qué es un PUNTERO?: Un puntero es un objeto que apunta a otro objeto. Es decir, una variable cuyo valor es la dirección de memoria de otra variable. No.
Archivos Contenido: Archivos de Texto Archivos de Acceso Aleatorio
Programación I Teoría VI: Recursividad
POO Java Módulo 3 Elementos de programas Identificadores
Slide 7-1 Copyright © 2003 Pearson Education, Inc. Figure: Estructuras de datos.
Clases y objetos La unidad fundamental de programación OO son las clases. Conjunto de métodos y semántica Qué se va a hacer POO Clase: que define la implementación.
 2003 Prentice Hall, Inc. All rights reserved. 1 Capítulo 6: Clases y Abstracción de Datos Índice del capítulo 6.1 Introducción 6.2 Estructuras 6.3 Clases.
1 Streams en Java Agustín J. González ELO Generalidades Un Stream es simplemente una fuente o destino de bytes. Los streams más comunes son los.
Archivos Programación.
Informática Ingeniería en Electrónica y Automática Industrial
Asignatura: Lenguaje de Programación de Sistemas PPT No.05 Programa vespertino de Ingeniería (E) en Sistemas Computacionales Profesor: José Estay Araya.
Archivos. fopen(...) Para comenzar a utilizar un archivo primero se debe abrir, invocando a la función fopen(...) FILE * fopen(char* nombre_arch, char*
Signal, kill, sigaction y máscara de señales
Sincronización de Procesos Semáforos Emely Arráiz Ene-Mar 08.
Archivos Binarios Lenguaje C Prof. Gonzalo Pastor.
1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe.
Archivos.
Framework Class Library (FCL) Dr. Diego Lz. de Ipiña Gz. de Artaza
Streams. / En casi todo programa se necesita traer o enviar información a una fuente externa. / Dicha información puede estar en un archivo en el disco.
El lenguaje de programación C - Identificadores y variables – Isidro González Caballero ( Introducción.
Arquitectura NFS El servidor NFS exporta uno o más directorios
Archivos Programación I MC Beatriz Beltrán Martínez.
Resumen Fundamentos de Programación/ Programación I

Llamadas al sistema del sistema de ficheros en POSIX Sistemas Operativos Ingeniería en Informática Área de Arquitectura de Computadores Universidad Carlos.
 En computación es un conjunto de líneas de señal que el microprocesador o CPU utilizan para intercambiar datos con otros componentes como teclados,
CONCEPTOS FUNDAMENTALES DEL NIVEL DEL SISTEMA OPERATIVO
El núcleo del sistema operativo
PROGRAMACIÓN MULTIMEDIA
Teoría de Sistemas Operativos Sistema de I/O. 2 Introducción Una de las funciones principales del sistema operativo es el control de todos los dispositivos.
CARACTERÍSTICAS Es un lenguaje de programación estructurado de propósito general. Está estrechamente asociado al sistema operativo UNIX, ya que el propio.
Sistemas de Archivos Sistemas Operativos.  Se debe proporcionar un almacenamiento secundario que respalda a la memoria principal  El Sistema de archivos.
MEMORIA DINÁMICA.
Archivos. Introducción Los datos que hemos tratado hasta el momento han residido en la memoria principal. Sin embargo, las grandes cantidades de datos.
Arquitectura de Computadores Clases Interrupciones de software y hardware IIC 2342 Semestre Rubén Mitnik Pontificia Universidad Católica.
Programación en Java Introducción a Java. Reseña histórica Surge en 1991 por Sun Microsystems Desarrollado para electrodomésticos Se buscaba un código.
Lenguaje de Programación II Prof. Rafael Montenegro B. Carrera: T.S.U en Informática Periodo: 2014-I.
SISTEMAS ELECTRÓNICOS 3ºGIERM1 1. Introducción 2. Tipos de datos 3. Estructuras típicas de programación 4. Manejo de bits Tema 7. Programación de microcontroladores.
Transcripción de la presentación:

1 E/S Driver Impresora –Airam Godoy Hernández –Jose Yeray Suárez Perdomo

2 Entrada/Salida(1) Se accede mediante el uso de archivos especiales (/dev). Se accede mediante el uso de archivos especiales (/dev). Este tipo de archivos tienen tres características: Este tipo de archivos tienen tres características: –1.-El número que identifica al controlados –2.-El número que identifica al dispositivo físico –3.-Modo de funcionamiento Modo bloque Modo bloque Modo carácter Modo carácter

3 Entrada/Salida(2) Entrada/Salida(2) Peticiones de acceso manejadas por el controlador Peticiones de acceso manejadas por el controlador Este interactúa con el dispositivo físico Este interactúa con el dispositivo físico Primitivas para leer y escribir iguales a las usadas en archivos regulares Primitivas para leer y escribir iguales a las usadas en archivos regulares

4 Modo bloque Corresponden a dispositivos estructurados Corresponden a dispositivos estructurados Se accede proporcionando el número de bloque. Se accede proporcionando el número de bloque. Las E/S se realizan mediante la función del búfer caché. Las E/S se realizan mediante la función del búfer caché. También puede trabajar en modo carácter. También puede trabajar en modo carácter. Implementación más confusa por necesitar más velocidad. Implementación más confusa por necesitar más velocidad. Ejemplo: El diskette, disco duro,… Ejemplo: El diskette, disco duro,…

5 Modo carácter Corresponden a dispositivos no estructurados Corresponden a dispositivos no estructurados Pueden ser accedidos como una corriente de bytes, como un fichero. Pueden ser accedidos como una corriente de bytes, como un fichero. Se leen y escriben los datos byte a byte. Se leen y escriben los datos byte a byte. Se accede de forma secuencial (no permite retrocesos) Se accede de forma secuencial (no permite retrocesos) Son bastantes transparentes Son bastantes transparentes

6 Driver de impresora Modo carácter Modo carácter Puede utilizar dos métodos diferentes para dialogar con el puerto Puede utilizar dos métodos diferentes para dialogar con el puerto –Interrupciones Mediante las IRQ Mediante las IRQ –Exploracion Mediante bucles que comprueba el registro de estado de los puertos Mediante bucles que comprueba el registro de estado de los puertos Permite evitar que se produzcan numerosas interrupciones Permite evitar que se produzcan numerosas interrupciones

7 Estructuras Se definen mediante descriptores localizados en la tabla lp_table Se definen mediante descriptores localizados en la tabla lp_table El tamaño de lp_table es 8 por defecto El tamaño de lp_table es 8 por defecto (#define LP_NO 8) Cada posicion contiene información de la impresora, mediante lp_struct Cada posicion contiene información de la impresora, mediante lp_struct (struct lp_struct lp_table[LP_NO];) Se encuentra definida en lp.h Se encuentra definida en lp.h Especifica el tipo de cada uno de los elementos Especifica el tipo de cada uno de los elementos

8 TipoCampoDescripcion intBase Dirección de la base de los puertos de E/S utilizados Unsigned int IRQ Número de interrucipn utilizada IntFlags Estado de la impresora conectada Unsigned int Chars Número de intentos a efectuar para imprimir un carácter Unsigned int Time Duración de la suspensión para una espera expresada en ciclos de reloj Unsigned int Wait Número de bucles de espera a efectuar antes de que la impresora tenga en cuenta un carácter Struct wait_queue * Lp_wait_q Cola de espera utilizada para esperar la llegada de una interrupción Char * Lp_buffer Puntero a una memoria intermedia que contiene los caracteres a imprimir Unsigned int Lastcall Fecha de la última escritura en la impresora Unsigned int Runchars Número de caracteres escritos en la impresora sin provocar suspensión Unsigned int Waittime Campo no utilizado Struct lp_stats Stats Estadísticas sobre el uso de la impresora Struct lp_struct

9 Struct file_operations static struct file_operations lp_fops = { static struct file_operations lp_fops = { lp_lseek, lp_lseek, NULL, /* lp_read */ NULL, /* lp_read */ lp_write, lp_write, NULL, /* lp_readdir */ NULL, /* lp_readdir */ NULL, /* lp_select */ NULL, /* lp_select */ lp_ioctl, lp_ioctl, NULL, /* lp_mmap */ NULL, /* lp_mmap */ lp_open, lp_open, lp_release}; lp_release};

10 Funciones de gestión de la impresora con Spolled La función lp_char_polled La función lp_char_polled La función lp_char_polled La función lp_char_polled –Implementa el envio de un carácter –Efectúa un bucle de espera hasta que la impresora esté disponible de recibir un carácter –Si se envía correctamente devuelve un 1 sino un 0 La función lp_write_polled La función lp_write_polled La función lp_write_polled La función lp_write_polled –Implementa el envio de una serie carácter –Efectúa un bucle sobre cada carácter a imprimir –Imprime los caracteres llamando a lp_char_polled –Si se produce un error, el proceso se duerme, y se pone su estado a TASK_INTERRUPTIBLE.

11 Funciones de gestión de la impresora con Interrupciones La función lp_char_interrupt La función lp_char_interrupt La función lp_char_interrupt La función lp_char_interrupt –Implementa el envio de un carácter –Efectúa un bucle hasta que la impresora esté disponible para recibir un carácter –Si se envía correctamente devuelve un 1 sino un 0 La función lp_interrupt La función lp_interrupt La función lp_interrupt La función lp_interrupt –Se llama cuando se produce una interrupción –Efectúa una búsqueda en la tabla lp_table para saber quien produjo la interrupción –Lama a wake_up para despertar el proceso en espera en lp_wait_q La función lp_write_interrupt La función lp_write_interrupt La función lp_write_interrupt La función lp_write_interrupt –Implementa el envio de una serie carácter –Efectúa un bucle sobra cada carácter a imprimir –Imprime los caracteres llamando a lp_char_interrupt –Si se produce un error, el proceso se duerme,se añade a lp_wait_q, y se pone su estado a TASK_INTERRUPTIBLE.

12 Operaciones de E/S sobre archivo(I) La función lp_write La función lp_write La función lp_write La función lp_write –implementa la operación sobre el archivo write –Esta llama a la función correspondiente según el modo La función lp_seek La función lp_seek La función lp_seek La función lp_seek –implementa la operación sobre el archivo lseek –Devuelve el error ESPIPE La función lp_ioctl La función lp_ioctl La función lp_ioctl La función lp_ioctl –implementa la operación sobre el archivo ioctl –Permite modificar o consultar los parámetros de la impresora

13 Operaciones de E/S sobre archivo(II) La función lp_open La función lp_open La función lp_open La función lp_open –implementa la operación sobre el archivo open –Verifica que la impresora existe y que no es usada por otro proceso –Inicializa la impresora –Marca la impresora como ocupada La función lp_release La función lp_release La función lp_release La función lp_release –implementa la operación sobre el archivo release –Marca la impresora como desocupada

14 Funciones de inicialización La función lp_probe La función lp_probe –Comprueba la presencia de un puerto paralelo –Inicializa su descriptor La función lp_init La función lp_init La función lp_init La función lp_init –Se llama al inicializarse el sistema, o en la carga del gestor en forma de módulo –Registra el gestor ( llamada a register_chrdev), indicando la operaciones asociadas al archivo –Efectúa un bucle de reconocimiento de los puertos posibles (llamada a lp_probe)

15 Lp_char_polled Implementa el envio de un carácter Implementa el envio de un carácter static int lp_char_polled(char lpchar, int minor) static int lp_char_polled(char lpchar, int minor) { int status = 0, wait = 0;unsigned long count = 0; { int status = 0, wait = 0;unsigned long count = 0; Efectúa un bucle de espera hasta que la impresora esté disponible de recibir un carácter Efectúa un bucle de espera hasta que la impresora esté disponible de recibir un carácter do { do { status = LP_S(minor); status = LP_S(minor); count ++; count ++; } while(!(status & LP_PBUSY) && count < LP_CHAR(minor)); } while(!(status & LP_PBUSY) && count < LP_CHAR(minor)); Si se envía correctamente devuelve un 1 sino un 0 Si se envía correctamente devuelve un 1 sino un 0 if (count == LP_CHAR(minor)) return 0; if (count == LP_CHAR(minor)) return 0; outb_p(lpchar, LP_B(minor)); outb_p(lpchar, LP_B(minor)); while(wait != LP_WAIT(minor)) wait++; while(wait != LP_WAIT(minor)) wait++; outb_p(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor ))); outb_p(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor ))); while(wait) wait--; while(wait) wait--; outb_p(( LP_PSELECP | LP_PINITP ), ( LP_C( minor ))); outb_p(( LP_PSELECP | LP_PINITP ), ( LP_C( minor ))); return 1;} return 1;}

16 Lp_wite_spolled Implementa el envio de una serie carácter Implementa el envio de una serie carácter static int lp_write_polled(struct inode * inode, struct file * file, char * buf, int count) static int lp_write_polled(struct inode * inode, struct file * file, char * buf, int count) { int retval; unsigned int minor = MINOR(inode->i_rdev); char c, *temp = buf;+ { int retval; unsigned int minor = MINOR(inode->i_rdev); char c, *temp = buf;+ temp = buf; temp = buf; Efectúa un bucle sobra cada carácter a imprimir Efectúa un bucle sobra cada carácter a imprimir while (count > 0) { while (count > 0) { c = get_fs_byte(temp); c = get_fs_byte(temp); Imprime los caracteres llamando a lp_char_polled Imprime los caracteres llamando a lp_char_polled retval = lp_char_polled(c, minor); retval = lp_char_polled(c, minor); if (retval) { count--; temp++;} if (retval) { count--; temp++;} Si se produce un error, el proceso se duerme, y se pone su estado a TASK_INTERRUPTIBLE. Si se produce un error, el proceso se duerme, y se pone su estado a TASK_INTERRUPTIBLE. if (!retval) { if (!retval) { current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies + LP_TIME(minor); current->timeout = jiffies + LP_TIME(minor); schedule(); schedule(); } } return temp-buf;} return temp-buf;}

17 Lp_char_interrupt Implementa el envio de un carácter Implementa el envio de un carácter static int lp_char_interrupt(char lpchar, int minor) static int lp_char_interrupt(char lpchar, int minor) {int wait = 0; unsigned char status; {int wait = 0; unsigned char status; Efectúa un bucle, durante el cual, espera que la impresora esté disponible de recibir un carácter Efectúa un bucle, durante el cual, espera que la impresora esté disponible de recibir un carácter if (!((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY) if (!((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY) || !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY) || !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY) || !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)) { || !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)) { outb_p(lpchar, LP_B(minor)); outb_p(lpchar, LP_B(minor)); while(wait != LP_WAIT(minor)) wait++; while(wait != LP_WAIT(minor)) wait++; while(wait) wait--; while(wait) wait--; outb_p(( LP_PSELECP | LP_PINITP ), ( LP_C( minor ))); outb_p(( LP_PSELECP | LP_PINITP ), ( LP_C( minor ))); return 1; return 1; } } Si se envía correctamente devuelve un 1 sino un 0 Si se envía correctamente devuelve un 1 sino un 0 return 0;} return 0;}

18 Lp_interrupt Se llama cuando se produce una interrupción Se llama cuando se produce una interrupción static void lp_interrupt(int irq) static void lp_interrupt(int irq) { struct lp_struct *lp = &lp_table[0]; { struct lp_struct *lp = &lp_table[0]; struct lp_struct *lp_end = &lp_table[LP_NO]; struct lp_struct *lp_end = &lp_table[LP_NO]; Efectúa una búsqueda en la tabla lp_table para saber quien produjo la interrupción Efectúa una búsqueda en la tabla lp_table para saber quien produjo la interrupción while (irq != lp->irq) { while (irq != lp->irq) { if (++lp >= lp_end) if (++lp >= lp_end) return; return; } } Lama a wake_up para despertar el proceso en espera en lp_wait_q Lama a wake_up para despertar el proceso en espera en lp_wait_q wake_up(&lp->lp_wait_q); wake_up(&lp->lp_wait_q); }

19 Lp_wite_interrupt Implementa el envio de una serie carácter Implementa el envio de una serie carácter static int lp_write_interrupt(struct inode * inode, struct file * file, char * buf, int count) static int lp_write_interrupt(struct inode * inode, struct file * file, char * buf, int count) { unsigned int minor = MINOR(inode->i_rdev); unsigned long copy_size; unsigned long total_bytes_written = 0; { unsigned int minor = MINOR(inode->i_rdev); unsigned long copy_size; unsigned long total_bytes_written = 0; unsigned long bytes_written; struct lp_struct *lp = &lp_table[minor]; unsigned char status; unsigned long bytes_written; struct lp_struct *lp = &lp_table[minor]; unsigned char status; Efectúa un bucle sobra cada carácter a imprimir Efectúa un bucle sobra cada carácter a imprimir do { bytes_written = 0; do { bytes_written = 0; copy_size = (count <= LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE); copy_size = (count <= LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE); memcpy_fromfs(lp->lp_buffer, buf, copy_size); memcpy_fromfs(lp->lp_buffer, buf, copy_size); while (copy_size) { while (copy_size) { Imprime los caracteres llamando a lp_char_interrupt Imprime los caracteres llamando a lp_char_interrupt if (lp_char_interrupt(lp->lp_buffer[bytes_written], minor)) {--copy_size; ++bytes_written;} if (lp_char_interrupt(lp->lp_buffer[bytes_written], minor)) {--copy_size; ++bytes_written;} Si se produce un error, el proceso se duerme,se añade a lp_wait_q, y se pone su estado a TASK_INTERRUPTIBLE. Si se produce un error, el proceso se duerme,se añade a lp_wait_q, y se pone su estado a TASK_INTERRUPTIBLE. outb_p((LP_PSELECP|LP_PINITP|LP_PINTEN), (LP_C(minor))); outb_p((LP_PSELECP|LP_PINITP|LP_PINTEN), (LP_C(minor))); status = LP_S(minor); status = LP_S(minor); current->timeout = jiffies + LP_TIMEOUT_INTERRUPT; current->timeout = jiffies + LP_TIMEOUT_INTERRUPT; interruptible_sleep_on(&lp->lp_wait_q); interruptible_sleep_on(&lp->lp_wait_q); outb_p((LP_PSELECP|LP_PINITP), (LP_C(minor))); outb_p((LP_PSELECP|LP_PINITP), (LP_C(minor))); total_bytes_written += bytes_written; buf += bytes_written; count -= bytes_written; total_bytes_written += bytes_written; buf += bytes_written; count -= bytes_written; } while (count > 0); } while (count > 0); return total_bytes_written;} return total_bytes_written;}

20 Lp_write y lp_seek Implementa la operación sobre el archivo write Implementa la operación sobre el archivo write static int lp_write(struct inode * inode, struct file * file, char * buf, int count) static int lp_write(struct inode * inode, struct file * file, char * buf, int count) Esta llama a la función correspondiente según el modo Esta llama a la función correspondiente según el modo if (LP_IRQ(MINOR(inode->i_rdev))) return lp_write_interrupt(inode, file, buf, count); if (LP_IRQ(MINOR(inode->i_rdev))) return lp_write_interrupt(inode, file, buf, count); else return lp_write_polled(inode, file, buf, count);} else return lp_write_polled(inode, file, buf, count);} Implementa la operación sobre el archivo lseek Implementa la operación sobre el archivo lseek static int lp_lseek(struct inode * inode, struct file * file,off_t offset, int origin) static int lp_lseek(struct inode * inode, struct file * file,off_t offset, int origin) Devuelve el error ESPIPE Devuelve el error ESPIPE {return -ESPIPE;} {return -ESPIPE;}

21 Lp_open static int lp_open(struct inode * inode, struct file * file) static int lp_open(struct inode * inode, struct file * file) { unsigned int minor = MINOR(inode->i_rdev); int ret; unsigned int irq; struct sigaction sa; { unsigned int minor = MINOR(inode->i_rdev); int ret; unsigned int irq; struct sigaction sa; Verifica que la impresora existe y que no es usada por otro proceso Verifica que la impresora existe y que no es usada por otro proceso if (minor >= LP_NO) return -ENODEV; if (minor >= LP_NO) return -ENODEV; if ((LP_F(minor) & LP_EXIST) == 0) return -ENODEV; if ((LP_F(minor) & LP_EXIST) == 0) return -ENODEV; if (LP_F(minor) & LP_BUSY) return -EBUSY; if (LP_F(minor) & LP_BUSY) return -EBUSY; Inicializa la impresora Inicializa la impresora if ((irq = LP_IRQ(minor))) { if ((irq = LP_IRQ(minor))) { sa.sa_handler = lp_interrupt; sa.sa_handler = lp_interrupt; sa.sa_flags = SA_INTERRUPT; sa.sa_flags = SA_INTERRUPT; sa.sa_mask = 0; sa.sa_mask = 0; sa.sa_restorer = NULL; sa.sa_restorer = NULL; ret = irqaction(irq, &sa); ret = irqaction(irq, &sa); if (ret) { kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE); if (ret) { kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE); lp_table[minor].lp_buffer = NULL; lp_table[minor].lp_buffer = NULL; printk("lp%d unable to use interrupt %d, error %d\n", minor, irq, ret); printk("lp%d unable to use interrupt %d, error %d\n", minor, irq, ret); return ret; } } return ret; } } Marca la impresora como ocupada Marca la impresora como ocupada LP_F(minor) |= LP_BUSY; LP_F(minor) |= LP_BUSY; return 0;} return 0;}

22 Lp_release Implementa la operación sobre el archivo release Implementa la operación sobre el archivo release static void lp_release(struct inode * inode, struct file * file) static void lp_release(struct inode * inode, struct file * file) { unsigned int minor = MINOR(inode->i_rdev); unsigned int minor = MINOR(inode->i_rdev); unsigned int irq; unsigned int irq; Marca la impresora como desocupada Marca la impresora como desocupada if ((irq = LP_IRQ(minor))) { if ((irq = LP_IRQ(minor))) { free_irq(irq); free_irq(irq); kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE); kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE); lp_table[minor].lp_buffer = NULL; lp_table[minor].lp_buffer = NULL; } } LP_F(minor) &= ~LP_BUSY; LP_F(minor) &= ~LP_BUSY; }

23 Lp_init Se llama al inicializarse el sistema, o en la carga del gestor en forma de módulo Se llama al inicializarse el sistema, o en la carga del gestor en forma de módulo long lp_init(long kmem_start) long lp_init(long kmem_start) { int offset = 0;unsigned int testvalue = 0;int count = 0; { int offset = 0;unsigned int testvalue = 0;int count = 0; Registra el gestor ( llamada a register_chrdev), indicando la operaciones asociadas al archivo Registra el gestor ( llamada a register_chrdev), indicando la operaciones asociadas al archivo if (register_chrdev(LP_MAJOR,"lp",&lp_fops)) { if (register_chrdev(LP_MAJOR,"lp",&lp_fops)) { printk("unable to get major %d for line printer\n", LP_MAJOR); printk("unable to get major %d for line printer\n", LP_MAJOR); return kmem_start; } return kmem_start; } Efectúa un bucle de reconocimiento de los puertos posibles (llamada a lp_probe) Efectúa un bucle de reconocimiento de los puertos posibles (llamada a lp_probe) for (offset = 0; offset < LP_NO; offset++) { for (offset = 0; offset < LP_NO; offset++) { outb_p( LP_DUMMY, LP_B(offset)); outb_p( LP_DUMMY, LP_B(offset)); for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++) for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++) testvalue = inb_p(LP_B(offset)); testvalue = inb_p(LP_B(offset)); if (testvalue != 255) { if (testvalue != 255) { LP_F(offset) |= LP_EXIST; LP_F(offset) |= LP_EXIST; lp_reset(offset); lp_reset(offset); printk("lp_init: lp%d exists (%d), ", offset, testvalue); printk("lp_init: lp%d exists (%d), ", offset, testvalue); if (LP_IRQ(offset)) printk("using IRQ%d\n", LP_IRQ(offset)); if (LP_IRQ(offset)) printk("using IRQ%d\n", LP_IRQ(offset)); else printk("using polling driver\n"); else printk("using polling driver\n"); count++; count++; } } } } if (count == 0) printk("lp_init: no lp devices found\n"); return kmem_start;} if (count == 0) printk("lp_init: no lp devices found\n"); return kmem_start;}

24 Lp_ioctl implementa la operación sobre el archivo ioctl implementa la operación sobre el archivo ioctl static int lp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) static int lp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { unsigned int minor = MINOR(inode->i_rdev);int retval = 0; { unsigned int minor = MINOR(inode->i_rdev);int retval = 0; if (minor >= LP_NO) return -ENODEV; if (minor >= LP_NO) return -ENODEV; if ((LP_F(minor) & LP_EXIST) == 0) return -ENODEV; if ((LP_F(minor) & LP_EXIST) == 0) return -ENODEV; Permite modificar o consultar los parámetros de la impresora Permite modificar o consultar los parámetros de la impresora switch ( cmd ) {case LPTIME: LP_TIME(minor) = arg; break; switch ( cmd ) {case LPTIME: LP_TIME(minor) = arg; break; case LPCHAR:LP_CHAR(minor) = arg; break; case LPCHAR:LP_CHAR(minor) = arg; break; case LPABORT: if (arg) LP_F(minor) |= LP_ABORT; case LPABORT: if (arg) LP_F(minor) |= LP_ABORT; else LP_F(minor) &= ~LP_ABORT; break; else LP_F(minor) &= ~LP_ABORT; break; case LPWAIT: LP_WAIT(minor) = arg; break; case LPWAIT: LP_WAIT(minor) = arg; break; case LPGETIRQ: retval = LP_IRQ(minor); break; case LPGETIRQ: retval = LP_IRQ(minor); break; default: retval = -EINVAL; } default: retval = -EINVAL; } return retval; return retval; }