Mem-IO unter Linux - Adressfehler

11/02/2009 - 18:59 von Martin Freiberg | Report spam
Hallo,

Ich bastle mir gerade einen Kerneltreiber um auf eine
ISA IO-Karte zuzugreifen die mit mem-io arbeitet.

Allerdings passt anscheinend der Adressenbereich nicht.

Unter DOS kann ich über den Bereich d000:0000 bis d000:0FFF
auf die Karte zugreifen. Programm geschrieben und getestet.

Unter Linux aber funktioniert der Zugriff darauf nicht.

Als Beispiel habe ich mir aus den Kernelsorcen den
hisax teles0 Treiber genommen der auch mit mem-io kann.

Zuerst mit request_mem_region überprüft ob ich den Bereich
erhalten kann. Dann mit ioremap mir den Adressbereich
geholt über den ich zugreifen können sollte.

Hier mal das wesentlichste aus dem Code:

static char *membereich = NULL;

int init_module (void)
{

if (!request_mem_region(0xd0000,0x0fff, "Mein IO-Treiber")) {
... Hier Code für Fehlerbehandlung...
}
membereich = ioremap (0xd0000,0x0fff);

printk (KERN_INFO "IO-Treiber - membereich ist: %p ",membereich);

writeb(0x5a,membereich +0x010);

}


Wenn ich mir mit printk den Inhalt von membereich anzeigen lasse,
erhalte ich 0x80d0000.

Wenn ich versuche mit writeb etwas auszugeben hat das keinen
Effekt. Genauso kann ich mit readb nichts einlesen, ich erhalte
da immer als Wert nur 0x00 zurück.

Auch wenn ich nach writeb den Befehl mb(); oder wmb(); Aufrufe.


Übersehe ich hier etwas? Oder benötige ich ioremap nur für PCI und
ISA-PNP Karten, und muß direkt auf den Adressbereich 0xd0000 - 0xd0fff
zugreifen?


Danke
Martin
 

Lesen sie die antworten

#1 Jan Seiffert
12/02/2009 - 09:56 | Warnen spam
Martin Freiberg wrote:

Hallo,

Ich bastle mir gerade einen Kerneltreiber um auf eine
ISA IO-Karte zuzugreifen die mit mem-io arbeitet.




Hmmm, das ist selten...

Allerdings passt anscheinend der Adressenbereich nicht.

Unter DOS kann ich über den Bereich d000:0000 bis d000:0FFF
auf die Karte zugreifen. Programm geschrieben und getestet.

Unter Linux aber funktioniert der Zugriff darauf nicht.

Als Beispiel habe ich mir aus den Kernelsorcen den
hisax teles0 Treiber genommen der auch mit mem-io kann.

Zuerst mit request_mem_region überprüft ob ich den Bereich
erhalten kann.



Das ist gut so.

Dann mit ioremap mir den Adressbereich geholt über den ich zugreifen können sollte.




Das ist anscheinend unnoetig.

Hier mal das wesentlichste aus dem Code:

static char *membereich = NULL;

int init_module (void)
{

if (!request_mem_region(0xd0000,0x0fff, "Mein IO-Treiber")) {
... Hier Code für Fehlerbehandlung...
}
membereich = ioremap (0xd0000,0x0fff);

printk (KERN_INFO "IO-Treiber - membereich ist: %p ",membereich);

writeb(0x5a,membereich +0x010);

}


Wenn ich mir mit printk den Inhalt von membereich anzeigen lasse,
erhalte ich 0x80d0000.

Wenn ich versuche mit writeb etwas auszugeben hat das keinen
Effekt. Genauso kann ich mit readb nichts einlesen, ich erhalte
da immer als Wert nur 0x00 zurück.




Schau mal in drivers/video/vgafb16.c oder drivers/video/vesafb.c
im wesentlichen ein:
info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0);

mit:

#define VGA_FB_PHYS 0xA0000

und aus include/asm-x86/vga.h:

#define VGA_MAP_MEM(x, s) (unsigned long)phys_to_virt(x)
#define vga_readb(x) (*(x))
#define vga_writeb(x, y) (*(y) = (x))

Das kommt mir zwar nicht wie die sauberste Methode vor, aber da war so was, aus
irgendwelchen legacy gruenden kann der bereich unter 1Mb nicht geremappt werden.
Der Vesatreiber ist aehnlich, der Vesa framebuffer (GraKa-Ram, irgendwo im
PCI-Space) wird geremapt, aber die Kontrollschnittstelle im legacy Membereich
wird einfach "gecastet".

Auch wenn ich nach writeb den Befehl mb(); oder wmb(); Aufrufe.




Vergiss mal ganz schnell das es diese Funktionen gibt. Die sind kein magischer
Feenstaub, den man irgendwo drueber streut und haben mit der Peripherie
syncronisation erstmal NICHTS zu tun (sorry, ist ein beliebter fehler mit
PCI-posting, das dann versucht wird mit mem bars zu fixen...).
Ach jetzt seh ichs, die fliegen ja auch im teles Treiber rum, uhh, was auch
immer da einer versucht hat...
Entweder er hat versucht den Compiler davon abzuhalten gewiesse Optimierungen zu
machen, dann sind die mb/rmb/wmb etwas heftig und es haetten barriers gereicht,
oder weil der Speicher da unten normalerweise als gecached in den mtrr
eingetragen ist, und fuer den Bereich zwischen 000a0000-000fffff keine Ausnahme
drin ist (das ist mit mtrr ein PITA). Das waere jetzt mit PAT zwar moeglich,
aber a) warscheinlich aus irgednwelshen legacy gruenden fuer da unten nicht
moeglich und b) wuerde sowieso nicht das gewunschte Ergebniss bringen dank
irgendwelcher CPU-Errata.
Da muesste man mal einen richtigen Kernel Guru fragen was das darstellt.
Vielleicht hat auch einer versucht den Treiber auf nicht x86 zum laufen zu
bringen oder sowas.
Bei der menge haette der Author heute echt ein Problem, jedes rmb/wmb/mb muss
mit einem Kommentar versehen werden warum es jetzt da benoetigt wird um zu
verhindern das damit irgendwelche grundlegenden Bugs ueberpinselt werden.


Übersehe ich hier etwas? Oder benötige ich ioremap nur für PCI und
ISA-PNP Karten, und muß direkt auf den Adressbereich 0xd0000 - 0xd0fff
zugreifen?




Sieht so aus als wenn du ioremap fuer alles ueber 1 Mb brauchst.
Unter 1 Mb geht anscheinen so unter x86, aber nicht das phys_to_virt vergessen ;)

Isa mem io ist halt selten und daher tot. Die paar Treiber die das noch machen
sind meistens alt, ungepflegt und seltenst getestet. Einzige ausnahme ist vesa
und vga, und die laesst man da wohl so rumspielen, aus legacy Gruenden.


Danke
Martin


Gruss
Jan

char c = *(bit1*8 + bit2*4 + bit3*2 + bit4 + "0123456789ABCDEF")
Es gibt Tage, da muss man C moegen

Ähnliche fragen