Kernel-Modul Programmierung

Welches Modul/Treiber für welche Hardware, Kernel compilieren...
Antworten
Benutzeravatar
Columbus
Beiträge: 1051
Registriert: 30.04.2002 15:25:02
Wohnort: Mainz
Kontaktdaten:

Kernel-Modul Programmierung

Beitrag von Columbus » 10.06.2007 22:35:21

Ich wollte mal rumhören, ob es hier auch Leute gibt, die Kernel-Module programmieren können. An dieses Leute (vielleicht z.B. jemand aus Wien ;-) hätte ich gleich mal einen Strauss an Fragen. Ich bin mir nicht sicher ob das alles besser zu "Softwareentwicklung" passen würde.

Vorneweg bin ich auf der Suche nach einer Web-Seite oder Doku im HTML-Format, auf der alle Befehle der Kernel-API aufgelistet und erklärt werden. UND es sollte vor allem aktuell sein. Ich habe in den letzten Wochen ziemlich oft an Problemen verzweifelt, die sich dadurch ergeben haben, daß die Doku nicht mehr ganz aktuell war.

Dann die erst konkrete Frage:
Ich habe versucht mit folgendem Code aus den PCI-Registern den IRQ zu erfragen:

Code: Alles auswählen

result = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &myirq);
habe aber nach dem Auslesen der Variablen myirq einen falschen Interrupt bekommen, wie sich später herausstellte. Den Richtigen habe ich durch die Membervaribale "dev->irq" bekommen.

Diese Variable habe ich aber nie initialisiert. Ich habe für meinen PCI-Karten-Treiber folgende Struktur aufgebaut.

Code: Alles auswählen

struct pci_driver me1400_driver = {
	.name = ME1400_NAME,
	.id_table = me1400_pci_table,
	.probe = me1400_probe,
	.remove = me1400_remove
};
Die Funktion me1400_probe, die bei der Initialisierung automatisch augerufen wird hat folgenden Prototyp:

Code: Alles auswählen

static int me1400_probe (struct pci_dev *dev, const struct pci_device_id *id)
hier ist nun die Struct vom Typ "pci_dev" vorhanden. Und aus dieser Struct habe ich den IRQ erfahren. Ich vermute mal, dass diese Struct automatisch initialisiert und gefüllt wird, aber warum steht das nicht im Rubini? (Erklärung: Rubini ist das Buch: "Linux Device Drivers" von Alessandro Rubini u.a, bin sonst sehr zufrieden damit)

Dann die Erklärung, wie man der parallelen Schnittstelle einen IRQ herauskitzel kann:

Code: Alles auswählen

	unsigned long mask;

	mask = probe_irq_on();
	outb_p(0x10,short_base+2); /* enable reporting */
	outb_p(0x00,short_base);   /* clear the bit */
	outb_p(0xFF,short_base);   /* set the bit: interrupt! */
	outb_p(0x00,short_base+2); /* disable reporting */
	udelay(5);  /* give it some time */
	short_irq = probe_irq_off(mask);
Warum, erst mal, wird hier outb_p verwendet anstatt outb? Also warum unterbrechbar auf die Ports schreiben?
Dann warum eine 16 auf die Adresse der Schnittstelle + 2? "short_base" ist doch die Adresse des Ports, an dem der Interrupt ausgelöst werden soll. Und warum wird dadurch die Mitteilung des IRQ erst möglich?

Wenn sich da jemand erbahmen könnte :lol:

Vielen Dank

Gruss Christian
Die größten Kritiker der Elche,
waren früher selber welche.

F.W. Bernstein

Spasswolf
Beiträge: 3472
Registriert: 30.11.2005 10:32:22
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Wald

Beitrag von Spasswolf » 11.06.2007 11:26:29

So wird die irq in ../drivers/pci/probe.c bestimmt:

Code: Alles auswählen

/*
 * Read interrupt line and base address registers.
 * The architecture-dependent code can tweak these, of course.
 */
static void pci_read_irq(struct pci_dev *dev)
{
        unsigned char irq;

        pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq);
        dev->pin = irq;
        if (irq)
                pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
        dev->irq = irq;
}
Diese Funktion wird von der Funktion pci_setup_device benutzt, die die struct pci_dev füllt:

Code: Alles auswählen

/**
 * pci_setup_device - fill in class and map information of a device
 * @dev: the device structure to fill
 *
 * Initialize the device structure with information about the device's 
 * vendor,class,memory and IO-space addresses,IRQ lines etc.
 * Called at initialisation of the PCI subsystem and by CardBus services.
 * Returns 0 on success and -1 if unknown type of device (not normal, bridge
 * or CardBus).
 */
static int pci_setup_device(struct pci_dev * dev)
{...}

Um welche Architektur geht es dir? outb_p existiert nicht für alle Architekturen:
http://lxr.linux.no/ident?i=outb_p

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Re: Kernel-Modul Programmierung

Beitrag von gms » 11.06.2007 13:56:27

Columbus hat geschrieben:Vorneweg bin ich auf der Suche nach einer Web-Seite oder Doku im HTML-Format, auf der alle Befehle der Kernel-API aufgelistet und erklärt werden. UND es sollte vor allem aktuell sein.
auf dieser Seite: http://lwn.net/Articles/2.6-kernel-api/ werden Änderungen im Kernel-API dokumentiert

eine aktuelle Doku kannst du dir selber aus den Kernelsourcen bauen:

Code: Alles auswählen

cd /usr/src/linux
make htlmdocs
cd Documentation/DocBook/kernel-api
DEINBROWSER file://`pwd`/index.html
Columbus hat geschrieben:Dann die erst konkrete Frage:
Ich habe versucht mit folgendem Code aus den PCI-Registern den IRQ zu erfragen:

Code: Alles auswählen

result = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &myirq);
habe aber nach dem Auslesen der Variablen myirq einen falschen Interrupt bekommen, wie sich später herausstellte. Den Richtigen habe ich durch die Membervaribale "dev->irq" bekommen.
das sollte nicht so sein :roll: , viel mehr kann ich dazu jetzt auch nicht sagen ( eventuell ein Quirks deines Bios, Boards, PCI-Controller, Karte...Treiber :) ?, wenn das ein Problem der Karte ist, könntest du diesen mit pci_write_config_byte wieder "beheben")
Columbus hat geschrieben: Ich vermute mal, dass diese Struct automatisch initialisiert und gefüllt wird, aber warum steht das nicht im Rubini? (Erklärung: Rubini ist das Buch: "Linux Device Drivers" von Alessandro Rubini u.a, bin sonst sehr zufrieden damit)
Diese Struktur wird beim Bootvorgang, beim Scannen der PCI-Devices, initialisiert. Das Buch kenne ich leider nicht, aber aus Sicht des "Linux Device Drivers", sollte der Interrupt eigentlich über "pci_read_config_byte" ermittelt werden.
Columbus hat geschrieben: Dann die Erklärung, wie man der parallelen Schnittstelle einen IRQ herauskitzel kann:

Code: Alles auswählen

	unsigned long mask;

	mask = probe_irq_on();
	outb_p(0x10,short_base+2); /* enable reporting */
	outb_p(0x00,short_base);   /* clear the bit */
	outb_p(0xFF,short_base);   /* set the bit: interrupt! */
	outb_p(0x00,short_base+2); /* disable reporting */
	udelay(5);  /* give it some time */
	short_irq = probe_irq_off(mask);
Warum, erst mal, wird hier outb_p verwendet anstatt outb? Also warum unterbrechbar auf die Ports schreiben?
manche Geräte werden durch zuviel Information auf einmal verwirrt, uns geht es ja auch so :)
Diesen Geräten wird mit outb_p eine "Nachdenkpause" gegönnt.
Columbus hat geschrieben: Dann warum eine 16 auf die Adresse der Schnittstelle + 2? "short_base" ist doch die Adresse des Ports, an dem der Interrupt ausgelöst werden soll. Und warum wird dadurch die Mitteilung des IRQ erst möglich?
Dazu müßte man sich die Spezifikation der parallelen Schnittstelle anschauen und dazu bin ich jetzt zu faul

Gruß
gms

Spasswolf
Beiträge: 3472
Registriert: 30.11.2005 10:32:22
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Wald

Beitrag von Spasswolf » 11.06.2007 14:05:45

Manchmal ist outb_p auch das gleiche wie outb:

Code: Alles auswählen

$ grep -rn outb_p include/ | grep define | grep -E '\<outb\>'
include/asm-blackfin/io.h:93:#define outb_p(x,addr) outb(x,addr)
include/asm-sparc64/io.h:89:#define outb_p(__b, __addr) outb(__b, __addr)
include/asm-parisc/io.h:199:#define outb_p outb
include/asm-frv/io.h:176:#define outb_p(x,addr) outb(x,addr)
include/asm-h8300/io.h:224:#define outb_p(x,addr) outb(x,addr)
include/asm-alpha/io.h:490:#define outb_p               outb
include/asm-v850/io.h:52:#define outb_p(val, port)      outb((val), (port))
include/asm-arm/io.h:133:#define outb_p(val,port)       outb((val),(port))
include/asm-sparc/io.h:131:#define outb_p(__b, __addr)  outb(__b, __addr)
include/asm-arm26/io.h:368:#define outb_p(val,port)     outb((val),(port))
include/asm-ia64/io.h:411:# define outb_p               outb
include/asm-xtensa/io.h:143:#define outb_p(val, port)   outb((val), (port))
include/asm-m68knommu/io.h:125:#define outb_p(x,addr) outb(x,addr)
include/asm-ppc/io.h:326:#define outb_p(val, port)      outb((val), (port))


Benutzeravatar
Columbus
Beiträge: 1051
Registriert: 30.04.2002 15:25:02
Wohnort: Mainz
Kontaktdaten:

Re: Kernel-Modul Programmierung

Beitrag von Columbus » 11.06.2007 15:21:57

gms hat geschrieben: das sollte nicht so sein :roll: , viel mehr kann ich dazu jetzt auch nicht sagen ( eventuell ein Quirks deines Bios, Boards, PCI-Controller, Karte...Treiber :) ?, wenn das ein Problem der Karte ist, könntest du diesen mit pci_write_config_byte wieder "beheben")
Damit kann man aber nicht den IRQ des Gerätes einstellen oder. Man kann nur nachsehen, welchen IRQ wurde dem Gerät vom Bios zugwiesen und diesen Wert hier mit pci_write_config_byte in diesen Register reinschreiben? Es ist nicht möglich damit den IRQ vom Programmierer "umzubiegen"?!?

gms hat geschrieben: Dazu müßte man sich die Spezifikation der parallelen Schnittstelle anschauen und dazu bin ich jetzt zu faul
Kann ich nachvollziehen, der Treiber für die parallelen Schnittstelle scheint ja auch so das Krohnjuwel in Sachen Übersichtlichkeit in Linux-Kern zu sein?!? Habe ich mal gehört.
Zuletzt geändert von Columbus am 11.06.2007 15:59:23, insgesamt 1-mal geändert.
Die größten Kritiker der Elche,
waren früher selber welche.

F.W. Bernstein

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Re: Kernel-Modul Programmierung

Beitrag von gms » 11.06.2007 15:52:33

Columbus hat geschrieben: Damit kann man aber nicht den IRQ des Gerätes einstellen oder. Man kann nur nachsehen, welchen IRQ wurde dem Gerät vom Bios zugwiesen und diesen Wert hier mit pci_write_config_byte in diesen Register reinschreiben? Es ist nicht möglich damit den IRQ vom Programmierer "umzubiegen"?!?
Der IRQ wird ja beim Scannen nach PCI Geräten ausgehandelt und sollte daher auch korrekt gesetzt sein. Leider sitze ich gerade vor einer Windows-Kiste, glaube mich aber erinnern zu können, daß einige PCI-Treiber auf vergeßliche Karten mit dieser "Lösung" reagieren (siehe auch drivers/pci/quirks.c, oder mach ein 'grep -Ri "irq fixup" *' )

Benutzeravatar
Columbus
Beiträge: 1051
Registriert: 30.04.2002 15:25:02
Wohnort: Mainz
Kontaktdaten:

Beitrag von Columbus » 11.06.2007 18:04:08

@gms: Zur Sache mit den htmldocs da hast Du einen Fehler gemacht. Ich habe ihn auch nicht entdeckt, da die Schrift zu klein ist und habe es einfach in die Shell gepastet. Also es muss heisen:

Code: Alles auswählen

 make htmldocs 
. Und man braucht xmlto um das auszuführen.
Naja Montag :lol:

Gruss Christian
Die größten Kritiker der Elche,
waren früher selber welche.

F.W. Bernstein

Antworten