• Nenhum resultado encontrado

Programação de Sistemas

N/A
N/A
Protected

Academic year: 2021

Share "Programação de Sistemas"

Copied!
17
0
0

Texto

(1)

Programação de Sistemas

Controlador de impressora

por interface paralela

Programação de Sistemas

Centronics : 1/33

• A interface paralela IEEE1284, ou Centronics, permite

dois equipamentos trocar informação de 8 bits em

simultâneo.

– Usa ficha DB25

– Velocidades de transferência até 150Kbps, com cabo até 10m.

Introdução (1)

– Pinos distribuídos por:

8 bidireccionais para porto OUTPUT (RW)

5 para porto STATUS(R)

4 para porto CONTROL(RW)

8 ligados ao GND

(2)

• Os 3 portos ocupam os seguintes endereços

– Endereço BASE: Output

– Endereço BASE+1: Status

– Endereço BASE+2: Control

• IEEE1284 especifica 4 modos de operação

Introdução (2)

Programação de Sistemas

Centronics : 3/33

• IEEE1284 especifica 4 modos de operação

– Compatível: modo básico, assíncrono.

– Nibble: do periférico para anfitrião (“host”) em mensagens de 4

bits e a metade da velocidade.

– Byte: do periférico para anfitrião em mensagens de 8 bits.

(combinado com modo compatível faz o porto ser designado por

Bidireccional)

– EPP, ECP: conexão half-duplex.

Status register

Bit

Pino

Sinal

Significado

3

15

Error/

Perifério em erro

4

13

Select

Perifério seleccionado

5

12

PaperOut

Sem papel

Ligado ao IRQ7

Introdução (3)

6

10

Ack/

Aceitou dados (mantém LOW durante ~ 5µs)

7

11

Busy

Perifério ocupado

Control register

Bit

Pino

Sinal

Significado

0

1

Strobe/

Dados disponíveis (manter LOW durante min 5µs)

1

14

AutoLineFeed/

Ordem para executar automaticamente salto de linha

(3)

• O controlador vai interagir com impressora em modo

E/S programada (“pooling”).

• Diagrama temporal de envio de um Byte para o

periférico.

Introdução (4)

Programação de Sistemas

Centronics : 5/33

• Uso do porto paralelo para controlar um step

motor

(4)

• Pretende-se implementar um controlador

para uma impressora HP LaserJet 6.

• Impressora de baixo custo, 600 dpi,

velocidade 4 páginas/min, alimentador

pouco fiável, com interface paralela.

Impressora (1)

Programação de Sistemas

Centronics : 7/33

pouco fiável, com interface paralela.

• Aceita apenas a descrição de páginas em

PCL-Printer Command Language.

• Entradas a implementar: open,

release

e write.

• Comandos da impressora expressos na linguagem

PJL-Printer Job Language da HP.

• Uma tarefa de impressão segue a seguinte estrutura

<ESC>%-12345X

Comandos controlo da tarefa

Impressora (2)

Comandos controlo da tarefa

<ESC>E

Página 1

Página n

<ESC>E

<ESC>%-12345X

(5)

• Consultar manual PCL em

http://h20000.www2.hp.com/bc//docs/support/SupportManual/bpl13210/bpl13210.pdf

• A linguagem de descrição das páginas PCL-Printer

Command Language, da HP, é implementada por todos os

fabricantes de impressoras.

Impressora (3)

Programação de Sistemas

Centronics : 9/33

fabricantes de impressoras.

• Outra linguagem de descrição de páginas, bastante

divulgada, é o POSTSCRIPT.

• <ESC>%-12345X

é designado por UEL-Universal Exit

Language, delimitando todas as tarefas

• Os comandos PCL possuem o formato

<ESC>C

parameterizado

C

grupo

#C

terminação

Opcionalmente mais dois campos,

C

parâmetro

#

Impressora (4)

quantidade

• O sistema de coordenadas é

definido pela figura

• O texto é impresso apenas

dentro das margens (tudo o

que saia é eliminado)

Margens

(0,0)

X

(6)

Comandos PCL de controlo de página: exemplos

<ESC>&l#A

### tamanho página (para A4, #=26)

<ESC>&l#H

### fonte papel (para manual, #=2)

<ESC>&l#O

### orientação papel (para vertical, #=0)

Fontes determinadas por parâmetros na seguinte ordem:

Impressora (5)

Programação de Sistemas

Centronics : 11/33

1.

Conjunto de símbolos (PC-8,…)

2.

Espaçamento ocupado por cada caractere (igual ou distinto)

3.

Pitch (número de caracteres impressos numa polegada horizontal)

4.

Altura (diferença em pontos=1/72 polegadas)

5.

Estilo (postura-ex:itálico, largura e estrutura-ex:sombreado)

6.

Espessura (“stroke weight”)

7.

Tipo de letra (Courier,CG Times,…)

Hp

<ESC>(0U<ESC>(s1p14v0s3b4101T

ASCII

espaçamento proporcional

altura

CG Times

Impressora (6)

Comandos PCL de posicionamento

<ESC>*p#x#Y

### posiciona cursor na linha, coluna

Terminação de linha

(7)

• Funções a implementar:

int init_module(void)

Inicialização módulo

void cleanup_module(void)

Finalização módulo

int parport_open(struct inode *inode,

Abertura ficheiro

struct file *filp)

int parport_close(struct inode *inode,

Fecho ficheiro

Interface

Programação de Sistemas

Centronics : 13/33

struct file *filp)

ssize_t parport_write(struct file *filp,

Escrita Bytes

char *buf, size_t count, loff_t *f_pos)

• Inicialização da impressora e comandos PCL de

configuração inseridos na função de abertura do ficheiro.

• Exemplifica-se o controlador de impressora em 2 modos:

– E/S programada

– Interrupções

#include <linux/module.h> #include <linux/kernel.h>

#include <linux/fs.h> /* struct file_operations,register_chrdev */ #include <linux/ioport.h> /* request_region */

#include <linux/errno.h> /* error codes */ #include <asm/io.h> /* inb,outb */ #include <asm/delay.h> /* udelay */

Interface modo E/S programada (1)

#define BASE 0x378 #define NPORTS 8 #define MDN 240

MODULE_LICENSE("GPL");

int parport_open(struct inode *, struct file *); int parport_release(struct inode *, struct file *);

(8)

struct file_operations parport_ops={ .owner = THIS_MODULE, .write = parport_write, .open = parport_open, .release = parport_release }; #define PARPORT_CONTROL_STROBE 0x1 #define PARPORT_CONTROL_AUTOFD 0x2

Interface modo E/S programada (2)

Programação de Sistemas

Centronics : 15/33

#define PARPORT_CONTROL_AUTOFD 0x2 #define PARPORT_CONTROL_INIT 0x4 #define PARPORT_CONTROL_SELECT 0x8 #define PARPORT_STATUS_ERROR 0x8 #define PARPORT_STATUS_SELECT 0x10 #define PARPORT_STATUS_PAPEROUT 0x20 #define PARPORT_STATUS_ACK 0x40 #define PARPORT_STATUS_BUSY 0x80 char uel[9] = {'\x1b','%','-','1','2','3','4','5','X'}; char printerReset[2] = {'\x1b','E'};

/* mantem-se a calha de alimentacao */

char paperSource[5] = {'\x1b','&','l','0','H'}; /* tamanho papel, A4=26 */

char paperSize[6] = {'\x1b','&','l','2','6','A'}; /* margem de topo 12 linhas */

char printerTop[6] = {'\x1b','&','l','1','2','E'};

Interface modo E/S programada (3)

char printerTop[6] = {'\x1b','&','l','1','2','E'}; /* terminacao linha 2-CR=CR, LF=CR+LF, FF=FF */

char lineTermination[5] = {'\x1b','&','k','2','G'};

/* selecciona simbolos de conjunto PC-8, espaçamento proporcional, altura 14 pt, estilo direito, espessura negrito, fonte Times */

char fontSet[22] =

{'\x1b','(','1','0','U','\x1b','(','s','1','p','1','4','v','0', 's','3','b','4','1','0','1','T'};

(9)

int init_module(void) {

int result = register_chrdev(MDN,dev_name,&parport_ops);

if (result<0) {

printk(KERN_WARNING "can't get major %d\n",MDN);

return result; }

printk(KERN_INFO "Parport_ops installed!\n");

return 0; }

Interface modo E/S programada (4)

Programação de Sistemas

Centronics : 17/33

return 0; }

void cleanup_module(void) {

unregister_chrdev(MDN,dev_name);

printk(KERN_INFO "Parport_ops removed!\n"); }

int parport_release(struct inode *inode, struct file *filp){

/* close device */

return 0; }

int parport_open(struct inode *inode, struct file *filp) {

/* open device */

outb(~(PARPORT_CONTROL_INIT | PARPORT_CONTROL_SELECT |

PARPORT_CONTROL_AUTOFD), BASE+2);

udelay(5);

outb(0xff,BASE+2);

Interface modo E/S programada (5)

/* PCL commands */

parport_write( NULL,&printerReset[0],2,NULL );

parport_write( NULL,&paperSource[0],5,NULL );

parport_write( NULL,&paperSize[0],6,NULL );

parport_write( NULL,&printerTop[0],6,NULL );

parport_write( NULL,&lineTermination[0],5,NULL) ;

parport_write( NULL,&fontSet[0],22,NULL );

return 0; /* success */

}

(10)

ssize_t parport_write(struct file *filp, char *buf, size_t count, loff_t *f_pos) { /* Writes buf to the Data port */

char *plocal=buf; ssize_t wrote=0;

unsigned char status, data; while(wrote<count) {

for (;;) { /* NOTA: espera activa que a impressora esteja disponível */ status = inb(BASE+1);

status = status & (PARPORT_STATUS_BUSY | PARPORT_STATUS_ERROR);

Interface modo E/S programada (6)

Programação de Sistemas

Centronics : 19/33

status = status & (PARPORT_STATUS_BUSY | PARPORT_STATUS_ERROR); if ( status == PARPORT_STATUS_ERROR ) break;

udelay(50); }

/* Set the data lines */

data = *plocal++; outb(data,BASE); udelay(1); /* Delay for a bit */ /* Pulse strobe */

outb(PARPORT_CONTROL_AUTOFD |

PARPORT_CONTROL_SELECT | PARPORT_CONTROL_INIT, BASE+2); udelay(5);

/* End the pulse */

outb(PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_STROBE | PARPORT_CONTROL_SELECT | PARPORT_CONTROL_INIT, BASE+2); wrote++; }

return wrote; }

#include <linux/module.h> #include <linux/kernel.h>

#include <linux/fs.h> /* struct file_operations,register_chrdev */ #include <asm/io.h> /* inb,outb */

#include <asm/delay.h> /* udelay */ #include <linux/sched.h> /* request_irq */ #include <linux/interrupt.h>

Interface modo interrupção (1)

#include <asm/semaphore.h> #define BASE 0x378

#define IRQ 7 /* NOTA: novo! */ #define MDN 240

MODULE_LICENSE("GPL");

int parport_open(struct inode *, struct file *); int parport_release(struct inode *, struct file *);

(11)

struct file_operations parport_ops={ .owner = THIS_MODULE, .write = parport_write, .open = parport_open, .release = parport_release }; #define PARPORT_CONTROL_STROBE 0x1

Interface modo interrupção (2)

Programação de Sistemas

Centronics : 21/33

#define PARPORT_CONTROL_STROBE 0x1 #define PARPORT_CONTROL_AUTOFD 0x2 #define PARPORT_CONTROL_INIT 0x4 #define PARPORT_CONTROL_SELECT 0x8

#define PARPORT_CONTROL_EN_IRQ 0x10 /* NOTA: novo! */

#define PARPORT_STATUS_ERROR 0x8 #define PARPORT_STATUS_SELECT 0x10 #define PARPORT_STATUS_PAPEROUT 0x20 #define PARPORT_STATUS_ACK 0x40 #define PARPORT_STATUS_BUSY 0x80

char dev_name[] = "Interrupt parport";

struct semaphore byte_rec; /* semáforo para espera de IRQ */ irqreturn_t IRQ_handler(int irq, void *dev_id);

int total_esc,num_int; /* Contador de bytes enviados e total de interrupções */ /* Constantes PCL */

char uel[9] = { '\x1b','%','-','1','2','3','4','5','X' }; char printerReset[2] = { '\x1b','E' };

Interface modo interrupção (3)

char printerReset[2] = { '\x1b','E' }; /* Mantem-se a calha de alimentação */

char paperSource[5] = { '\x1b','&','l','0','H' }; /* Tamanho papel, A4=26 */

char paperSize[6] = { '\x1b','&','l','2','6','A' }; /* Margem de topo 12 linhas */

char printerTop[6] = { '\x1b','&','l','1','2','E' }; /* terminacao linha 2-CR=CR, LF=CR+LF, FF=FF */

char lineTermination[5] = { '\x1b','&','k','2','G' }; /* selecciona símbolos de conjunto PC-8, espaçamento proporcional, altura 14 pt,

estilo direito, espessura negrito, fonte Times */

(12)

irqreturn_t IRQ_handler(int irq, void *dev_id) { /*NOTA: nova função, desbloqueia gestor de semáforo */ up(&byte_rec);

num_int++;

return IRQ_HANDLED; } int init_module(void) {

int result = register_chrdev(MDN,dev_name,&parport_ops);

Interface modo interrupção (4)

Programação de Sistemas

Centronics : 23/33

int result = register_chrdev(MDN,dev_name,&parport_ops);

if (result<0) {

printk(KERN_WARNING "can't get major %d\n",MDN); return result; }

printk(KERN_INFO "Parport_int installed!\n"); return 0; }

void cleanup_module(void) {

unregister_chrdev(MDN,dev_name);

printk(KERN_INFO "Parport_int removed!\n"); }

int parport_release(struct inode *inode,struct file *filp) {

/* NOTA: libertar IRQ que já não é necessario */ free_irq(IRQ, NULL);

/* desactiva geração de interupção da porta paralela */

outb(PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_STROBE |

Interface modo interrupção (5)

PARPORT_CONTROL_SELECT | PARPORT_CONTROL_INIT, BASE+2);

printk(KERN_INFO "Parport_int closed\n Written %d\n interrupts %d\n", total_esc, num_int);

return 0; }

(13)

int parport_open(struct inode *inode, struct file *filp) { int result;

/* open device */

printk(KERN_INFO "Parport_int open\n");

total_esc = num_in t= 0;

Interface modo interrupção (6)

Programação de Sistemas

Centronics : 25/33

/* NOTA: Instalar função de tratamento de IRQ */

result= request_irq(IRQ, IRQ_handler, SA_INTERRUPT, dev_name, NULL);

if (result!=0) {

printk(KERN_WARNING "can't get IRQ %d\n",IRQ); return result; }

/* inicializar impressora na porta paralela */

outb(PARPORT_CONTROL_INIT | PARPORT_CONTROL_SELECT | PARPORT_CONTROL_AUTOFD, BASE+2);

udelay(5);

outb( 0xff & (~PARPORT_CONTROL_EN_IRQ),BASE+2 );

/* inicializar semáforo bloqueado para esperar chegada da interrupção */ init_MUTEX_LOCKED(&byte_rec);

Interface modo interrupção (7)

init_MUTEX_LOCKED(&byte_rec);

/* comandos PCL de inicialização da impressora */

parport_write( NULL,&printerReset[0],2,NULL ); parport_write( NULL,&paperSource[0],5,NULL ); parport_write( NULL,&paperSize[0],6,NULL ); parport_write( NULL,&printerTop[0],6,NULL ); parport_write( NULL,&lineTermination[0],5,NULL ); parport_write( NULL,&fontSet[0],22,NULL );

(14)

ssize_t parport_write(struct file *filp, char *buf, size_t count, loff_t *f_pos) { /* Writes buf to the Data port */

char *plocal=buf; ssize_t wrote=0;

unsigned char status, data;

/* Esperar que a impressora esteja pronta para iniciar impressão (útil caso a impressora esteja a terminar alguma impressão) */

Interface modo interrupção (8)

Programação de Sistemas

Centronics : 27/33

(útil caso a impressora esteja a terminar alguma impressão) */ for (;;) {

status = inb(BASE+1);

status = status & (PARPORT_STATUS_BUSY | PARPORT_STATUS_ERROR); if ( status == PARPORT_STATUS_ERROR ) break;

udelay(50); }

while(wrote<count) { /* Set the data lines */ data = *plocal++; outb(data,BASE);

udelay(1); /* Delay for a bit */

/* Pulse strobe */

outb(PARPORT_CONTROL_EN_IRQ | PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_SELECT | PARPORT_CONTROL_INIT, BASE+2); udelay(5);

/* End the pulse */

outb(PARPORT_CONTROL_EN_IRQ |PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_STROBE |

Interface modo interrupção (9)

PARPORT_CONTROL_STROBE |

PARPORT_CONTROL_SELECT | PARPORT_CONTROL_INIT, BASE+2); /* A esperar IRQ * /

if ( down_interruptible(&byte_rec)!=0 ) break; wrote++;

total_esc++; }

(15)

1. Gerar o controlador

[root@manitoba parport]#make –C /lib/modules/`uname-r`/build=M=`pwd` modules

make: Entering directory `/usr/src/kernels/2.6.18-1.2798.fc6-i686'

CC [M] /root/parport/parport_ops.o

/root/parport/parport_ops.c: In function ‘parport_write’:

/root/parport/parport_ops.c: In function ‘init_module’:

Instalação do controlador (1)

Programação de Sistemas

Centronics : 29/33

/root/parport/parport_ops.c: In function ‘init_module’:

/root/parport/parport_ops.c:140: warning: assignment makes integer from pointer

without a cast

Building modules, stage 2.

MODPOST

CC /root/parport/parport_ops.mod.o

LD [M] /root/parport/parport_ops.ko

make: Leaving directory `/usr/src/kernels/2.6.18-1.2798.fc6-i686'

2. Criar um i-node

[root@manitoba parport]# mknod /dev/parport_ops c 240 0

3. Inserir o módulo no sistema

[root@manitoba parport]# /sbin/insmod parport_ops.ko

Nota

: efeito da função init_module() pode ser

Instalação do controlador (2)

Nota

: efeito da função init_module() pode ser

observado no ficheiro /var/log/messages

Mar 29 17:51:54 manitoba kernel: Parport_ops installed!

A

instalação pode ser confirmada

Pelo comando lsmod

Module

Size

Used by

parport_ops 7296 0

No directório /dev/

[root@manitoba parport]# ls -l /dev/parport_ops

crw-rw-rw- 1 root root 240, 0 Mar 29 14:50

/dev/parport_ops

(16)

4. Experimentar com o programa

#include <stdio.h> #define SIZE 128

main(int argc, char **argv) { int fsA;

FILE *fsB; int count;

Instalação do controlador (3)

Programação de Sistemas

Centronics : 31/33

int count; char buf[SIZE]; if (argc!=2) {

fprintf( stderr,"Apenas 1 parametro-ficheiro a despejar\n" ); exit(12); }

fsA = open( "/dev/parport_ops",O_WRONLY ); if(fsA<0) {

perror(""); exit(10); }

fprintf( stderr,"Abri /dev/parport_ops\n" );

fsB = fopen( argv[1],"r" ); if(fsB==NULL) {

perror(""); exit(10); }

fprintf( stderr,"Abri %s\n",argv[1 ]);

do {

Instalação do controlador (4)

do { count = fread(&buf[0],1,SIZE,fsB); if(count>0) write(fsA,&buf[0],count); } while (count!=0); close(fsA); fclose(fsB); }

(17)

5. Depois de experimentar, eliminar módulo do sistema

[root@manitoba rgc]# /sbin/rmmod /dev/parport_ops

6. Eliminar referência a dispositivo

[root@manitoba rgc]# rm /dev/parport_ops

rm: remove character special file `/dev/parport_ops'? y

Instalação do controlador (5)

Programação de Sistemas

Centronics : 33/33

rm: remove character special file `/dev/parport_ops'? y

[root@manitoba rgc]#

Referências

Documentos relacionados

5.2 Após o horário de encontro com o professor não mais será permitida a entrada do aluno para que não perturbe a entrevista ou exame do grupo com o paciente. 5.3 Caso o aluno perca

2 apresenta o comportamento dos preços dos produtos que compõem a Cesta Básica de Alimentação em Montes Claros no mês de Dezembro de 2015..

Os veículos produzidos pela YAMAHA são máquinas de engenharia precisa. Siga rigorosamente as etapas do plano de manutenção recomendado efetuando todas as REVISÕES PERIÓDICAS.

c) a proposta de preços relativa ao valor arrematado, inclusive, se for o caso, detalhando a planilha de custos, observado o disposto no subitem 11.1.1. 12.1.1.1 Uma

O objetivo do trabalho foi estudar o avanço da formação de cor pela reação Maillard com misturas de dois açúcares (glicose ou lactose) e dois aminoácidos (glicina e glutamato

▪ Realizar exames finais nacionais para melhoria de nota, relevando o seu resultado apenas como classificação de prova de ingresso. A inscrição nos exames do

A interpretação de palavras, expressões e pequenas frases, do português (escrito ou falado) para a LIBRAS, na forma gestual e animada, já está concluída, tanto utilizando técnicas

A representação gráfica foi realizada com o auxílio do software Ucinet® 6 para Windows versão 6.320 específico para esta finalidade, que apresenta