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.
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
Das wesentlich bessere Buch ist "Essential Linux Device Drivers" - wenn man sich schon so ein Buch leisten möchte.
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
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??
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
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??
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
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 .. }
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
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ß,
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.