Get_pci.c |
Beispiel für Dos und Windows 95/98
/*
Ermittlung
einer KOLTER ELECTRONC Karte in C
Die
folgende Funktion zeigt eine Möglichkeit auf, wie die
I/O-Adresse
einer PCI-Karte ermittelt werden kann.
Als
Übergabewert der Funktion ist die Device ID der
entsprechenden
Karte anzugeben (Beispiel: PCI1616 = 0x0010).
Der
Rückgabewert der Funktion beinhaltet die I/O-Adresse
der
Karte oder 0, wenn keine Karte gefunden wurde bzw. keine
Plug'n
Play-Adresse vergeben wurde.
Wichtig:
Bei der Einbindung dieser Funktion in ein Programm
ist
zu beachten, dass für den Compiler der 386er
Befehlssatz
verwendet wird, da sonst Zugriffe
auf
erweiterten Register (ECX) nicht unterstützt werden.
*/
unsigned
long get_io_adr(unsigned int Device)
{
unsigned
int slot_no;
unsigned
long io_adr;
unsigned
long ven_dev;
unsigned
long KVENDOR;
io_adr
= 0;
KVENDOR
= Device; /* Device und VendorID
werden verknüpft*/
KVENDOR
= KVENDOR << 16 | 0x1001;
for
(slot_no = 0;(slot_no <= 0x00F8) && (io_adr == 0);slot_no +=
8)
{
asm
mov bx,slot_no
asm
mov di,0x0000 /* Alle PCI-Einheiten
werden */
asm
mov ax,0xb10a /* nach der entsprechenden
*/
asm
int 0x1a
/* PCI-Karte durchsucht. */
asm
mov ven_dev,ecx
if
(KVENDOR == ven_dev) /* Konnte die Karte gefunden */
{
/* werden, so wird die ent- */
asm
mov ax,0xb10a
/* sprechende I/O-Adresse */
asm
mov bx,slot_no
/* ausgelesen. */
asm
mov di,0x0010
asm
int 0x1a
asm
mov io_adr,ecx
}
}
io_adr
&= 0xFFFFFFF0; /* I/O-Adresse wird maskiert
*/
return(io_adr);
/* Rückgabe der I/O-Adresse */
}
Beispiel für Windows 95/98
/*
Die
folgende Funktion zeigt eine Möglichkeit auf, wie die
I/O-Adresse
einer KOLTER-Karte ermittelt werden kann.
Als
übergabewert der Funktion ist die Device ID der
entsprechenden
Karte anzugeben (Beispiel: PCI1616 = 0x0010).
Der
Rückgabewert der Funktion beinhaltet die I/O-Adresse
der
Karte oder 0, wenn keine Karte gefunden wurde bzw. keine
Plug'n
Play-Adresse vergeben wurde.
*/
#define VENDOR_KOLTER 0x1001
extern
unsigned long far pascal INT_1A( unsigned long reax,
unsigned
long rebx,
unsigned
long recx,
unsigned
long redi);
unsigned
long int PciGetIO(Device) {
unsigned
long reax;
unsigned
long rebx;
unsigned
long recx;
unsigned
long redi;
unsigned
long ret_ecx;
unsigned
int slot_no;
unsigned
long io_adr;
unsigned
long ven_dev;
unsigned
long KVENDOR;
io_adr = 0;
/*
Device und VendorID werden verknüpft */
KVENDOR
= ((long) Device << 16) | VENDOR_KOLTER;
for
(slot_no = 0;(slot_no <= 0x00F8) && (io_adr == 0);slot_no +=
8) {
ven_dev=INT_1A(0xb10aL,(long)
slot_no,0L,0L);
if
(KVENDOR == ven_dev)
io_adr=INT_1A(0xb10aL,(long)
slot_no,0L,0x0010L);
}
io_adr
&= 0xFFFFFFF0;
/* I/O-Adresse wird maskiert */
return(io_adr);
/* Rückgabe der I/O-Adresse */
}
C-Beispiel zur Überprüfung der I/O-Adresse
#include
<stdio.h>
#define
pLED port+0
#define
pSW port+0
void
main()
{
unsigned
long ret;
unsigned
int port;
port=ret=PciGetIO(0x0017);
printf("Die
Basis-Adresse ist:%lx\n",ret);
if(port==0)
exit(0);
}
I/O-Adresse in den PCI-Contoller schreiben
/*
Programm:
SETIO.EXE
PCI
Einstellungsprogramm in C
Programm
zur manuellen Einstellung der I/O-Adresse.
*/
#include
<dos.h>
#include
<stdio.h>
#include
<stdlib.h>
#include
<conio.h>
unsigned
int KPCI_einheit;
unsigned
long vendor;
unsigned
long adresse;
unsigned
int einheit;
unsigned
int device;
unsigned
long Kolter_device;
unsigned
long adresse4;
unsigned long pci_rd_cfg(unsigned int einheit, unsigned int adresse);
void pci_wr_cfg(unsigned int einheit, unsigned int adresse, unsigned long wert);
int
main (int argc,char *argv[])
{
if
(argc==1 || argv[1][0]=='?') {
printf("\nWARNUNG
!"
"\nDieses
Programm ermöglicht die manuelle Änderung der I/O-Adresse einer."
"\nPCI-Karte."
"\nDiese
Änderung kann zu Konflikten mit anderen Karten führen und einen"
"\nDatenverlust
oder physikalische Schäden des Rechners verursachen."
"\n\nFür
Schäden, die durch die Benutzung des Programms entstehen, übernimmt"
"\nder
Programmierer keine Haftung!");
printf("\n\n\nEingabebeispiele:"
"\n\n
SETIO 10 1D0 (Die Adresse der PCI1616-Karte wird auf 0x1D0 gesetzt)"
"\n\n
SETIO 10 1D0 x (wie oben,jedoch ohne Hinweistext)");
exit(0);
}
if
(argc > 4 || argc ==2) {
printf("\nFehlerhafte
Eingabe");
exit(0);
}
if
((argc == 3) || (argc == 4)) {
sscanf(argv[2],"%08lx",&adresse);
sscanf(argv[1],"%4x",&device);
if
((0x0100 < adresse < 0xffff) && !(adresse & 0x0000000F))
{
if(argc==3
|| (argc==4 && argv[3][0]!='x' && argv[3][0]!='X')) {
printf("\nWARNUNG
!"
"\nDieses
Programm ermöglicht die manuelle Änderung der I/O-Adresse einer."
"\nKOLTER
PCI-Karte."
"\nDiese
Änderung kann zu Konflikten mit anderen Karten führen und einen"
"\nDatenverlust
oder physikalische Schäden des Rechners verursachen."
"\n\nFür
Schäden, die durch die Benutzung des Programms entstehen, übernimmt"
"\nder
Programmierer keine Haftung!");
printf("\n\n\n
Adressänderung durchführen? (j/n)");
if
(getch() != 'j') exit(1);
printf("\n");
}
Kolter_device
= device;
Kolter_device
= Kolter_device << 16;
Kolter_device
|= 0x1001;
KPCI_einheit=0xFFFF;
for
(einheit=0;einheit<=0x00ff;einheit+=8) {
vendor
= pci_rd_cfg(einheit, 0x0000);
KPCI_einheit=(vendor==Kolter_device)?einheit:KPCI_einheit;
}
if(KPCI_einheit==0xFFFF)
printf("%cDie Karte konnte nicht gefunden werden\n",7);
else
{
printf("Die
voreingestellte Adresse war 0x%04X",(pci_rd_cfg(KPCI_einheit, 0x0010) &
0xFFFE));
pci_wr_cfg(KPCI_einheit,0x10,adresse);
printf("\nDie
neue Adresse ist 0x%04X",(pci_rd_cfg(KPCI_einheit, 0x0010) & 0xFFFE));
/*Bit
0 von Adresse 4 enabled (bei 1) die Ausdekodierung der I/O-Adresse*/
/*Dieses
Bit wird hiermit gelesen*/
adresse4=pci_rd_cfg(KPCI_einheit,
0x0004);
pci_wr_cfg(KPCI_einheit,
0x0004, adresse4 | 1);
}
}
}
}
Hinweis:
Bei manchen neuen Rechnern ist es erfoderlich,
den PCI-Bus nicht bis
Slot Nr. 8 sondern bis zur Slot-Nummer
FF abzupollen.