mikrocontroller.net

Forum: PC-Programmierung C_Linux_PCI-Buskommunikation


Autor: Alibaba (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
System Linux
kernel 2.6.27.7


Hallo,

ich habe ein verständnissproblem mit dem Datentransfer, zwischen meiner 
Messkarte die auf dem Pci-X Bus hängt.

Und zwar geht es mir speziell um den Zugriff auf die 
PCI_Base1+0x00D8(r/w).
Ich habe bereits auf die Karte schreiben und lesen können dies geschah 
allerdings mit Treiberbefehlen die bereits vorhanden waren
(z.B. int rc = ioctl (hnd, ICS554_GET_IoInfo,pInfo);).
Bin momentan ratlos wie ich auf die PCI_Base1+0x00D8(r/w) schreiben 
kann.
Ich finde keinen Befehl oder ähnliches.

Jemand eine Idee?? Für tipps bin ich dankbar.

Autor: Oliver R. (superberti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

> Bin momentan ratlos wie ich auf die PCI_Base1+0x00D8(r/w) schreiben
> kann.
> Ich finde keinen Befehl oder ähnliches.

Wenn Dein Treiber diese Möglichkeit nicht bietet, dann geht es so 
einfach auch nicht.

>
> Jemand eine Idee?? Für tipps bin ich dankbar.

Du kommst dann nicht umhin

- den Treiber mit einem neuen IOCTL entsprechend anzupassen (falls du 
die Quellen dafür hast)

- selbst einen Treiber zu schreiben (dann bräuchte man das genaue 
Datenblatt für die Karte)

Das Standardwerk für solche Zwecke ist "Linux device drivers" in der 
dritten Auflage. Wahrscheinlich würde für Deine Zwecke ein einfacher 
char-driver reichen.
Es gibt allerdings auch inzwischen ein User-Mode-Treiber Framework, was 
für Deine Zwecke sicherlich einfacher ist, ich habe die Entwicklung 
hierbei allerdings nicht verfolgt und kann dazu wenig sagen.

Gruß, Oliver

Autor: Puppe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das wesentlich bessere Buch ist "Essential Linux Device Drivers" - wenn 
man sich schon so ein Buch leisten möchte.

Autor: Oliver R. (superberti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

> Das wesentlich bessere Buch ist "Essential Linux Device Drivers" - wenn
> man sich schon so ein Buch leisten möchte.

interessant, dieses Buch kannte ich noch gar nicht. Zu meiner 
Verteidigung muss ich allerdings sagen, dass dieses Buch auch noch gar 
nicht existierte, als ich meine letzten Treiber schrieb.
Habe ich glatt in meine Bestellliste aufgenommen!

Gruß, Oliver

Autor: Alibaba (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oliver R. schrieb:
> Wenn Dein Treiber diese Möglichkeit nicht bietet, dann geht es so
> einfach auch nicht.

Mein treiber bietet diese Möglichkeit. Ich besitze das 
Software/Operating Manuel allerdings kann ich nicht finden wie ich 
speziell auf diese Base/adresse schreiben kann. Normalerweise gibt es 
Funktionen wie

"StatusGet(hDevice, &Stat);" // diese fkt funktioniert mit IOCTL

mit denen kann man auf bestimmte Registerbänke zugreifen.

wie schreibt man einen neuen IOCTL?? muss ich unbedingt ein buch lesen?
oder gibt es Bibs oder ähnlichen mit Fkt. wie

PCIset(PCIadr,BaseNr,W/R?,ÜbergabeWert);

oder  stelle ich mir das zu leicht vor??

Autor: Oliver R. (superberti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

> Oliver R. schrieb:
>> Wenn Dein Treiber diese Möglichkeit nicht bietet, dann geht es so
>> einfach auch nicht.
>
> Mein treiber bietet diese Möglichkeit. Ich besitze das

Offensichtlich bietet er doch KEINE Möglichkeit auf diese Adresse zu 
schreiben/lesen.

> Software/Operating Manuel allerdings kann ich nicht finden wie ich
> speziell auf diese Base/adresse schreiben kann. Normalerweise gibt es
> Funktionen wie
>
> "StatusGet(hDevice, &Stat);" // diese fkt funktioniert mit IOCTL
>
> mit denen kann man auf bestimmte Registerbänke zugreifen.
>
> wie schreibt man einen neuen IOCTL?? muss ich unbedingt ein buch lesen?

Du kannst auf die Hardware NUR mit einem Treiber zugreifen! Einen neuen 
IOCTL schreibst Du, indem du den Treiber veränderst, neu kompilierst und 
das Treibermodul austauschst bzw. den Kernel. Dazu brauchst Du die 
Treiberquellen und ein Kernel-compilierfähiges System.
Ja, ein Buch hilft dabei weiter, es gibt aber auch im Netz viele 
Anleitungen. Im Treiber könnte die IOCTL-Behandlungsfunktion ungefähr so 
aussehen:

/*
 * ioctl entry point.
 */
static int mein_ioctl(struct inode* inode, struct file* file, unsigned 
int cmd, unsigned long arg )
{
[...]
}

Diese Stelle muss man finden und um einen IOCTL ergänzen, der auf das 
gewünschte Register schreibt/liest.

> oder gibt es Bibs oder ähnlichen mit Fkt. wie
>
> PCIset(PCIadr,BaseNr,W/R?,ÜbergabeWert);

Auf die Hardware direkt zugreifen darf nur der Kernel und seine 
Treibermodule. Aus Deiner Anwendung (die im User-Mode läuft) heraus geht 
das nicht (Ausnahmen s. meine erste Mail).

>
> oder  stelle ich mir das zu leicht vor??

Bedauerlicherweise: Ja!

Gruß,

Oliver

Autor: Alibaba (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oliver R. schrieb:
> Im Treiber könnte die IOCTL-Behandlungsfunktion ungefähr so
> aussehen:
>
> /*
>  * ioctl entry point.
>  */
.
.
.

Ich glaube da habe ich etwas gefunden im header hardwlow.h.

int ADCOverRangeReset (HANDLE hnd, STATUS *pStat)
{
  int rc;

  rc = ioctl (hnd, Hardw_SET_ADCOverRangeReset, pStat);
  Hardw_FORMAT_RESULT(hnd,rc,"ADCOverRangeReset");
  return((int)rc);
}

könnte das eine Behandlungstrucktur sein?
"SET_ADCOverRangeReset" finde ich ich in einen anderen header nämlich im

Hardwioctl.h
#define..
.
.

"#define Hardw_GET_OverflowDone          _IOW(Hardw_IO_MAGIC, 134, u32)"
.
.


und in der Hardwload.c
case
.
.

case Hardw_SET_ADCOverRangeReset:
{
  if(copy_from_user(&val64,(void*)arg,sizeof(u64))) {
  return -EFAULT;
}
 PDEBUG("hardw(ioctl_Hardw):    SET_ADCOverRangeReset0x%llx\n",val64);

WRITE_ICSDEV_U32(board, STATUS_OFFSET, (u32)(0xFLL & val64));
    break;
  }

.
.


Ich finde allerdings nichts was auf eine PCI_Adresse hindeutet oder irre 
ich mich da??

Autor: Oliver R. (superberti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi nochmal,
>
> Ich glaube da habe ich etwas gefunden im header hardwlow.h.
>
> int ADCOverRangeReset (HANDLE hnd, STATUS *pStat)
> {
>   int rc;
>
>   rc = ioctl (hnd, Hardw_SET_ADCOverRangeReset, pStat);
>   Hardw_FORMAT_RESULT(hnd,rc,"ADCOverRangeReset");
>   return((int)rc);
> }

Nein, das ist eine Usermode-Funktion, da ioctl() auch eine 
Usermode-Funktion ist. Sie dient zur Kommunikation mit dem Treiber bei 
"unüblichen" Kommandos, sprich Spezialfunktionen, die über das 
Lesen/Schreiben hinausgehen. Zur Identifikation benutzen aber sowohl 
Usermode-Programm als auch der Treiber eine gemeinsame IOCTL-Definition 
(s.u.)

>
> könnte das eine Behandlungstrucktur sein?
> "SET_ADCOverRangeReset" finde ich ich in einen anderen header nämlich im
>
> Hardwioctl.h
> #define..
> .
> .
>
> "#define Hardw_GET_OverflowDone          _IOW(Hardw_IO_MAGIC, 134, u32)"
> .

Hier wird in der Tat ein IOCTL definiert, hier könntest Du einen eigenen 
IOCTL hinzufügen.


>
> und in der Hardwload.c
> case
> .
> .
>
> case Hardw_SET_ADCOverRangeReset:
> {
>   if(copy_from_user(&val64,(void*)arg,sizeof(u64))) {
>   return -EFAULT;
> }
>  PDEBUG("hardw(ioctl_Hardw):    SET_ADCOverRangeReset0x%llx\n",val64);
>
> WRITE_ICSDEV_U32(board, STATUS_OFFSET, (u32)(0xFLL & val64));
>     break;
>   }
>

Ja, das könnte die IOCTL-Behandlungsfunktion sein. Du hast leider nicht 
den Funktionskopf mit angehangen.

>
> Ich finde allerdings nichts was auf eine PCI_Adresse hindeutet oder irre
> ich mich da??

Ich kenne ja den Treiber nicht, aber hier sieht es so aus, als ob die 
Variable "board" auf die Basisadresse der PCI-Karte zeigt. Deren 
Register/Speicher werden in den Adressraum des Kernels eingeblendet. 
"STATUS_OFFSET" scheint dann der Offset zu "board" zu sein und 
adressiert ein bestimmtes Register. Du könntest also evtl. mit 
"WRITE_ICSDEV_U32(board,0x00D8,Wert)" einen uint an die von Dir 
gewünschte Adresse schreiben. Schau im Code nach, was die Funktion genau 
macht.

Gruß,

Oliver

Autor: Alibaba (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oliver R. schrieb:
> Ja, das könnte die IOCTL-Behandlungsfunktion sein. Du hast leider nicht
> den Funktionskopf mit angehangen.

danke für die Erklärung.

Hier noch der Kopf.
switch (cmd)
{
 case..:
 ..
 case
 ..
}

Autor: Alibaba (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube ich habe da was gefunden:

//IOCTL wird definiert/////////////////////////////////7

Hardw.h
#define FIFO_CLOCK_OFFSET                    0xD8




//IOCTL-Behandlungsfunktion////////////////////////////
Hardwload.h:

switch (cmd)
{


  case Hardw_SET_FifoClock:
  {
    u32 dwval, i;

    if(copy_from_user(&val64,(void*)arg,sizeof(u64))) {
      return -EFAULT;
    }
    PDEBUG("Hardw(ioctl_Hardw): Hardw_SET_FifoClock 0x%llx\n",val64);
    dwval = (u32)(0xFFFFFFFFLL & val64);
    for(i = 0; i < 32; i++) {
      WRITE_ICSDEV_U32(board, FIFO_CLOCK_OFFSET, (u32)(0x1L & dwval));
      udelay(10);
      dwval >>= 1;
    }
    break;
  }



}


//Usermode-Funktion///////////////////////////////////////
Hardwlow.c
int HardwFifoClockSet (HANDLE hnd, unsigned long long *pClock)
{
  int rc;

  rc = ioctl (hnd, Hardw_SET_FifoClock, pClock);
  ICS_FORMAT_RESULT(hnd,rc,"FifoClockSet");
  return((int)rc);
}



es deutet allerdings nichts bis auf
#define FIFO_CLOCK_OFFSET                    0xD8

darauf hin, das es die BASE1+0X00D8 ist(FifoLevelControl).
Könnte trotzdem so sein das sei was ich suche??

Nochmal danke für die gute Hilfe

Autor: Oliver R. (superberti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

>
> es deutet allerdings nichts bis auf
> #define FIFO_CLOCK_OFFSET                    0xD8
>
> darauf hin, das es die BASE1+0X00D8 ist(FifoLevelControl).
> Könnte trotzdem so sein das sei was ich suche??

Schwer zu sagen, FIFO clock und FIFO level hören sich ja doch 
unterschiedlich an. Schau Dir mal im Treiber an, wo die Variable "board" 
belegt wird. Evtl. in einer Zeile wie dieser:

board = pci_resource_start(dev, BAR3);

Gruß,

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.