Arquitetura Plug and Play
Por Ricardo Zelenovsky e Alexandre Mendonça em 11 de maio de 1998

Introdução

O mercado de computadores pessoais vem gradativamente mudando o seu perfil. Primeiramente, o que se observava, no início da década de 80, era que grande parte dos compradores de PCs ou possuíam algum conhecimento técnico ou não se preocupavam com instalações futuras de recursos após o computador ser adquirido. Ou seja, não se tinha o costume de abrir uma máquina e conectar placas, drives ou outros periféricos. Mesmo quando havia uma necessidade de instalação de qualquer componente, exigia-se um mínimo de conceitos técnicos. Ora, era comum, e ainda não deixa de ser, que as configurações de endereços de I/O ou memória, interrupções e canais de DMA fossem determinadas por jumpers e chaves do tipo dip-switch. Daí, no mínimo, era imprescindível saber interpretar alguma literatura técnica, como um manual de placa. E mais, saber mapear endereços ou interrupções, de forma a garantir que não houvesse conflitos elétricos no barramento.

Um outro tipo de problema também era freqüente: o usuário comprava uma placa nova que requeria, em sua instalação, alterar algum parâmetro de configuração de outra placa já conectada e com seu software já inicializado. Certamente, quem não tem tanta intimidade com conceitos de hardware teria certa dificuldade em adequar os device-drivers outrora configurados, tanto nos arquivos "config.sys" e "autoexec.bat", quanto no painel de controle do windows ou outro aplicativo.

Contudo, o perfil de mercado passou a ser dominado por um novo tipo de consumidor: aquele totalmente leigo, o que não sabe sequer o que são interrupções, endereços ou jumpers. Com isso, aquele problema de reconfiguração fica agravado.

Para evitar as referidas dificuldades de configuração, reconfiguração e atualização, que tanto frustavam os usuários, foram idealizados sistemas confortáveis, denominados plug and play, ou seja, conecte e opere.

Então, tecnicamente falando, o objetivo de um sistema plug and play é permitir que a BIOS ou sistema operacional instalem e configurem quaisquer combinações de placas de expansão e dispositivos. Desta forma, aquele método de configuração de jumpers ou chaves passa a ser substituído por um gerenciamento por software. A flexibilidade conseguida com este sistema é tal que permite reconfigurações mesmo em tempo de execução.

A Solução Plug and Play

A solução para o problema plug and play consiste em fazer com que o hardware, firmware, sistema operacional e aplicativos sejam capazes de compartilhar dispositivos através da definição de formatos de identificadores de dispositivos (tipo, de placa, fabricante, versão, etc.) e recursos exigidos (interrupção, canal de DMA e endereços de I/O ou memória), e que são estruturas de dados, padronizadas pela arquitetura plug and play.

O primeiro passo para que seja constituído o ambiente plug and play é identificar a configuração da máquina (feito inicialmente pela BIOS e posteriormente gerenciada pelo sistema operacional), ou seja, construindo-se uma árvore de hardware. Tal árvore deve conter os registros necessários para estabelecerem-se a assinatura ou identificação dos dispositivos e a informação necessária para automaticamente localizar e carregar os device-drivers. Após carregar o device-driver, adiciona-se à árvore de hardware, mesmo em tempo de execução, um nó de dispositivo associado ao driver.

Vale observar que toda placa-mãe que suporta a arquitetura plug and play possui uma BIOS que busca, durante a inicialização do computador, e armazena os registros de nós de dispositivos, contendo as informações dos recursos exigidos. Isto orienta todas as partições de sistemas operacionais e os device-drivers que possam futuramente ser instalados. Após a instalação, os nós de dispositivos são acrescentados ou modificados segundo às necessidades do sistema operacional.

É importante ressaltar que quaisquer tipos de conecções elétricas fazem parte da árvore de hardware, inclusive todas as ligações hierárquicas entre os barramentos (ex: ponte barramento local - barramento ISA ou PCI). A Figura 1 ilustra um exemplo de configuração envolvida numa árvore de hardware.

Um problema surge ao distribuir os recursos pelos nós da árvore de hardware, de solução não trivial, que é o de identificar os dispositivos estáticos, como placas ISA que não têm a flexibilidade de alterar dinamicamente os recursos exigidos de interrupção, DMA e endereços de I/O ou memória. Por tal falta de flexibilidade, duas são as opções para tais dispositivos: mapeá-los de forma prioritária (ex: se o dispositivo exigir a IRQ 5, ele a terá disponível) ou desligá-los (desconectá-los logicamente da configuração da máquina e fisicamente do barramento).

A BIOS oferece também um conjunto padronizado de serviços referentes à arquitetura plug and play, como a obtenção dos recursos alocados para cada dispositivo. Tais serviços são acessados, por software, de duas formas: somente em modo real (ex: programas para DOS), através da interrupção por software 1Ah; e tanto em modo real quanto em modo protegido (ex: windows 95 e DOS), através de subrotinas (instrução call).

 
clique para ampliar
Figura 1: Exemplo de uma árvore de hardware, cuja raiz é o barramento local da CPU.

Device-Drivers

Basicamente, a diferença entre desenvolver um device-driver comum e um device-driver plug and play é deixá-lo prevenido contra reconfigurações por parte do sistema operacional. Isto pode ser traduzido por alguns procedimentos de software que se resumem aos recursos exigidos pelo device-driver ficarem sob custódia do sistema operacional (isto para que eles possam ser gerenciados dinamicamente).

Detalhando um pouco mais tal custódia, o device-driver, no instante de seu registro ou instalação, retorna ao sistema operacional um endereço de uma rotina, contida no device-driver, do tipo call-back (como o procedimento de janela ou de caixa de diálogo). Com isso, fica permitida a troca de mensagens entre o sistema operacional e o device-driver. Inclusive, fica o device-driver obrigado a responder a todas as mensagens de reconfiguração enviadas pelo sistema operacional.

A Figura 2 ilustra uma seqüência de comandos que devem estar contidos no código desenvolvido para o device-driver plug and play.


/* variáveis globais do device-driver */
unsigned int interrupção, endereço_base;
  
/* subrotina que recebe as ordens de reconfiguração */
LRESULT CALLBACK device_driver_reconfig( ... )     {
       ...
/* identifica mensagem de reconfiguração */
       ... 
/* altera variáveis globais */
interrupção = ...;
endereço_base = ...; 
altera_manipulador_vetor_interrupção( ... );
      ...
}
  
/* rotinas de acesso ao periférico */
void envia_dado (int dado)    {
outp (endreço_base, dado);      }
  ...  

Figura 2: Exemplo de uma arquitetura de device-driver, contendo a subrotina que intercepta as ordens de reconfiguração e subrotinas de acesso genérico ao periférico.

Concluindo, o processo de configuração de recursos é realizado em duas situações: primeira, por parte da BIOS, durante a inicialização do computador, naturalmente, fazendo parte do POST (Power On Self Test) e, segundo, em tempo de execução, sob gerenciamento do sistema operacional.

BIOS Plug and Play

Primeiramente, o mínimo exigido para um sistema ser plug and play é que ele contenha uma BIOS plug and play, ou seja, que disponha ao sistema operacional e aos aplicativos serviços padronizados de gerenciamento de recursos.

Para detectar a BIOS plug and play, o sistema operacional ou o aplicativo procura, na memória, o que se chama de "cabeçalho de instalação". O cabeçalho é uma estrutura de 34 bytes que contém os endereços a partir de onde estão residentes as rotinas de serviços oferecidas pela BIOS, tanto para o modo real, quanto para o modo protegido, além de outras informações (assinatura, fabricante, versão, etc.).

O cabeçalho de instalação começa com uma assinatura de 4 bytes ("$PNP"), e pode estar localizado a partir do offset 0 do início de qualquer dos segmentos do modo real entre os endereços físicos F0000h e FFFF0h. A rotina a seguir, implementada para o modo real, verifica se o sistema é plug and play, através da busca de um cabeçalho de instalação com a assinatura padronizada.


#include 
...
unsigned int verifica_plug_play(void) {
 void far endereço;     
  unsigned int seletor;     
  for (seletor=0xF000;seletor!= 0xFFF0; seletor++) { 
    endereço = MK_FP(seletor,0);    
    if (strncmp( (char far *) (endereço), "$PNP", 4) == 0 )
      return (seletor);     
  return ( 0 );  }     

Obtidos os endereços das rotinas dos serviços (contidos no cabeçalho de instalação), ficam disponíveis os serviços de configuração. As chamadas aos serviços são do tipo int far (função far que retorna um inteiro de 16 bits). Como são vários os serviços, a passagem de parâmetros pela pilha é feita como nos compiladores C, e não como no PASCAL, ou seja, são empilhados os parâmetros da direita para a esquerda. O último parâmetro empilhado é um inteiro que especifica o índice do serviço oferecido. Em C, a declaração destes tipos de função segue ao padrão a seguir:


int far(end_do_conjunto_de_serviços)(int índice_do_serviço,...);

O número de parâmetros passados depende do índice do serviço.

Apenas como ilustração, exemplificam-se alguns serviços como obter as características e recursos de um nó de dispositivo num registro de dados, ou alterar, de acordo com a convenência de gerenciamento, parâmetros do registro outrora obtido.

Hardware Plug and Play Comercial

Dispositivos periféricos conectados diretamente à placa mãe do sistema (temporizadores, RAM CMOS, controladores de interrupção e DMA, interface de teclado e outros) e as placas ISA estáticas (que não são reconfiguráveis) têm seus recursos estrategicamente alocados como num PC AT convencional. Então, apenas os recursos restantes poderão vir a ser compartilhados pelas placas plug and play.

Comercialmente, são mais comuns placas plug and play para 3 tipos de barramentos comerciais: PCI, ISA e PCMCIA. Os dois primeiros casos serão comentados.

Placas que satisfazem à especificação PCI já são, por natureza, plug and play. Tal especificação já reserva, para cada slot PCI lógico, 256 endereços de I/O consecutivos, onde, pelos primeiros 64, são feitas as programações de recursos e oferecidas informações outras, como identificações do fabricante e da versão e a localização da ROM de expansão.

Ao contrário do barramento ISA, podem existir múltiplos barramentos PCI numa configuraçào de máquina (a vantagem disto é descongestionar o fluxo de dados onde está conectada a CPU principal). Tais barramentos são hierarquizados da seguinte forma: existe um barramento raiz e os outros barramentos são interligados eletricamente por pontes PCI-PCI, como mostrado na Figura 3.

Para verificar se a máquina admite a especificação PCI, utilizar o seguinte código, para modo real, em assembler:


clique para ampliar
Figura 3: Esquema que ilustra a interligação de diversos barramentos PCI.


mov ax,B101h  ;serviço B101h
int 1Ah   ;interrupção 1Ah
cmp edx, 50434920h ;se for PCI compatível, retorna a  
   string'PCI 'em edx

Se a flag ZF (zero flag) estiver em 1, o sistema admite o PCI.

Uma placa ISA plug and play é uma variação nova dos adaptadores ISA, com a característica de admitir uma configuração dinâmica de recursos. Vale ressaltar que, para os dois casos, as pinagens dos conectores de encaixe de placas são idênticas. A diferença é que, na tradicional, a configuração é estabelecida por jumpers e chaves, e que, na plug and play, é por software, segundo a padrões bem definidos.

Quanto a custos, as placas ISA tradicionais são de projeto e programação bem mais simples que as ISA plug and play, que, para atender aos padrões de configuração dinâmica, exigem circuitos digitais extras e uma programação bem mais complexa. Isto talvez explica o porquê de ainda projetarem-se bastante placas ISA tradicionais, principalmente no meio acadêmico ou mesmo no profissional em escala reduzida, isto quando a placa tem utilização bastante restrita.

Para permitir-se a reconfiguração em placas ISA plug and play, foram acrescentados, na placa mãe do sistema, 3 registradores extras: o registrador de endereços (279h, só para escrita), o registrador de escrita (A79h, só para escrita) e o registrador de leitura (programável entre 203h e 3FFh, só para leitura). Por estes registradores são feitas algumas trocas de informações entre a BIOS ou sistema operacional e as placas ISA plug and play.

Uma dúvida poderia surgir quanto ao fato de utilizarem-se os endereços 279h e A79h, que são reservados para a LPT2 e LPT3, respectivamente. Contudo, não haverá conflitos elétricos devido a esta multiplexação, pois estes endereços são usados apenas para a leitura pelas portas paralelas.


Para saber mais:

Originalmente em http://www.clubedohardware.com.br/artigos/867

© 1996-2008, Clube do Hardware. Todos os direitos reservados.

É expressamente proibida a reprodução total ou parcial do conteúdo deste site e dos textos disponíveis, seja através de mídia eletrônica, impressa, ou qualquer outra forma de distribuição. Os infratores serão indiciados e punidos com base na lei nº 9.610 de 19/02/1998.

Não nos responsabilizamos por danos materiais e/ou morais de qualquer espécie promovidos pelo uso das informações contidas no Clube do Hardware.