Descargar la presentación
La descarga está en progreso. Por favor, espere
Publicada porVisitación Madruga Modificado hace 10 años
1
1 E/S Driver Impresora –Airam Godoy Hernández –Jose Yeray Suárez Perdomo
2
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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; }
Presentaciones similares
© 2025 SlidePlayer.es Inc.
All rights reserved.