e/s driver impresora

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

Upload: kalani

Post on 23-Mar-2016

33 views

Category:

Documents


0 download

DESCRIPTION

E/S Driver Impresora. Airam Godoy Hernández Jose Yeray Suárez Perdomo. Entrada/Salida(1). Se accede mediante el uso de archivos especiales ( /dev ). Este tipo de archivos tienen tres características: 1.-El número que identifica al controlados - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: E/S Driver Impresora

11

E/SE/SDriver ImpresoraDriver Impresora

– Airam Godoy HernándezAiram Godoy Hernández– Jose Yeray Suárez PerdomoJose Yeray Suárez Perdomo

Page 2: E/S Driver Impresora

22

Entrada/Salida(1)Entrada/Salida(1)• Se accede mediante el uso de archivos Se accede mediante el uso de archivos

especiales (especiales (/dev/dev).).• Este tipo de archivos tienen tres características:Este tipo de archivos tienen tres características:

– 1.-El número que identifica al controlados1.-El número que identifica al controlados– 2.-El número que identifica al dispositivo físico2.-El número que identifica al dispositivo físico– 3.-Modo de funcionamiento3.-Modo de funcionamiento

•Modo bloqueModo bloque•Modo carácterModo carácter

Page 3: E/S Driver Impresora

33

Entrada/Salida(2)Entrada/Salida(2)• Peticiones de acceso manejadas por Peticiones de acceso manejadas por

el controladorel controlador• Este interactúa con el dispositivo Este interactúa con el dispositivo

físicofísico• Primitivas para leer y escribir iguales Primitivas para leer y escribir iguales

a las usadas en archivos regularesa las usadas en archivos regulares

Page 4: E/S Driver Impresora

44

Modo bloqueModo bloque• Corresponden a dispositivos estructuradosCorresponden a dispositivos estructurados• Se accede proporcionando el número de Se accede proporcionando el número de

bloque.bloque.• Las E/S se realizan mediante la función del Las E/S se realizan mediante la función del

búfer caché.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 Implementación más confusa por necesitar

más velocidad.más velocidad.• Ejemplo: El diskette, disco duro,…Ejemplo: El diskette, disco duro,…

Page 5: E/S Driver Impresora

55

Modo carácter Modo carácter • Corresponden a dispositivos no Corresponden a dispositivos no

estructuradosestructurados• Pueden ser accedidos como una Pueden ser accedidos como una

corriente de bytes, como un fichero.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 Se accede de forma secuencial (no

permite retrocesos)permite retrocesos)• Son bastantes transparentesSon bastantes transparentes

Page 6: E/S Driver Impresora

66

Driver de impresoraDriver de impresora• Modo carácterModo carácter• Puede utilizar dos métodos diferentes para Puede utilizar dos métodos diferentes para

dialogar con el puertodialogar con el puerto– InterrupcionesInterrupciones

• Mediante las IRQMediante las IRQ– ExploracionExploracion

• Mediante bucles que comprueba el registro de estado Mediante bucles que comprueba el registro de estado de los puertosde los puertos

• Permite evitar que se produzcan numerosas Permite evitar que se produzcan numerosas interrupcionesinterrupciones

Page 7: E/S Driver Impresora

77

EstructurasEstructuras• Se definen mediante descriptores localizados Se definen mediante descriptores localizados

en la tabla lp_tableen la tabla lp_table• El tamaño de lp_table es 8 por defectoEl tamaño de lp_table es 8 por defecto

(#define LP_NO 8)(#define LP_NO 8)• Cada posicion contiene información de la Cada posicion contiene información de la

impresora, mediante lp_structimpresora, mediante lp_struct(struct lp_struct lp_table[LP_NO];)(struct lp_struct lp_table[LP_NO];)

• Se encuentra definida en lp.hSe encuentra definida en lp.h• Especifica el tipo de cada uno de los Especifica el tipo de cada uno de los

elementoselementos

Page 8: E/S Driver Impresora

88

TipoTipo CampoCampo DescripcionDescripcionintint BaseBase Dirección de la base de los puertos de E/S utilizados Dirección de la base de los puertos de E/S utilizados Unsigned intUnsigned int IRQIRQ Número de interrucipn utilizadaNúmero de interrucipn utilizadaIntInt FlagsFlags Estado de la impresora conectadaEstado de la impresora conectadaUnsigned intUnsigned int CharsChars Número de intentos a efectuar para imprimir un carácterNúmero de intentos a efectuar para imprimir un carácterUnsigned int Unsigned int TimeTime Duración de la suspensión para una espera expresada en Duración de la suspensión para una espera expresada en

ciclos de relojciclos de relojUnsigned intUnsigned int WaitWait Número de bucles de espera a efectuar antes de que la Número de bucles de espera a efectuar antes de que la

impresora tenga en cuenta un carácterimpresora tenga en cuenta un carácterStruct wait_queue Struct wait_queue **

Lp_wait_Lp_wait_qq

Cola de espera utilizada para esperar la llegada de una Cola de espera utilizada para esperar la llegada de una interrupcióninterrupción

Char *Char * Lp_buffeLp_bufferr

Puntero a una memoria intermedia que contiene los Puntero a una memoria intermedia que contiene los caracteres a imprimircaracteres a imprimir

Unsigned intUnsigned int LastcallLastcall Fecha de la última escritura en la impresoraFecha de la última escritura en la impresoraUnsigned intUnsigned int RuncharRunchar

ssNúmero de caracteres escritos en la impresora sin Número de caracteres escritos en la impresora sin provocar suspensiónprovocar suspensión

Unsigned intUnsigned int WaittimeWaittime Campo no utilizadoCampo no utilizadoStruct lp_statsStruct lp_stats StatsStats Estadísticas sobre el uso de la impresoraEstadísticas sobre el uso de la impresora

Struct lp_structStruct lp_struct

Page 9: E/S Driver Impresora

99

Struct file_operationsStruct 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};

Page 10: E/S Driver Impresora

1010

Funciones de gestión de la Funciones de gestión de la impresora con Spolledimpresora con Spolled• La función La función lp_char_polledlp_char_polled

– Implementa el envio de un carácterImplementa el envio de un carácter– Efectúa un bucle de espera hasta que la impresora esté Efectúa un bucle de espera hasta que la impresora esté

disponible de recibir un carácterdisponible de recibir un carácter– Si se envía correctamente devuelve un 1 sino un 0Si se envía correctamente devuelve un 1 sino un 0

• La función La función lp_write_polledlp_write_polled– Implementa el envio de una serie carácterImplementa el envio de una serie carácter– Efectúa un bucle sobre cada carácter a imprimirEfectúa un bucle sobre cada carácter a imprimir– Imprime los caracteres llamando a lp_char_polledImprime los caracteres llamando a lp_char_polled– Si se produce un error, el proceso se duerme, y se pone su Si se produce un error, el proceso se duerme, y se pone su

estado a TASK_INTERRUPTIBLE.estado a TASK_INTERRUPTIBLE.

Page 11: E/S Driver Impresora

1111

Funciones de gestión de la Funciones de gestión de la impresora con impresora con InterrupcionesInterrupciones• La función La función lp_char_interruptlp_char_interrupt

– Implementa el envio de un carácterImplementa el envio de un carácter– Efectúa un bucle hasta que la impresora esté disponible para recibir un carácterEfectúa un bucle hasta que la impresora esté disponible para recibir un carácter– Si se envía correctamente devuelve un 1 sino un 0Si se envía correctamente devuelve un 1 sino un 0

• La función La función lp_interruptlp_interrupt– Se llama cuando se produce una interrupción Se llama cuando se produce una interrupción – Efectúa una búsqueda en la tabla lp_table para saber quien produjo la interrupciónEfectú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_qLama a wake_up para despertar el proceso en espera en lp_wait_q

• La función La función lp_write_interruptlp_write_interrupt– Implementa el envio de una serie carácterImplementa el envio de una serie carácter– Efectúa un bucle sobra cada carácter a imprimirEfectúa un bucle sobra cada carácter a imprimir– Imprime los caracteres llamando a lp_char_interrupt 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 Si se produce un error, el proceso se duerme,se añade a lp_wait_q, y se pone su

estado a TASK_INTERRUPTIBLE.estado a TASK_INTERRUPTIBLE.

Page 12: E/S Driver Impresora

1212

Operaciones de E/S sobre Operaciones de E/S sobre archivo(I)archivo(I)• La función La función lp_writelp_write

– implementa la operación sobre el archivo writeimplementa la operación sobre el archivo write– Esta llama a la función correspondiente según el modoEsta llama a la función correspondiente según el modo

• La función La función lp_seeklp_seek– implementa la operación sobre el archivo lseekimplementa la operación sobre el archivo lseek– Devuelve el error ESPIPEDevuelve el error ESPIPE

• La función La función lp_ioctllp_ioctl– implementa la operación sobre el archivo ioctlimplementa la operación sobre el archivo ioctl– Permite modificar o consultar los parámetros de la Permite modificar o consultar los parámetros de la

impresoraimpresora

Page 13: E/S Driver Impresora

1313

Operaciones de E/S sobre Operaciones de E/S sobre archivo(II)archivo(II)• La función La función lp_openlp_open

– implementa la operación sobre el archivo openimplementa la operación sobre el archivo open– Verifica que la impresora existe y que no es usada por Verifica que la impresora existe y que no es usada por

otro procesootro proceso– Inicializa la impresoraInicializa la impresora– Marca la impresora como ocupadaMarca la impresora como ocupada

• La función La función lp_releaselp_release– implementa la operación sobre el archivo releaseimplementa la operación sobre el archivo release– Marca la impresora como desocupadaMarca la impresora como desocupada

Page 14: E/S Driver Impresora

1414

Funciones de inicializaciónFunciones de inicialización• La función lp_probeLa función lp_probe

– Comprueba la presencia de un puerto paraleloComprueba la presencia de un puerto paralelo– Inicializa su descriptorInicializa su descriptor

• La función La función lp_initlp_init– Se llama al inicializarse el sistema, o en la carga del Se llama al inicializarse el sistema, o en la carga del

gestor en forma de módulogestor en forma de módulo– Registra el gestor ( llamada a register_chrdev) , Registra el gestor ( llamada a register_chrdev) ,

indicando la operaciones asociadas al archivoindicando la operaciones asociadas al archivo– Efectúa un bucle de reconocimiento de los puertos Efectúa un bucle de reconocimiento de los puertos

posibles (llamada a lp_probe)posibles (llamada a lp_probe)

Page 15: E/S Driver Impresora

1515

Lp_char_polledLp_char_polled• Implementa el envio de un carácterImplementa 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é Efectúa un bucle de espera hasta que la impresora esté disponible de recibir un carácterdisponible 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 0Si 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;}

Page 16: E/S Driver Impresora

1616

Lp_wite_spolledLp_wite_spolled• Implementa el envio de una serie carácterImplementa 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 imprimirEfectú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_polledImprime 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 Si se produce un error, el proceso se duerme, y se pone su estado a TASK_INTERRUPTIBLE.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;}

Page 17: E/S Driver Impresora

1717

Lp_char_interruptLp_char_interrupt• Implementa el envio de un carácterImplementa 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 Efectúa un bucle, durante el cual, espera que la impresora esté disponible de recibir un carácterimpresora 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 0Si se envía correctamente devuelve un 1 sino un 0• rreturn 0;}eturn 0;}

Page 18: E/S Driver Impresora

1818

Lp_interruptLp_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 Efectúa una búsqueda en la tabla lp_table para saber quien produjo la interrupciónprodujo 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 Lama a wake_up para despertar el proceso en espera en lp_wait_qlp_wait_q

• wake_up(&lp->lp_wait_q);wake_up(&lp->lp_wait_q);• }}

Page 19: E/S Driver Impresora

1919

Lp_wite_interrupt Lp_wite_interrupt • Implementa el envio de una serie carácterImplementa 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 imprimirEfectú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 Si se produce un error, el proceso se duerme,se añade a lp_wait_q, y se pone su estado a TASK_INTERRUPTIBLE.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;}

Page 20: E/S Driver Impresora

2020

Lp_write y lp_seekLp_write y lp_seek• Implementa la operación sobre el archivo writeImplementa 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 modoEsta 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 lseekImplementa 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 ESPIPEDevuelve el error ESPIPE• {r{return -ESPIPE;}eturn -ESPIPE;}

Page 21: E/S Driver Impresora

2121

Lp_openLp_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 procesoVerifica 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 impresoraInicializa 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 ocupadaMarca la impresora como ocupada• LP_F(minor) |= LP_BUSY;LP_F(minor) |= LP_BUSY;• return 0;}return 0;}

Page 22: E/S Driver Impresora

2222

Lp_releaseLp_release• Implementa la operación sobre el archivo releaseImplementa 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 desocupadaMarca 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;• }}

Page 23: E/S Driver Impresora

2323

Lp_initLp_init• Se llama al inicializarse el sistema, o en la carga del gestor en forma de móduloSe 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 archivoRegistra 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;}

Page 24: E/S Driver Impresora

2424

Lp_ioctlLp_ioctl• implementa la operación sobre el archivo ioctlimplementa 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 Permite modificar o consultar los parámetros de la impresoraimpresora

• 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;• }}