Wavelan Driver
Introdução –
divisão em 2 equipes
O driver da
interface de rede será implementado por dois grupos:
1º grupo: Será responsável pela parte de
hardware (acesso a registradores, mapeamento
dos mesmos na
memória, etc.) exportando as funcionalidades no formato de uma interface padrão
C (proxy).
2º grupo: Incluirá no Linux um módulo que
acesse o Hardware através das abstrações criadas pelo primeiro grupo.
1º Grupo:
O objetivo deste grupo é de tratar
questões que lidam diretamente com o hardware
(placa Wavelan
orinoco). A modelagem de classes deve permitir que o código possa ser usado tanto
no Linux como no EPOS. Funções específicas do Linux serão encapsuladas em uma
classe separada, permitindo que somente esta classe seja alterada quando o
código for portado para outras plataformas (e.g. EPOS).
- Método de acesso aos registradores da
placa
O acesso aos registradores será feito
através do mapeamento dos mesmos em memória,
em oposição a
operações de I/O. Essa opção foi escolhida por ser uma maneira rápida/eficiente
de transferir dados entre dispositivo e computador, além de deixar o código
fonte mais legível.
Os endereços dos registradores, o conteúdo
que cada um deve possuir, a sequência
de operações que
deve ser seguida para realizar certas operações (e.g enviar um frame de
dados) e outras
informações adicionais estão disponíveis no datasheet da placa, já obtido
pelo grupo junto
à empresa fabricante da mesma.
* Interface forncecida às camadas
superiores:
1) int hardware_init(void);
Inicializa o hardware.
Retorno: 0 caso não ocorram erros.
2) int hardware_getIrq(void);
Retorna a IRQ da interrupcao
3) int hardware_getAddress(void);
Retorna o endereco fisico da placa (endereco MAC)
4) int hardware_prepareConnection(void);
Prepara a placa pra comecar a transacao (transmissao/recebimento) efetiva de pacotes
5) int hardware_shutdown(void);
Finaliza as operações.
6) int hardware_send(char *data, int len);
data - ponteiro para o início dos dados.
len - número de bytes a serem transmitidos.
Retorno: 0 (zero) caso nenhum erro tenha ocorrido.
7) int hardware_receive(char *data, int *len);
data - ponteiro para o início da área de memória onde os dados recebidos serão colocados.
len - tamanho máximo dos dados que podem ser recebidos.
Retorno: número de bytes recebidos.
8) int hardware_isTxInt(void);
Retorna true se eh interrupcao de transmissao feita com sucesso.
9) int hardware_isRxInt(void);
Retorna true se eh interrupcao de recebimento.
De acordo com a figura, o grupo 1 tem o
objetivo de "esconder" detalhes referentes
ao hardware
(placa wavelan) fornecendo à camada superior uma "visão uniforme" do
dispositivo através de uma interface de programação única.
Apesar do módulo ser desenvolvido em C++,
a interface fornecida deve ser em C para facilitar a integração com o Linux.
Para isso usaremos um proxy com uma interface em C.
O proxy repassa as chamadas de função para
o objeto da classe OrinocoDriver que ele agrega.
O que temos?
-
Datasheet da
placa PRISM II
-
Linux Device
Drivers
2º Grupo:
A integração da interface de rede WaveLan com
o sistema Linux será feita em duas etapas:
1ª Consistirá na implementação de um módulo
Char Device Driver que não levará em consideração a pilha de protocolos do sistema. Com isso será testado o
funcionamento do envio e recepção de
informações simples. Tal abordagem visa evitar possíveis problemas de
interpretação de resultados decorrentes da passagem da informação pela pilha de
protocolos.
2ª Consistirá na implementação de um módulo
Net Device Driver (que é o objetivo a ser alcançado). Este desempenhará as
mesmas funções do módulo anterior, tendo como adicional a integração com a
pilha de protocolos do Linux.
Interface
com o sistema Linux:
=============================================================================================================
Métodos que
devem ser implementados para o Net Device:
int init_module(void);
Inicialização do módulo e registro do device no kernel.
void cleanup_module(void);
Limpa tudo antes de sair, desfaz o registro do device.
int wlan_init (struct net_device *dev);
Configura o dispositivo de acordo com o padrão Ethernet usando ¨ether_setup¨. A inicializacao do hardware é chamada e o
owner do módulo é setado.
int wlan_open (struct net_device *dev);
Incrementa o número de usuários que estão utilizando o módulo e reinicia a fila de envio de pacotes.
int wlan_stop (struct net_device *dev);
Executa os procedimentos necessários para a finalizacão da comunicacão com a placa.
A fila de envio de pacotes é parada bem como a camada de hardware do driver.
int wlan_hard_start_xmit (struct sk_buff *skb,struct net_device *dev);
Executa os procedimentos necessários para a transmissao de pacotes. Pára a fila de envio de pacotes para que o kernel não mande
outro pacote antes que o atual seja enviado. O pacote é convertido de 802_3 para 802_11.
int wlan_set_config (struct net_device *dev,struct ifmap *map);
Nao utilizada
void wlan_tx_timeout (struct net_device *dev);
Acorda a fila de envio de pacotes para que o sistema continue a enviar os socket buffers.
struct net_device_stats* wlan_get_stats (struct net_device *dev);
Funções de Suporte:
void wlan_rx(struct net_device *dev, int len);
Monta o sk_buffer com o dado recebido, faz a conversão de 802.11 para 802.3 e chama a funcao de recebimento de um pacote do
kernel.
void wlan_interrupt(int irq, void *dev_id, struct pt_regs *regs);
Tratamento da interrupcão. As interrupcões tratadas são as de pacote recebido e transmissão efetuada com sucesso.
void wlan_802p3_to_802p11(struct sk_buff *skb);
Conversao do header do sk_buff. A conversao é feita da especificacao 802.3 para a 802.11, recriando um novo sk_buff.
void wlan_802p11_to_802p3(struct sk_buff *skb);
Conversao do header do sk_buff. A conversao é feita da especificacao 802.11 para a 802.3, recriando um novo sk_buff