Como eu leio e escrevo em um barramento ISA a partir de um módulo do kernel?

4

Estou tentando me comunicar com uma placa ISA personalizada (não projetada por mim) com um computador de placa única x86 executando o redhat 6.2. As únicas informações que tenho para como me comunicar com essa placa personalizada são os endereços de barramento ISA e os dados que essa placa personalizada responde (e isso eu descobri apenas conectando o barramento ISA a um analisador lógico).

Por exemplo, um endereço de barramento comum que eu vejo é 0xE30000 , que acessa um FPGA no quadro personalizado. Originalmente, eu esperava que o endereço de barramento e o endereço físico do computador de placa única fossem os mesmos. Isso me permitiria mmap/ioremap o endereço físico assumido 0xE30000 em algum endereço virtual que eu poderia escrever. Infelizmente o kernel do redhat não permite que o espaço do usuário mmap para um endereço tão alto. Quando tentei obter acesso a ele em um módulo do kernel que escrevi, acabei descobrindo que esse endereço físico já está reservado para a RAM do sistema:

[root@rheldev ~]# cat /proc/iomem
00000000-00000fff : reserved
00001000-0009dfff : System RAM
0009e000-0009ffff : reserved
000a0000-000bffff : Video RAM area
000c0000-000cbfff : Video ROM
000e0000-000fffff : reserved
  000f0000-000fffff : System ROM
00100000-07ffffff : System RAM  // <--- 0xE30000 sits in there
  00400000-008364e2 : Kernel code
  008364e3-00a917c7 : Kernel data
  00b15000-00c3af6f : Kernel bss
c0000000-c3ffffff : 0000:00:00.0
e0000000-e0000fff : 0000:00:0f.0
  e0000000-e0000fff : e100
e0020000-e003ffff : 0000:00:0f.0
  e0020000-e003ffff : e100
ff000000-ff00ffff : 0000:00:0f.0
fff00000-ffffffff : reserved

Então, agora estou de volta à estaca zero procurando uma maneira de escrever no barramento ISA. Eu não encontrei muito no que diz respeito aos drivers do ISA, embora eu tenha encontrado um driver de PC / 104 de código aberto aqui . Olhando para ele, no entanto, ele usa o mapeamento de porta para gravar no barramento, e não consegui ver como garantir que a gravação na porta X coloque o endereço de barramento desejado 0xE30000 no barramento ISA (e / ou PC / 104) .

Eu admito que esta é uma área completamente fora da minha área de entendimento. Isso parece incrivelmente básico e simples que não deve ser um problema muito grande, mas é um protocolo antigo o suficiente para que encontrar informações sobre eles não seja tão simples quanto eu esperava. Agradecemos antecipadamente por quaisquer recursos / tutoriais / exemplos que você possa me indicar!

Atualização:

Obrigado @dirkt pela resposta apontando-me na direção certa! Eu estava tentando entrar no barramento ISA diretamente, quando na verdade é uma ponte conectada ao barramento PCI:

[root@rheldev ~]# lspci
00:00.0 Host bridge: VIA Technologies, Inc. VT8605 [ProSavage PM133]
00:01.0 PCI bridge: VIA Technologies, Inc. VT8605 [PM133 AGP]
00:07.0 ISA bridge: VIA Technologies, Inc. VT82C686 [Apollo Super South] (rev 40)
00:07.1 IDE interface: VIA Technologies, Inc. VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (rev 06)
00:07.4 Non-VGA unclassified device: VIA Technologies, Inc. VT82C686 [Apollo Super ACPI] (rev 40)
00:0f.0 Ethernet controller: Intel Corporation 8255xER/82551IT Fast Ethernet Controller (rev 10)

Procurando, não havia muito em /sys/bus/isa/ , mas o ISA: 00: 07: 0 não aparece em /sys/bus/pci/devices/ . Aqui está o conteúdo dessa pasta:

[root@rheldev 0000:00:07.0]# ls
broken_parity_status  enable         msi_bus  reset             uevent
class                 irq            power    resource          vendor
config                local_cpulist  ppdev    subsystem
device                local_cpus     remove   subsystem_device
driver                modalias       rescan   subsystem_vendor

Então, agora para atualizar minha pergunta: Como faço para ler e gravar em um barramento ISA através de uma ponte ISA conectada a um barramento PCI?

Eu vi alguns sites falando sobre o uso de pouca memória / portas para obter o barramento ISA, mas não acho que funcionará para mim, já que preciso trabalhar com endereços ISA muito mais altos (a partir de 0xE00000) . (veja também meu comentário sobre a resposta do @ dirkt)

Mais uma vez, todos os recursos que você pode me indicar sobre como dizer ao barramento PCI que eu quero falar com essa ponte ISA para que eu possa colocar endereços de barramento ISA mais altos no barramento ISA são muito apreciados. Obrigado!

Atualização 2:

Enquanto olhava para o lilo como sugerido por @dirkt, notei que minha instalação do redhat 6 estava usando o grub legacy em vez do grub 2, então decidi ver o que o grub 2 faria com o primeiro furo de memória ativado. Depois de compilar localmente e instalá-lo manualmente na minha máquina (já que não havia um pacote redhat 6 para ele), as coisas parecem estar funcionando melhor do que eu esperava!

Eu adicionei argumentos de linha do kernel no grub para marcar a memória de 14MB-16MB como reservado, e o kernel parece honrar essa solicitação e marcar esses endereços como reserved in /proc/iomem/ . Como indicado no meu comentário para @dirkt, eu não esperava que o kernel marcasse corretamente como reservado, mas parece que eu estava olhando para um código-fonte do kernel mais antigo do que o que o redhat 6.2 usa.

Com um programa C simples e um analisador lógico, posso ver os dados passarem pela leitura / gravação para esses endereços! O próximo passo é escrever um módulo do kernel correto para manipular corretamente a leitura e gravação no barramento ISA, mas agora que está funcionando, isso deve ser uma brisa relativa!

    
por cjameston 10.05.2017 / 22:28

1 resposta

3

Eu só posso dar uma resposta genérica, mas espero que você aponte na direção certa.

Você não disse qual placa x86 você usa, mas em sistemas não antigos, o barramento ISA estará atrás de uma ponte PCI-para-ISA. Você pode usar lspci para encontrar essa ponte. A ponte fornecerá um mapeamento da memória principal e do espaço de E / S para a memória do barramento ISA e o espaço de E / S. Isso é configurado pelo kernel na inicialização de acordo com as informações fornecidas no BIOS, ou seja, ACPI, incluindo o PNP herdado. Você pode ver informações sobre esse processo em dmesg após a inicialização.

Mesmo no sistema moderno, ainda existem dispositivos ISA legados, embora estejam agora no barramento LPC e não em um barramento ISA real. Os drivers de kernel do Linux para tal dispositivo, ou seja, o driver de teclado / mouse 8042 PS / 2 (consulte drivers/input/serio ), reservam as portas que precisam ( request_region ) no init ( i8042_platform_init in i8042-io.h ), libere-os sair e para a porta E / S ( inb , outb etc.) para se comunicar com ela. Eu não sei como funciona para o acesso à memória, mas provavelmente semelhante. As portas reservadas aparecem em /proc/ioports .

A ponte deve aparecer em /sys/bus/pci/devices , talvez você possa encontrar informações adicionais lá. Há também /sys/bus/isa , mas não tenho certeza sob quais circunstâncias o kernel preencherá isso com informações.

Primeiro, tentei ver se a placa reage a algumas portas de E / S. Além disso, tente o procedimento de enumeração PNP (ou verifique dmesg se isso não for feito na inicialização), se ele responder a isso, o resto será muito mais fácil.

Finalmente, tentarei descobrir como a ponte PCI-to-ISA mapeia o espaço de memória, quais operações de kernel você precisa para reservar esse espaço de memória e, em seguida, novamente investigá-lo e ver se algo acontece.

Editar :

O livro Drivers de dispositivos do Linux, 3ª edição tem algumas informações sobre como acessar a memória ISA na seção 9.4.5 .

Editar :

Coisas para experimentar:

1) Inicialize com lilo em vez de grub , ative "hole" (ISA-mapping) no BIOS, veja se ele inicializa. Sim, lilo ainda funciona.

2) Google para VIA VT82C686A South Bridge data sheet. No espaço de configuração PCI, se a ponte PCI-para-ISA, existe o seguinte registro:

Offset 43 - ROM Decode Control  

Setting these bits enables the indicated address range to be
included in the ROMCS# decode:  

7    FFFE0000h-FFFEFFFFh  
6    FFF80000h-FFFDFFFFh 
5    000E8000h-000EFFFFh  
4    000E0000h-000E7FFFh 
3    000D8000h-000DFFFFh  
2    000D0000h-000D7FFFh  
1    000C8000h-000CFFFFh 
0    000C0000h-000C7FFFh  

Então eu acho que você pode tentar habilitar o "buraco" (mapeamento ISA) após a inicialização, e verificar com o logicanalyser se ele funciona. Usar FFFE0000h em vez de 000E0000h também vale a pena tentar se a placa não decodificar bits altos.

Eu não sei como fazer isso corretamente e informar o kernel do Linux do mapeamento alterado. Talvez haja também opções de inicialização para isso.

Eu sei que você pode acessar o espaço de configuração PCI através do pseudo-arquivo /sys/bus/pci/devices/0000:00:07.0/config , então você pode até tentar isso fora de um driver de kernel.

3) Verifique definitivamente dmesg e /sys/bus/pnp para ver se sua carta já está enumerada. Se você não conseguir entender a dmesg output, coloque-a em um pastebin e poste um link; Eu posso dar uma olhada.

    
por 11.05.2017 / 12:04

Tags