Autor Thema: Windowstreiber-Schnittstelle  (Gelesen 18756 mal)

OsDevNewbie

  • Beiträge: 282
    • Profil anzeigen
    • YourOS Kernel
Gespeichert
« am: 15. January 2013, 18:24 »
Hallo,
gibt es irgendwo eine Dokumentation über die Treiber-Schnittstelle von Windows? Ich habe nämlich vor die Treiber von Windows für meinen Kernel zu benutzen, somit hat man auf jeden Fall einen funktionierenden Treiber für die meisten Geräte. Ich hab bis jetzt immer nur etwas über so ein Treiber-SDK gefunden.

Ich hoffe ihr könnt mir helfen. Danke.
Viele Grüsse
OsDevNewbie

Ein Computer ohne Betriebsystem ist nicht mehr wert als ein Haufen Schrott.
Ein Computer ist eine Maschine, die einem Lebewesen das kostbarste klaut, was sie selber nicht hat:
DIE ZEIT DES LEBENS

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 15. January 2013, 20:48 »
Für einen eigenen kleinen netten Kernel: Vergiss es.

Aber wenn du es ernst meinst, kannst du versuchen, bei ReactOS mitzuhelfen, die probieren genau das.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 16. January 2013, 03:45 »
Hallo,

die Dokumentation ist frei verfügbar, hieß früher Windows Driver Development Kit (DDK), heißt jetzt Windows Driver Kit (WDK) und gibt es hier zum freien Download.

Gruß,
Svenska

Martin Erhardt

  • Beiträge: 165
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 16. January 2013, 17:25 »
Was man vllt machen könnte wäre die Treiber für Linux zu portieren um eine Vielzahl an GraKa und Netzwerkkarten zu unterstützen. Dadurch das die LinuxTreiber als Modul in Ring 0 laufen brauchen sie keine so große Schnittstelle zum Kernel weil sie ua. die IOPorts ansteuern können. Vor allem aber sind die Linux Treiber z.T. OpenSource so kann man gezielt Stellen modifizieren auskommentieren et cetera was bei BLOBs natürlich nicht geht.

Ich will allerdings den Mund nicht zu voll nehmen. Ich werde dieses MegaProjekt erst in Angriff nehmen wenn ich nicht mehr weiß was ich sonst noch in meinen Kernel aufnehmen kann.
Da ich davon aber noch Lichtjahre entfernt bin(Mein Kernel kann noch nicht mal Paging :oops:) mache ich mir um die Details noch keine Sorgen :-D

Ich will an dieser Stelle ausdrücklich sagen das die GraKa Treiber von Linux teilweise sehr mit dem X Window Server verwoben sind. Die Neueren Graka Treiber werden aber volle Funktionalität besitzen weil Wayland http://de.wikipedia.org/wiki/Wayland_(Anzeige-Server)

Hier habe ich noch eine kleine Linksammlung:
http://nouveau.freedesktop.org/wiki/  (2D Nvidia Graka Open source Treiber)
http://www.mesa3d.org/ (3D Graka Open source Treiber und OpenGl Implementierung)
http://www.x.org/docs/AMD/ (Spezifikationen zum Selberschreiben eines AMD Treibers)
http://www.thinkwiki.org/wiki/Fglrx (ATI Graka Opensource Treiber)
http://de.wikipedia.org/wiki/Reverse_Engineering (Mit Reverse Engineering kann man durch Debugging und Dekomplieren von WindowsTreibern den Quellcode herausfinden und anhand von diesem oder dem Linux Quellcode die Spezifikationen herausfinden um dann anhand von diesen selbst einen Treiber zu schreiben.)
« Letzte Änderung: 16. January 2013, 17:29 von Martin Erhardt »

DerHartmut

  • Beiträge: 236
    • Profil anzeigen
    • Mein Blog
Gespeichert
« Antwort #4 am: 16. January 2013, 18:26 »
Es sei an dieser Stelle an das CDI verwiesen.
$_="krJhruaesrltre c a cnp,ohet";$_.=$1,print$2while s/(..)(.)//;
Nutze die Macht, nutze Perl ;-)

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 16. January 2013, 18:38 »
Was man vllt machen könnte wäre die Treiber für Linux zu portieren um eine Vielzahl an GraKa und Netzwerkkarten zu unterstützen. Dadurch das die LinuxTreiber als Modul in Ring 0 laufen brauchen sie keine so große Schnittstelle zum Kernel weil sie ua. die IOPorts ansteuern können.
Falsch. Tatsächlich können Linuxtreiber auf jede nicht lokale Funktion im Linuxkernel zugreifen, wodurch die Schnittstelle extrem breit wird. Selbstverständlich machen sie auch ausgiebig Gebrauch davon, weil man gemeinsame Funktionalität nicht in jeden Treiber kopieren will, sondern nur einmal pro Subsystem haben. Dadurch musst du ziemlich viele Linux-Kernelfunktionen nachbauen, bis du einen Treiber erfolgreich gebaut bekommst.

Das andere Problem ist, dass die Schnittstellen innerhalb von Kernel nicht stabil sind, das heißt, selbst wenn du das einmal erfolgreich zum Laufen bringen solltest, kannst du nicht einfach irgendwann den Treiber auf die nächste Linuxversion updaten, sondern du musst dann alle in Linux geänderten Schnittstellen auch wieder nachziehen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Martin Erhardt

  • Beiträge: 165
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 16. January 2013, 18:44 »
Was man vllt machen könnte wäre die Treiber für Linux zu portieren um eine Vielzahl an GraKa und Netzwerkkarten zu unterstützen. Dadurch das die LinuxTreiber als Modul in Ring 0 laufen brauchen sie keine so große Schnittstelle zum Kernel weil sie ua. die IOPorts ansteuern können.
Falsch. Tatsächlich können Linuxtreiber auf jede nicht lokale Funktion im Linuxkernel zugreifen, wodurch die Schnittstelle extrem breit wird. Selbstverständlich machen sie auch ausgiebig Gebrauch davon, weil man gemeinsame Funktionalität nicht in jeden Treiber kopieren will, sondern nur einmal pro Subsystem haben. Dadurch musst du ziemlich viele Linux-Kernelfunktionen nachbauen, bis du einen Treiber erfolgreich gebaut bekommst.

Das andere Problem ist, dass die Schnittstellen innerhalb von Kernel nicht stabil sind, das heißt, selbst wenn du das einmal erfolgreich zum Laufen bringen solltest, kannst du nicht einfach irgendwann den Treiber auf die nächste Linuxversion updaten, sondern du musst dann alle in Linux geänderten Schnittstellen auch wieder nachziehen.
Ersteres überrascht mich. Um wie viele Submodule globale funktionen geht es ungefähr?
« Letzte Änderung: 16. January 2013, 18:48 von Martin Erhardt »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 16. January 2013, 19:14 »
Probier es aus. Nimm einfach einen beliebigen Linxutreiber und versuch ihn einzeln zu kompilieren. Dann zähl die Warnungen über implizite Deklarationen.

Als ich es vor ein paar Jahren probiert habe, waren es so viele, dass ich den Plan sofort aufgegeben habe. ;)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Martin Erhardt

  • Beiträge: 165
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 16. January 2013, 19:34 »
Mmh ich kriegs nich richtig kompiliert(make: *** No targets specified and no makefile found.  Stop) aber egal.

Ich hab auf jeden fall mal sone source File geöffnet und mich gefragt ob man sonen *haufen ehrlich gesagt portieren sollte. :-)
PUSH_DATA (push, 0x10000001);
PUSH_DATA (push, 0x0423c788);
PUSH_DATA (push, 0x10000205);
PUSH_DATA (push, 0x0423c788);
PUSH_DATA (push, 0xc0800401);
PUSH_DATA (push, 0x00200780);
PUSH_DATA (push, 0xc0830405);
PUSH_DATA (push, 0x00200780);
PUSH_DATA (push, 0xc0860409);
PUSH_DATA (push, 0x00200780);
PUSH_DATA (push, 0xe0810601);
PUSH_DATA (push, 0x00200780);
PUSH_DATA (push, 0xe0840605);
PUSH_DATA (push, 0x00204780);
PUSH_DATA (push, 0xe0870609);
PUSH_DATA (push, 0x00208780);
PUSH_DATA (push, 0xb1000001);
PUSH_DATA (push, 0x00008780);
PUSH_DATA (push, 0xb1000205);
PUSH_DATA (push, 0x00014780);
PUSH_DATA (push, 0xb1000409);
PUSH_DATA (push, 0x00020780);
PUSH_DATA (push, 0x90000409);
PUSH_DATA (push, 0x00000780);
PUSH_DATA (push, 0xc0020001);
PUSH_DATA (push, 0x00000780);
PUSH_DATA (push, 0xc0020205);
PUSH_DATA (push, 0x00000780);
PUSH_DATA (push, 0xc0890009);
PUSH_DATA (push, 0x00000788);
PUSH_DATA (push, 0xc08a020d);
PUSH_DATA (push, 0x00000788);
PUSH_DATA (push, 0xc08b0801);
PUSH_DATA (push, 0x00200780);
PUSH_DATA (push, 0xc08e0805);
PUSH_DATA (push, 0x00200780);
PUSH_DATA (push, 0xc0910809);
PUSH_DATA (push, 0x00200780);
PUSH_DATA (push, 0xe08c0a01);
PUSH_DATA (push, 0x00200780);
PUSH_DATA (push, 0xe08f0a05);
PUSH_DATA (push, 0x00204780);
PUSH_DATA (push, 0xe0920a09);
PUSH_DATA (push, 0x00208780);
PUSH_DATA (push, 0xb1000001);
PUSH_DATA (push, 0x00034780);
PUSH_DATA (push, 0xb1000205);
PUSH_DATA (push, 0x00040780);
PUSH_DATA (push, 0xb1000409);
PUSH_DATA (push, 0x0004c780);
PUSH_DATA (push, 0x90000409);
PUSH_DATA (push, 0x00000780);
PUSH_DATA (push, 0xc0020001);
PUSH_DATA (push, 0x00000780);
PUSH_DATA (push, 0xc0020205);
PUSH_DATA (push, 0x00000780);
PUSH_DATA (push, 0xc0940011);
PUSH_DATA (push, 0x00000788);
PUSH_DATA (push, 0xc0950215);
PUSH_DATA (push, 0x00000789);

/* fetch only VTX_ATTR[0,8,9].xy */
BEGIN_NV04(push, NV50_3D(VP_ATTR_EN(0)), 2);
PUSH_DATA (push, 0x00000003);
PUSH_DATA (push, 0x00000033);
BEGIN_NV04(push, NV50_3D(VP_REG_ALLOC_RESULT), 1);
PUSH_DATA (push, 6);
BEGIN_NV04(push, NV50_3D(VP_RESULT_MAP_SIZE), 2);
PUSH_DATA (push, 8);
PUSH_DATA (push, 4); /* NV50_3D_VP_REG_ALLOC_TEMP */
BEGIN_NV04(push, NV50_3D(VP_ADDRESS_HIGH), 2);
PUSH_DATA (push, (pNv->scratch->offset + PVP_OFFSET) >> 32);
PUSH_DATA (push, (pNv->scratch->offset + PVP_OFFSET));
BEGIN_NV04(push, NV50_3D(CB_DEF_ADDRESS_HIGH), 3);
PUSH_DATA (push, (pNv->scratch->offset + PVP_DATA) >> 32);
PUSH_DATA (push, (pNv->scratch->offset + PVP_DATA));
PUSH_DATA (push, (CB_PVP << NV50_3D_CB_DEF_SET_BUFFER__SHIFT) | 256);
BEGIN_NV04(push, NV50_3D(SET_PROGRAM_CB), 1);
PUSH_DATA (push, 0x00000001 | (CB_PVP << 12));
BEGIN_NV04(push, NV50_3D(VP_START_ID), 1);
PUSH_DATA (push, 0);

PUSH_DATAu(push, pNv->scratch, PFP_OFFSET + PFP_S, 6);
PUSH_DATA (push, 0x80000000);
PUSH_DATA (push, 0x90000004);
PUSH_DATA (push, 0x82010200);
PUSH_DATA (push, 0x82020204);
PUSH_DATA (push, 0xf6400001);
PUSH_DATA (push, 0x0000c785);
PUSH_DATAu(push, pNv->scratch, PFP_OFFSET + PFP_C, 16);
PUSH_DATA (push, 0x80000000);
PUSH_DATA (push, 0x90000004);
PUSH_DATA (push, 0x82030210);
PUSH_DATA (push, 0x82040214);
PUSH_DATA (push, 0x82010200);
PUSH_DATA (push, 0x82020204);
PUSH_DATA (push, 0xf6400001);
PUSH_DATA (push, 0x0000c784);
PUSH_DATA (push, 0xf0400211);
PUSH_DATA (push, 0x00008784);
PUSH_DATA (push, 0xc0040000);
PUSH_DATA (push, 0xc0040204);
PUSH_DATA (push, 0xc0040409);
PUSH_DATA (push, 0x00000780);
PUSH_DATA (push, 0xc004060d);
PUSH_DATA (push, 0x00000781);
PUSH_DATAu(push, pNv->scratch, PFP_OFFSET + PFP_CCA, 16);
PUSH_DATA (push, 0x80000000);
PUSH_DATA (push, 0x90000004);
PUSH_DATA (push, 0x82030210);
PUSH_DATA (push, 0x82040214);
PUSH_DATA (push, 0x82010200);
PUSH_DATA (push, 0x82020204);
PUSH_DATA (push, 0xf6400001);
PUSH_DATA (push, 0x0000c784);
PUSH_DATA (push, 0xf6400211);
PUSH_DATA (push, 0x0000c784);
PUSH_DATA (push, 0xc0040000);
PUSH_DATA (push, 0xc0050204);
PUSH_DATA (push, 0xc0060409);
PUSH_DATA (push, 0x00000780);
PUSH_DATA (push, 0xc007060d);
PUSH_DATA (push, 0x00000781);
PUSH_DATAu(push, pNv->scratch, PFP_OFFSET + PFP_CCASA, 16);
PUSH_DATA (push, 0x80000000);
PUSH_DATA (push, 0x90000004);
PUSH_DATA (push, 0x82030200);
PUSH_DATA (push, 0x82040204);
PUSH_DATA (push, 0x82010210);
PUSH_DATA (push, 0x82020214);
PUSH_DATA (push, 0xf6400201);
PUSH_DATA (push, 0x0000c784);
PUSH_DATA (push, 0xf0400011);
PUSH_DATA (push, 0x00008784);
PUSH_DATA (push, 0xc0040000);
PUSH_DATA (push, 0xc0040204);
PUSH_DATA (push, 0xc0040409);
PUSH_DATA (push, 0x00000780);
PUSH_DATA (push, 0xc004060d);
PUSH_DATA (push, 0x00000781);
PUSH_DATAu(push, pNv->scratch, PFP_OFFSET + PFP_S_A8, 10);
PUSH_DATA (push, 0x80000000);
PUSH_DATA (push, 0x90000004);
PUSH_DATA (push, 0x82010200);
PUSH_DATA (push, 0x82020204);
PUSH_DATA (push, 0xf0400001);
PUSH_DATA (push, 0x00008784);
PUSH_DATA (push, 0x10008004);
PUSH_DATA (push, 0x10008008);
PUSH_DATA (push, 0x1000000d);
PUSH_DATA (push, 0x0403c781);
PUSH_DATAu(push, pNv->scratch, PFP_OFFSET + PFP_C_A8, 16);
PUSH_DATA (push, 0x80000000);
PUSH_DATA (push, 0x90000004);
PUSH_DATA (push, 0x82030208);
PUSH_DATA (push, 0x8204020c);
PUSH_DATA (push, 0x82010200);
PUSH_DATA (push, 0x82020204);
PUSH_DATA (push, 0xf0400001);
PUSH_DATA (push, 0x00008784);
PUSH_DATA (push, 0xf0400209);
PUSH_DATA (push, 0x00008784);
PUSH_DATA (push, 0xc002000d);
PUSH_DATA (push, 0x00000780);
PUSH_DATA (push, 0x10008600);
PUSH_DATA (push, 0x10008604);
PUSH_DATA (push, 0x10000609);
PUSH_DATA (push, 0x0403c781);
PUSH_DATAu(push, pNv->scratch, PFP_OFFSET + PFP_NV12, 24);
PUSH_DATA (push, 0x80000008);
PUSH_DATA (push, 0x90000408);
PUSH_DATA (push, 0x82010400);
PUSH_DATA (push, 0x82020404);
PUSH_DATA (push, 0xf0400001);
PUSH_DATA (push, 0x00008784);
PUSH_DATA (push, 0xc0800014);
PUSH_DATA (push, 0xb0810a0c);
PUSH_DATA (push, 0xb0820a10);
PUSH_DATA (push, 0xb0830a14);
PUSH_DATA (push, 0x82010400);
PUSH_DATA (push, 0x82020404);
PUSH_DATA (push, 0xf0400201);
PUSH_DATA (push, 0x0000c784);
PUSH_DATA (push, 0xe084000c);
PUSH_DATA (push, 0xe0850010);
PUSH_DATA (push, 0xe0860015);
PUSH_DATA (push, 0x00014780);
PUSH_DATA (push, 0xe0870201);
PUSH_DATA (push, 0x0000c780);
PUSH_DATA (push, 0xe0890209);
PUSH_DATA (push, 0x00014780);
PUSH_DATA (push, 0xe0880205);
PUSH_DATA (push, 0x00010781);

/* HPOS.xy = ($o0, $o1), HPOS.zw = (0.0, 1.0), then map $o2 - $o5 */
BEGIN_NV04(push, NV50_3D(VP_RESULT_MAP(0)), 2);
PUSH_DATA (push, 0x41400100);
PUSH_DATA (push, 0x05040302);
BEGIN_NV04(push, NV50_3D(POINT_SPRITE_ENABLE), 1);
PUSH_DATA (push, 0x00000000);
BEGIN_NV04(push, NV50_3D(FP_INTERPOLANT_CTRL), 2);
PUSH_DATA (push, 0x08040404);
PUSH_DATA (push, 0x00000008); /* NV50_3D_FP_REG_ALLOC_TEMP */
BEGIN_NV04(push, NV50_3D(FP_ADDRESS_HIGH), 2);
PUSH_DATA (push, (pNv->scratch->offset + PFP_OFFSET) >> 32);
PUSH_DATA (push, (pNv->scratch->offset + PFP_OFFSET));
BEGIN_NV04(push, NV50_3D(CB_DEF_ADDRESS_HIGH), 3);
PUSH_DATA (push, (pNv->scratch->offset + PFP_DATA) >> 32);
PUSH_DATA (push, (pNv->scratch->offset + PFP_DATA));
PUSH_DATA (push, (CB_PFP << NV50_3D_CB_DEF_SET_BUFFER__SHIFT) | 256);
BEGIN_NV04(push, NV50_3D(SET_PROGRAM_CB), 1);
PUSH_DATA (push, 0x00000031 | (CB_PFP << 12));

BEGIN_NV04(push, NV50_3D(SCISSOR_ENABLE(0)), 1);
PUSH_DATA (push, 1);

BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2);
PUSH_DATA (push, 8192 << NV50_3D_VIEWPORT_HORIZ_W__SHIFT);
PUSH_DATA (push, 8192 << NV50_3D_VIEWPORT_VERT_H__SHIFT);
/* NV50_3D_SCISSOR_VERT_T_SHIFT is wrong, because it was deducted with
* origin lying at the bottom left. This will be changed to _MIN_ and _MAX_
* later, because it is origin dependent.
*/
BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2);
PUSH_DATA (push, 8192 << NV50_3D_SCISSOR_HORIZ_MAX__SHIFT);
PUSH_DATA (push, 8192 << NV50_3D_SCISSOR_VERT_MAX__SHIFT);
BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2);
PUSH_DATA (push, 8192 << NV50_3D_SCREEN_SCISSOR_HORIZ_W__SHIFT);
PUSH_DATA (push, 8192 << NV50_3D_SCREEN_SCISSOR_VERT_H__SHIFT);

return TRUE;
« Letzte Änderung: 16. January 2013, 20:09 von Martin Erhardt »

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 16. January 2013, 20:09 »
Ich hab auf jeden fall mal sone source File geöffnet und mich gefragt ob man sonen *haufen ehrlich gesagt portieren sollte.
Mach es besser, dann diskutieren wir weiter. Die Leute arbeiten ganz ohne Dokumentation.

Und nein, ohne Makefile funktioniert make nicht.

OsDevNewbie

  • Beiträge: 282
    • Profil anzeigen
    • YourOS Kernel
Gespeichert
« Antwort #10 am: 16. January 2013, 22:16 »
Danke für eure schnelle Antwort. Wahrscheinlich werde ich erstmal das CDI verwenden und vielleicht erstmals die Portierung von Windows-Treiber in den Hintergrund verschieben :-).
Viele Grüsse
OsDevNewbie

Ein Computer ohne Betriebsystem ist nicht mehr wert als ein Haufen Schrott.
Ein Computer ist eine Maschine, die einem Lebewesen das kostbarste klaut, was sie selber nicht hat:
DIE ZEIT DES LEBENS

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 18. January 2013, 13:47 »
Hallo,


... Selbstverständlich machen sie auch ausgiebig Gebrauch davon, ...
War nicht gerade das der Haupt-Kritik-Punkt den die Pioniere der Micro-Kernel an den damaligen OSen hatten? Und in den mindestens 30 Jahren haben die OS-Dever die Monolithen schreiben nichts gelernt? Es ist ja nicht so das mich das überraschen tät (so sind Menschen eben) aber entsetzt bin ich da jetzt doch.

Das andere Problem ist, dass die Schnittstellen innerhalb von Kernel nicht stabil sind
Das ist aus meiner persönlichen Sicht der größte Kritikpunkt am Linux-Kernel überhaupt (mal davon abgesehen das er ein Monolith ist ;) ) und ich wette viele Firmen die Hardware herstellen sehen das ähnlich.

Mal vom Aufwand abgesehen, da es sich beim Linux-Kernel ja um GPL-Code handelt sollte es doch für ein Micro-Kernel-OS möglich (und auch legal) sein alles was man für einen bestimmten Treiber benötigt aus dem Linux-Kernel komplett hinaus zu filetieren und als eigenständigen User-Mode-Prozess laufen zu lassen oder? Man müsste doch eigentlich nur die Teile des Linux-Codes anpassen/ersetzen die das Treiber-Management (z.B. IRQ-Handler an/ab-melden oder HW-Speicher ein/aus-blenden) betreffen oder?


Zumindest steckt in diesem Thread ein wesentliches Kernproblem von "Hobby"-OSen: wie unterstütze ich mit möglichst vertretbaren Aufwand möglichst viel Hardware?
Im Endeffekt gibt es genau 2 Möglichkeiten dieses Problem anzugehen: entweder man übernimmt die Treiber eines anderen Systems oder man programmiert eigene Treiber.
Das die zweite Variante ein extrem hoher Aufwand ist (den man ja gerade nicht will) ist ziemlich offensichtlich aber das die erste Variante ein eventuell noch größerer Aufwand darstellt ergibt sich erst auf den zweiten Blick.
Nach allem was ich in den letzten Jahren zu diesem Thema an Informationen gefunden hab muss ich ganz ehrlich sagen das wenn man Variante 1 wählen möchte das dann die Windows-Treiber-API durchaus recht interessant erscheint (solange man auf einer Plattform arbeitet die von Windows ebenfalls nativ unterstützt wird könnte man sogar Closed-Source-Treiber übernehmen) da diese recht stabil und auch einigermaßen gut Dokumentiert ist, außerdem ist die Windows-Treiber-API auf Flexibilität und Performance ausgelegt was man von allen alternativen APIs (CDI/UDI/...) wahrlich nicht behaupten kann.

Ich würde mir wünschen das diese Kernfrage hier vielleicht noch ein wenig Diskutiert wird.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 18. January 2013, 14:46 »
Hallo,

der große Vorteil eines Monolithen ist, dass du interne Funktionen ohne Overhead aufrufen kannst, es also bestimmte Funktionalität nur einmal im gesamten Kernel geben muss. Da sind Bugfixes maximal effektiv.

Die Schnittstellen im Kernel sind nicht stabil, das stimmt. Viele API-Änderungen sind aber nur relativ klein bzw. lassen sich in den Treibern ohne größeren Aufwand automatisiert umsetzen (umbenannte Funktionsnamen etc.), wenn man mal von Subsystemen wie KMS usw. absieht. Schlimmer ist, dass die ABI nicht stabil ist, was Binärtreiber verunmöglicht. :-)

Theoretisch kannst du jeden Treiber mit einem halben Linux verheiraten und im Userspace laufen lassen, ob das aber mehr Spaß macht als den Treiber zu reversen und neu zu entwickeln, kann ich nicht einschätzen. Vermutlich kommst du da mit den BSD-Treibern eher weiter, die haben da - soweit ich das einschätzen kann - kleinere Schnittstellen. Andererseits ist z.B. der nouveau-Treiber von den Entwicklern als Kernel- und Userspace-Treiber ausgelegt worden, damit die bei der Entwicklung "mal eben schnell" eine Änderung testen können.

Ich denke, wenn man sich auf Treiber einer Klasse (z.B. Ethernet) beschränkt, kann man Linux-Treiber portieren. Wenn man aber alle/viele verschiedene Treiber übernehmen will, läuft das auf eine Reimplementation von Linux im eigenen Kernel raus.

Windows-Treiber haben den Vorteil der Verfügbarkeit, sind aber meist hinreichend schlecht/instabil programmiert. Das war ja eines der Probleme mit den NDIS-Treibern unter Linux (das zweite, dass nicht alle Fähigkeiten der Hardware zugreifbar waren, z.B. HostAP u.ä.). Außerdem ist es trotzdem eine ziemlich heftige API, die man unterstützen muss (Binärformate, ...). Portabel ist es dann auch nicht, aber bei einem Hobby-OS tut das nicht unbedingt weh.

Gruß,
Svenska

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 18. January 2013, 15:58 »
Hallo,


der große Vorteil eines Monolithen ist, dass du interne Funktionen ohne Overhead aufrufen kannst, es also bestimmte Funktionalität nur einmal im gesamten Kernel geben muss. Da sind Bugfixes maximal effektiv.
Also wenn diese Funktionen in einer DLL liegen dann sind sie aus mehreren User-Mode-Treibern mit genau so wenig Overhead aufzurufen und belegen auch nur einmal RAM/Cache und lassen sich genau so zentral warten. Sorry, aber das zählt nich. Der große Nachteil dieses Funktions-Sharings ist das wenn ein Subsystem-Entwickler sich so eine Funktion ausgedacht hat und diese dann plötzlich von den Treibern anderer Subsysteme auch benutzt wird das dann plötzlich (möglicherweise sogar ohne es zu wissen) der erste Entwickler seine Funktion nicht mehr einfach so modifizieren kann da das plötzlich unvorhergesehene Rückwirkungen auf ganze andere Dinge im Kernel hat. Diese Art von Spagetti-Code ist grundsätzlich nicht schön und ich persönlich würde gerne 0,2% System-Performance opfern wenn dafür ein stabileres System entsteht.

Viele API-Änderungen sind aber nur relativ klein bzw. lassen sich in den Treibern ohne größeren Aufwand automatisiert umsetzen
Ich hätte jetzt eher daran gedacht das ich aus einer bestimmten Kernel-Version bestimmte Treiber heraus filetiere, indem man ein Tool benutzt dem man sagt welche Dateien man unverändert bekommen will (den Treiber) und dieses Toll dann die Abhängigkeiten im restlichen Kernel iterativ durchgeht und genau das was benötigt wird mit ausschneidet. Letzteres abzüglich der Funktionen die ich selber anbieten muss und auch nur bei diesen Funktionen muss ich zuerst (händisch) prüfen ob sich dort die API und/oder die Funktionalität geändert hat.

Schlimmer ist, dass die ABI nicht stabil ist, was Binärtreiber verunmöglicht. ;)
Einige HW-Hersteller haben mehr oder minder erfolgreich vorgeführt das auch dieses Problem lösbar ist. ;)

Theoretisch kannst du jeden Treiber mit einem halben Linux verheiraten und im Userspace laufen lassen, ob das aber mehr Spaß macht als den Treiber zu reversen und neu zu entwickeln, kann ich nicht einschätzen.
Es geht mir nicht um den Spaß sondern darum ein Ziel mit möglichst geringem Aufwand zu erreichen und ich will auch nicht den halben Linux-Kernel sondern nur genau das was der Treiber benötigt und nicht eh von mir kommen muss (weil gewisse Dinge eben zu meinem OS passen müssen, alles andere würde auf nahezu vollwertiges User-Mode-Linux hinauslaufen).

Vermutlich kommst du da mit den BSD-Treibern eher weiter, die haben da - soweit ich das einschätzen kann - kleinere Schnittstellen. Andererseits ist z.B. der nouveau-Treiber von den Entwicklern als Kernel- und Userspace-Treiber ausgelegt worden, damit die bei der Entwicklung "mal eben schnell" eine Änderung testen können.
Okay, es gibt also mehr Quellen als nur den Linux-Kernel, wenn mein oben beschriebenes Tool flexibel genug ist sollte auch das kein Problem sein.

Ich denke, wenn man sich auf Treiber einer Klasse (z.B. Ethernet) beschränkt, kann man Linux-Treiber portieren. Wenn man aber alle/viele verschiedene Treiber übernehmen will, läuft das auf eine Reimplementation von Linux im eigenen Kernel raus.
Naja, also wenn dann geht es IMHO schon darum die typischen PCs die Media-Markt/Saturn/ALDI/... in den letzten X Jahren verkauft haben zu unterstützen damit mein kleines Hobby-OS auf möglichst vielen potentiellen PCs läuft. Wenn wir uns mal ansehen für welche HW es CDI-Treiber gibt dann muss man ganz klar sagen das deren Zielgruppe die virtuellen PCs von VMware und Co sind. Klar auch das ist ein Markt, wenn man damit (und den anderen Nachteilen von CDI) zufrieden ist dann ist CDI eine interessante Wahl aber wenn man mehr will dann ist es eventuell ratsam doch mal die Alternativen zu prüfen.

Windows-Treiber haben den Vorteil der Verfügbarkeit, sind aber meist hinreichend schlecht/instabil programmiert.
Um ersteres geht es mir doch und ob ich als Hobby-OS-Dever im zweiten Punkt mit eigenen Treibern so viel besser abschneiden würde steht auf einem anderen Blatt (deswegen bin ich ja so an den Linux-Treibern interessiert, die sind ebenfalls gut verfügbar und meistens von mindestens ebenwürdiger Qualität).

Außerdem ist es trotzdem eine ziemlich heftige API, die man unterstützen muss (Binärformate, ...).
Das ist wohl war. Die Windows-Treiber-API gibt es in verschiedenen Geschmacksrichtungen und jede Treiber-Sorte benötigt eine eigene API und dann hat man oft sogar noch die Wahl ob der Treiber im User-Mode oder im Kernel-Mode laufen soll. Aber gemessen an dem Aufwand den man investieren müsste um alle gewünschten Treiber selber zu entwickeln ist das vielleicht gar nicht mal so viel wie es scheint. Nebst dessen das man sich vielleicht bei ReactOS bedienen kann.

Portabel ist es dann auch nicht, aber bei einem Hobby-OS tut das nicht unbedingt weh.
Zumindest x86 in 32Bit und 64Bit und demnächst auch ARM in 32Bit und 64Bit sind doch schon mal was. Was will den der klassische Hobby-OS-Dever (der keine eigene Plattform bauen möchte, so wie wir beide) mehr?


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 18. January 2013, 17:19 »
Die Schnittstellen im Kernel sind nicht stabil, das stimmt. Viele API-Änderungen sind aber nur relativ klein bzw. lassen sich in den Treibern ohne größeren Aufwand automatisiert umsetzen (umbenannte Funktionsnamen etc.), wenn man mal von Subsystemen wie KMS usw. absieht.
Stimmt, deswegen funktioniert das ja für Linux. Wenn einer die API ändert, dann ändert er eben gleich alle Treiber mit und gut ist. Sobald du außerhalb des offiziellen Kernels bist und das nachträglich selbst machen musst, bekommst du natürlich einen großen Spaß damit, nachzuvollziehen, welche Änderungen gemacht worden sind und das auf deinen externen Code auch anzuwenden. Keine gute Idee.

Zitat
Schlimmer ist, dass die ABI nicht stabil ist, was Binärtreiber verunmöglicht. :-)
Das ist mir ehrlichgesagt schon unter Linux egal, Binärtreiber machen eh nur Ärger. Bei einem Hobby-OS ist es mir erst recht egal.

Der große Nachteil dieses Funktions-Sharings ist das wenn ein Subsystem-Entwickler sich so eine Funktion ausgedacht hat und diese dann plötzlich von den Treibern anderer Subsysteme auch benutzt wird das dann plötzlich (möglicherweise sogar ohne es zu wissen) der erste Entwickler seine Funktion nicht mehr einfach so modifizieren kann da das plötzlich unvorhergesehene Rückwirkungen auf ganze andere Dinge im Kernel hat.
Wer seine Funktionen jederzeit inkompatibel ändern können will, ohne sich um andere Aufrufer zu kümmern, der soll sie einfach nicht exportieren... Das ist nicht wirklich anders als bei deinen Shared Libraries im Userspace.

Zitat
Ich hätte jetzt eher daran gedacht das ich aus einer bestimmten Kernel-Version bestimmte Treiber heraus filetiere, indem man ein Tool benutzt dem man sagt welche Dateien man unverändert bekommen will (den Treiber) und dieses Toll dann die Abhängigkeiten im restlichen Kernel iterativ durchgeht und genau das was benötigt wird mit ausschneidet. Letzteres abzüglich der Funktionen die ich selber anbieten muss und auch nur bei diesen Funktionen muss ich zuerst (händisch) prüfen ob sich dort die API und/oder die Funktionalität geändert hat.
Das heißt, du willst den kompletten Subsystemcode mit rauskopieren? Du kannst es ja mal versuchen, ob du auf diese Weise irgendwohin kommst, aber an irgendeiner Stelle musst du einen Strich ziehen. Die komplette Speicherverwaltung willst du ja vermutlich nicht kopieren. ;)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 18. January 2013, 17:20 »
Hallo,

Also wenn diese Funktionen in einer DLL liegen dann sind sie aus mehreren User-Mode-Treibern mit genau so wenig Overhead aufzurufen und belegen auch nur einmal RAM/Cache und lassen sich genau so zentral warten.
Was ist mit der DLL-Hell? Außerdem sind sie dann zur Laufzeit genauso in den Kernel eingelinkt wie bei einem Monolithen. Wenn es dir nur um fixe Schnittstellen geht, geh' zu den BSDs. Da gibt es aber nicht wirklich viele Treiber.

Ich hätte jetzt eher daran gedacht das ich aus einer bestimmten Kernel-Version bestimmte Treiber heraus filetiere, indem man ein Tool benutzt dem man sagt welche Dateien man unverändert bekommen will (den Treiber) und dieses Toll dann die Abhängigkeiten im restlichen Kernel iterativ durchgeht und genau das was benötigt wird mit ausschneidet.
Läuft bei verschiedenen Treibern auf ein ziemlich komplettes Linux hinaus, abzüglich der Bugfixes, die in den Treibern geschehen (musst du manuell tracken). Außerdem verlassen sich Treiber u.U. auf bestimmte Eigenheiten der Speicherverwaltung (z.B. dass vaddr->paddr niemals einen page table walk durchführt und daher schnell ist), die bei dir nicht gegeben sind.

Um Linux-Treiber automatisiert übernehmen zu können, musst du in deiner Semantik so nah am Original sein, dass du dir die Kopie auch gleich sparen kannst.

Naja, also wenn dann geht es IMHO schon darum die typischen PCs die Media-Markt/Saturn/ALDI/... in den letzten X Jahren verkauft haben zu unterstützen damit mein kleines Hobby-OS auf möglichst vielen potentiellen PCs läuft.
Ich behaupte, dass die durchschnittlichen Nutzer von Aldi/Saturn/Mediamarkt/...-PCs nicht die Zielgruppe für Hobby-OSe sind. Außerdem fängt das Problem schon mit NVidia-Chipsätzen an. :-)

Portabel ist es dann auch nicht, aber bei einem Hobby-OS tut das nicht unbedingt weh.
Zumindest x86 in 32Bit und 64Bit und demnächst auch ARM in 32Bit und 64Bit sind doch schon mal was.
Nicht alle interessanten Treiber existieren für x64 und bei ARM wäre ich auch sehr überrascht, wenn sich dort ein halbwegs gebrauchbares Arsenal (jenseits von USB-Geräten) finden würde. Windows RT gibt es nur für Microsoft-zertifizierte Hardware, nicht für den Standard-SoC da draußen. Für USB-Treiber würde ich ohnehin Abstand vom Microsoft-Modell nehmen wollen.

Es hängt von der Hardware ab, die man unterstützen will. Für viele USB-Geräte gibt es auch Treiber auf Basis von libusb, da ist der Port dann einfacher und alles andere ... ist halt komplizierter.

Gruß,
Svenska

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #16 am: 18. January 2013, 19:18 »
Mal vom Aufwand abgesehen, da es sich beim Linux-Kernel ja um GPL-Code handelt sollte es doch für ein Micro-Kernel-OS möglich (und auch legal) sein alles was man für einen bestimmten Treiber benötigt aus dem Linux-Kernel komplett hinaus zu filetieren und als eigenständigen User-Mode-Prozess laufen zu lassen oder? Man müsste doch eigentlich nur die Teile des Linux-Codes anpassen/ersetzen die das Treiber-Management (z.B. IRQ-Handler an/ab-melden oder HW-Speicher ein/aus-blenden) betreffen oder?
Ich hab mich mal in eine Microkernelvorlesung verirrt, in der genau das getan wurde. Da gibt es irgendeine Art Bibliothek für L4 (wimre), die den Linuxkernel darstellt, und wenn man Treiber gegen die linkt, kann man die halt im Userspace ausführen und Linuxtreiber unter L4 benutzen. Das wurde auch live gemacht, also da saßen alle im Rechnerpool und vorne standen die URLs, wo man die Bibliothek und ein L4-Image bekommt und dann hieß es „So, jetzt sucht euch einen Hallo-Welt-Treiber im Netz oder so und probiert das mal in qemu aus“.

EDIT: Wenn man nach „Linux on L4“ googlet, ist die Seite der TU Dresden da auch der erste Treffer: http://os.inf.tu-dresden.de/L4/LinuxOnL4/overview.shtml

Martin Erhardt

  • Beiträge: 165
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 18. January 2013, 20:05 »
Hallo,
der große Vorteil eines Monolithen ist, dass du interne Funktionen ohne Overhead aufrufen kannst, es also bestimmte Funktionalität nur einmal im gesamten Kernel geben muss. Da sind Bugfixes maximal effektiv.
Also wenn diese Funktionen in einer DLL liegen dann sind sie aus mehreren User-Mode-Treibern mit genau so wenig Overhead aufzurufen und belegen auch nur einmal RAM/Cache
Das HauptperformanceProblem bei echten Mikrokernels ist ja weniger die Kommunikation mit dem ohnehin minimalen Kernel sondern die der UserspaceTreiber untereinander. Die Kommunikation zwischen SATA/USB/PATA dem FS und VFS muss über IPC erfolgen und das ist natürlich nicht so effizient wie Funktionsaufrufe.

Das andere Problem ist, dass die Schnittstellen innerhalb von Kernel nicht stabil sind.
Gut, man könnte aber auch zusätzliche standarisierte stabile Abstraktionschichten zwischen beispielsweise den Datenträger Treibern und den FS Treibern legen.(mit so einer Abstraktionsschicht könnten die FS Treiber auch verschiedene physche Datenträger gleich ansprechen)

Sorry das wir so vom Thema abgekommen sind.
« Letzte Änderung: 18. January 2013, 20:16 von Martin Erhardt »

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 18. January 2013, 20:22 »
Hallo,


Da gibt es irgendeine Art Bibliothek für L4 (wimre), die den Linuxkernel darstellt, und wenn man Treiber gegen die linkt, kann man die halt im Userspace ausführen und Linuxtreiber unter L4 benutzen.
Hm, das ist doch schon mal ein interessanter Schritt in die richtige Richtung, auch wenn es ein paravirtualisiertes Linux ist, also auf eine Art von User-Mode-Linux hinausläuft was ich ja eigentlich nicht möchte. Um z.B. einen Ethernet-Treiber zu bekommen möchte ich mir eigentlich nicht z.B. den IP-Stack des Linux-Kernel als Ballast in meinen User-Mode-Prozess holen, ich denke schon das es besser wäre gezielt die Funktionen die mein OS selber bieten will aus dem Linux-Kernel auszublenden und dann nur das raus zu filetieren was als Abhängigkeiten übrig bleibt. Zu dem was mein OS (bzw. meine User-Mode-libc) selber bieten gehört IMHO auch die Speicherverwaltung, nur Dinge wie eben das mappen von physischen Speicherressourcen der betreffenden Hardware muss ich passend abfangen und mit einem Syscall an mein OS behandeln. Mir ist klar das diese Vorgehensweise trotzdem einiges an Arbeit erfordert und auch mein Mapping-Code je nach Geräte-Type unterschiedliche Dinge bieten muss, trotzdem halte ich das für einen vernünftigen Ansatz um nahezu beliebige Treiber von Linux in mein OS zu holen.


Außerdem verlassen sich Treiber u.U. auf bestimmte Eigenheiten der Speicherverwaltung (z.B. dass vaddr->paddr niemals einen page table walk durchführt und daher schnell ist), die bei dir nicht gegeben sind.
Um Linux-Treiber automatisiert übernehmen zu können, musst du in deiner Semantik so nah am Original sein, dass du dir die Kopie auch gleich sparen kannst.
Also davon bin ich jetzt noch nicht überzeugt. Letztendlich kocht Linux auch nur mit Wasser, also warum sollte ich diese Features/Eigenheiten nicht auch hinbekommen?
Die kritische Frage ist doch eher ob diese subtilen Dinge auch sauber dokumentiert sind.

Ich behaupte, dass die durchschnittlichen Nutzer von Aldi/Saturn/Mediamarkt/...-PCs nicht die Zielgruppe für Hobby-OSe sind.
Okay, Punkt für Dich. ;)

Außerdem fängt das Problem schon mit NVidia-Chipsätzen an. :-)
Schon klar, aber wäre es nicht cool wenn tyndur trotz NVidia-Chipsatz eine vernünftige Graphik bieten könnte? Mal davon abgesehen das tyndur überhaupt Graphik richtig unterstützen müsste (ja ich weiß das es da erste Ansätze gibt).

Nicht alle interessanten Treiber existieren für x64
Aber beim heutigen Verbreitungsgrad von x64 sind die Lücken bereits recht dünn. Welcher HW-Hersteller kann es sich den leisten das seine HW von aktuellem Windows nicht unterstützt wird?

und bei ARM wäre ich auch sehr überrascht, wenn sich dort ein halbwegs gebrauchbares Arsenal finden würde
Okay, aber immerhin soll z.B. der Tegra 3 unterstützt werden und für diesen z.B. einen halbwegs brauchbaren Grafik-Treiber zu bekommen ist doch schon mal was.


Das Thema USB ist auch noch so ein Punkt, ja ich hatte bisher primär an PCI-Hardware gedacht.
Die libusb kenne ich auch aber das es auf dieser Basis "richtige" Treiber gibt wusste ich noch nicht. Wenn man auf diesem Weg zumindest HID und Mass-Storage bekommt wäre das doch schon mal ein echt großer Schritt, auch wenn einem immer noch die Hubs und der Host-Controller als Hausaufgabe bleiben.


Das heißt, du willst den kompletten Subsystemcode mit rauskopieren? Du kannst es ja mal versuchen, ob du auf diese Weise irgendwohin kommst, aber an irgendeiner Stelle musst du einen Strich ziehen. Die komplette Speicherverwaltung willst du ja vermutlich nicht kopieren. ;)
Ich denke das gerade vom betreffenden Subsystem eh nicht so viel Code kommt, wenn wir mal beim Beispiel des Ethernet-Treibers bleiben dann will ich doch gerade den IP-Stack usw. selber anbieten. Aus meiner Sicht sind eher die Funktionen kritisch die wirklich irgendwo im Kernel liegen und nicht so offensichtlich zu Ethernet-Treibern gehören. Die Speicherverwaltung aus dem Linux-Kernel zu kopieren geht natürlich gar nicht, IMHO noch nicht mal bei einem paravirtualisiertem Linux-Kernel und weil man gerade die eh für alle Treiber benötigt sollte es auch nicht so arg schwer fallen hier einmal was anständiges zu Entwickeln. Außerdem hoffe ich das sich die API zur Speicherverwaltung nur selten ändert (schon weil es da extrem viele Aufrufe gibt die man ändern müsste, da vertraue ich einfach auf die natürliche Faulheit des Menschen).


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #19 am: 18. January 2013, 20:47 »
Na ja, eigentlich wollte ich ja keine Diskussion zu CDI anfangen, aber wenns kein anderer macht…

Wenn wir uns mal ansehen für welche HW es CDI-Treiber gibt dann muss man ganz klar sagen das deren Zielgruppe die virtuellen PCs von VMware und Co sind.

CDI-Treiber gibt es genau dann, wenn jemand sie geschrieben hat. Da Treiber für von VMs unterstützte Hardware zu schreiben deutlich einfacher ist, ist logisch, weshalb vor allem dafür Treiber existieren. Zu sagen, CDI habe deshalb diese Zielgruppe, ist aber falsch. CDI hat keine Zielgruppe. Echte Hardware zu unterstützen ist mindestens genauso wichtig wie virtuelle.

 

Einloggen