Bustreiber werden auch als „Bus Agnostic Driver“ bezeichnet. Der Windows- CE-Treiber besteht aus folgenden Dateien:
| HANDLE PCI_Init(LPCTSTR RegistryPath, DWORD dwBusContect) { 1. hkDevice = OpenDeviceKey(RegistryPath); 2. dwStatus = DDKReg_GetWindowInfo(hkDevice, &wini); 3. dwStatus = DDKReg_GetIsrInfo(hkDevice, &isri); 4. dwStatus = DDKReg_GetPciInfo(hkDevice, &pcii); 5. hloadICHandle = LoadIntChainHandler(isri.szIsrDll, isri.szIsrHandler, (BYTE)isri.dwIrq); 6. TransBusAddrToStatic(PCIBus, PCI_BusNumber, PortAddress, PCI_BusLength, &inIoSpace, &PhysAddr); 7. KernelLibIoControl(hloadICHandle, IOCTL_GIISR_INFO, &Info, sizeof (Info), NULL, 0, NULL) 8. hEvent = CreateEvent (NULL, FALSE,FALSE, NULL); 9. hThreadIst = CreateThread (NULL, 0, IsThread, (LPVOID)0,0, &lThreadIstID); 10. BOOL IntInitialOK = InterruptInitialize (SysInterrupt, hEvent, NULL, 0); } |
Listing 2. PCI_Init ist die wichtigste und aufwendigste Funktion der Treiber-Quellcodedatei PCI_ ParallelPort_ Driver.cpp. Die Bedeutung der Aufrufe und Datenstrukturen ist im Artikel beschrieben.
Für die Initialisierung des PCI-Karten-Treibers sind zahlreiche APIs notwendig. Die zehn Quellcode- Zeilen innerhalb des PCI_Init- Blocks von Listing 2 sind durchnummeriert. Die Datenstrukturen in den einzelnen Zeilen haben folgende Bedeutung:
1. Die Registry wird mit dem in Bild 3 gezeigten Schlüssel [HKLM\Drivers\ Active\03] geöffnet und ausgelesen. Der Treiber ist aktiv und kann verwendet werden.
2. Die Struktur wini enthält die Informationen, die im Registry-Schlüssel (..\Instance\ MSC9815CV..) durch den PCIBus.dll-Treiber abgelegt wurden. Der wichtigste Parameter ist die IOAdresse des Controllers. Über diese Adresse kann der Controller programmiert werden.
3. Die Struktur isri enthält alle Parameter, um für den Treiber die Interrupt- Schnittstelle (IRQ=10, Sys- Intr=0x18 zu implementieren.
4. Die Struktur pcii enthält PCI-Parameter, z.B. wieviel Instanzen es von diesem Treiber gibt.
5. Diese Funktion ersetzt die Standard- ISR durch den dynamisch ladbaren ISRHandler(), der sich im Treiber „giisr.dll“ befindet.
6. Die physikalische Adresse des Controllers wird erzeugt.
7. Die Datenstruktur IOCTL_GIISR_ INFO enthält zwei wichtige Parameter. Der Parameter Info.PortAddr gibt das Interrupt-Register im Controller an und der Parameter Info.Mask=4 das entspechende Bit (Enable/Disable Interrupt). Anstehende Interrupts werden durch ein Bit im Register DSR des MSC9815CV-Controllers angezeigt.
8. Um einen IST über einen HW-Interrupt zu signalisieren, benötigt man ein Event-Objekt.
9. Es wird der IST erzeugt und der Befehl WaitForSingleObjekt(hEvent) ausgeführt. Der Thread ist bereit, Interrupts entgegenzunehmen.
10. Dem Kernel wird mitgeteilt, dass Interrupts bearbeitet werden können. Dazu wird die SysInterrupt-ID übergeben.
Der PCI-Bus-Treiber (PCIBus.dll) ist optimal gerüstet und vorbereitet, um neu gesteckte PCI-Karten zu erkennen und sie anschließend zu registrieren. Wird eine funktionsfähige PCI-Karte vom PCI-Bus-Treiber erkannt, erfolgt das Auslesen der PCI-Parameter im Controller und ein Vergleich mit den Parametern in der Registry unter [..\PCI\Template\ MSC9815CV].
Sind einige dieser Parameter identisch, generiert der PCI-Bus- Treiber einen [..\PCI\Instance\MSC- 9815CV]-Eintrag. Damit hat der PCITreiber- Entwickler die schwierigste Hürde überwunden und kann mit der Entwicklung der eigentlichen Treiberanwendung beginnen.