summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel-devel/uio-driver/handout_uio-driver_de.tex597
-rw-r--r--kernel-devel/uio-driver/images/ioctl-vs-uio_de.pngbin0 -> 35842 bytes
-rw-r--r--kernel-devel/uio-driver/images/ioctl-vs-uio_de.svg383
-rw-r--r--kernel-devel/uio-driver/images/ioctl-vs-uio_en.png (renamed from kernel-devel/uio-driver/images/ioctl-vs-uio.png)bin106503 -> 106503 bytes
-rw-r--r--kernel-devel/uio-driver/images/konventioneller-treiber_de.pngbin0 -> 34106 bytes
-rw-r--r--kernel-devel/uio-driver/images/konventioneller-treiber_de.svg332
-rw-r--r--kernel-devel/uio-driver/images/konventioneller-treiber_en.png (renamed from kernel-devel/uio-driver/images/konventioneller-treiber.png)bin104184 -> 104184 bytes
-rw-r--r--kernel-devel/uio-driver/images/uio-treiber_de.pngbin0 -> 43114 bytes
-rw-r--r--kernel-devel/uio-driver/images/uio-treiber_de.svg433
-rw-r--r--kernel-devel/uio-driver/images/uio-treiber_en.png (renamed from kernel-devel/uio-driver/images/uio-treiber.png)bin126807 -> 126807 bytes
-rw-r--r--kernel-devel/uio-driver/pres_uio-driver_en.tex7
11 files changed, 1742 insertions, 10 deletions
diff --git a/kernel-devel/uio-driver/handout_uio-driver_de.tex b/kernel-devel/uio-driver/handout_uio-driver_de.tex
index 4c391b2..546c7fe 100644
--- a/kernel-devel/uio-driver/handout_uio-driver_de.tex
+++ b/kernel-devel/uio-driver/handout_uio-driver_de.tex
@@ -1,17 +1,602 @@
-\documentclass{article}
+\documentclass{lxarticle}
\usepackage{german}
\usepackage[utf8]{inputenc}
+\usepackage{lxheaders}
+\usepackage{lxextras}
\begin{document}
-\section*{Titel}
+\section*{Linux-Treiber im Userspace}
-\subsection*{Abschnitt1}
+Das ab Linux 2.6.23 im stabilen Kernel verfügbare Userspace-I/O-Framework
+(UIO) ermöglicht, bestimmte Treiber fast vollständig in den Userspace zu
+verlagern. Dies vereinfacht die Entwicklung und Wartung von Treibern,
+außerdem ergeben sich Möglichkeiten, die besonders Industriebetrieben
+entgegen kommen.
-Text
+Eine im Automatisierungsbereich tätige Firma hat eine PCI-I/O-Karte
+entwickelt. Sie soll in einer unter Linux laufenden Maschinensteuerung
+eingesetzt werden. Ein Linux-Kerneltreiber muss her. Kein Problem, denkt
+man sich. Immerhin stehen sowohl der Kernel-Sourcecode als auch die nötigen
+Entwicklungstools frei zur Verfügung. So oder so ähnlich hat schon so manche
+Linux-Horror-Story begonnen.
-\subsection*{Abschnitt2}
+Trotz benutzerfreundlicher Kernel-Subsysteme und Unterstützung durch
+Mailinglisten bedeutet das Schreiben eines Kerneltreibers für Linux-Einsteiger
+eine nicht zu unterschätzende Einarbeitungszeit. Industrielle I/O-Hardware ist
+oft so speziell, dass die Subsysteme des Kernels dem Programmierer gerade einmal
+das Erkennen der PCI-Karte abnehmen können. Gleichzeitig verfügen solche Karten
+oft über sehr komplexe Funktionen, so dass der Treiber immer umfangreicher wird.
+Treibercode mit mehreren tausend Codezeilen ist keine Seltenheit.
-Text
+Doch auch wenn diese Hürde genommen, der Treiber erfolgreich debugged und
+getestet wurde, gibt es ein noch größeres Problem: Die Wartung des Treibers.
+Denn ein so großer Treiber verwendet zweifellos eine große Zahl interner
+Kernel-Funktionen und -Makros. Dieses Kernel-interne API ist stets in Bewegung.
+Wer einen Treiber für 2.6.30 geschrieben hat, hat keinerlei Garantie, dass der
+unter 2.6.31 noch fehlerfrei kompiliert. Wer seinen Code mehrere Kernel-Versionen
+lang liegen lässt und dann upgraden will, hat höchst wahrscheinlich ein paar
+unerfreuliche Tage vor sich.
+
+Das zuletzt genannte Problem löst sich in Luft auf, wenn es gelingt, die
+Kernel-Entwickler, an der Spitze Linus Torvalds, dazu zu bewegen, den Code in
+den stabilen Mainline-Kernel aufzunehmen. Denn dann sind die Entwickler, die
+etwas am internen API ändern, verpflichtet, für die Anpassung aller betroffenen
+Module zu sorgen. Für unsere Automatisierungsfirma würde das bedeuten, dass die
+Linux-Community ihnen gratis diese Wartungsarbeit abnehmen würde. Sie und ihre
+Kunden könnten immer die neueste Kernelversion verwenden und würden ihren Treiber
+kompilierfähig vorfinden.
+
+Leider ist dies aus mehreren Gründen oft nicht machbar. Erstens werden die
+Kernel-Entwickler die Aufnahme eines großen Treibers, der nicht von allgemeinem
+Interesse ist, schlicht verweigern. Der Umfang des Kernelcodes würde sonst ins
+Unermessliche wachsen. Zweitens geht der Aufnahme von Code in den Mainline-Kernel
+gewöhnlich eine langwierige Review-Prozedur voraus. Dabei wird nicht nur
+Coding-Style begutachtet, es kann sich durchaus auch um Kritik an grundlegenden
+Vorgehensweisen handeln. Erst wenn alle Kritiker zufrieden gestellt sind, wird
+der Code in den Kernel aufgenommen. Darüber können Wochen vergehen. Die wenigsten
+Industriebetriebe genehmigen ihren Programmierern diesen Zusatzaufwand, da der
+Treiber in ihrer Maschine ja schon läuft.
+
+Drittens haben manche Firmen Probleme mit der GPL. Code, der im Kernel
+einkompiliert wird, muss dieser Lizenz genügen, das heißt, der Sourcecode muss
+öffentlich zugänglich sein. Firmen haben in der Vergangenheit zahlreiche
+(meist illegale) Tricks angewandt, um dieser Bedingung der GPL zu entgehen und
+ihren Kernelcode unter Verschluss zu halten.
+
+\subsection*{UIO löst Probleme}
+
+Die geschilderte Problematik führte bereits vor längerer Zeit zu Überlegungen,
+zumindest Teile eines Treibers in den Userspace zu verlagern. I/O-Hardware
+besteht in der Regel aus einem Speicherbereich, in dem sich RAM oder Register
+befinden. Linux ist von Haus aus in der Lage, einen solchen Speicherbereich per
+\cmd{mmap()} in den Userspace zu mappen. Damit kann man bereits alle Register
+der Hardware erreichen. Dies ist aber erst die halbe Miete: In der Regel
+erzeugen I/O-Karten Interrupts, und diese lassen sich nur im Kernel bearbeiten.
+Ausserdem muss man in einem allgemein verwendbaren System der Tatsache
+Rechnung tragen, dass eventuell mehrere (gleiche oder verschiedene) I/O-Karten
+im System vorhanden sein können.
+
+Das Userspace-I/O-Framework (UIO) löst diese Probleme einfach und elegant.
+Das für den Treiber immer noch benötigte Kernelmodul beschränkt sich auf einen
+minimalen Interrupt-Handler sowie das Anmelden des Treibers beim
+UIO-Framework. Letzteres erzeugt ein Device-File unter /dev sowie einige
+dokumentierte Standardfiles im sysfs unter /sys/class/uio. Ausserdem stellt das
+UIO-Framework bereits die für den Zugriff auf das Device-File benötigten
+Funktionen wie \cmd{open()}, \cmd{read()} und \cmd{mmap()} zur Verfügung. Im
+kundenspezifischen Kerneltreiber wird lediglich eine Struktur vom Typ
+\cmd{struct uio\_info} mit einigen Informationen gefüllt und damit die Funktion
+\cmd{uio\_register\_device()} aufgerufen. Den Rest erledigt das Framework.
+Durch dieses Design kann das hardwarespezifische Kernelmodul sehr klein
+ausfallen: das seit Kernel 2.6.23 enthaltene Modul für eine PCI-Feldbuskarte
+(Hilscher CIF) besteht aus gerade einmal 156 Zeilen, inklusive Leerzeilen und
+Kommentaren. Durch die sehr überschaubare Codegröße ist ein solches Modul schnell
+geschrieben, übersichtlich, wenig fehleranfällig, leicht wartbar und kann
+wesentlich leichter in den Mainline-Kernel integriert werden. Der Review-Prozess
+ist viel einfacher, da auch Kernelentwickler, die nicht über die passende
+Hardware verfügen, das Modul bezüglich Fehlerfreiheit beurteilen können.
+
+Nach dem Laden des Kernelmoduls kann man vom Userspace aus das Device-File
+(z.B. \cmd{/dev/uio0}) öffnen und sich per \cmd{mmap()}-Aufruf Zugriff auf
+den Speicher der Hardware verschaffen. Man wird zunächst durch geeignetes
+Beschreiben von Registern die Hardware initialisieren, so dass sie die
+gewünschte Funktion ausführt und Interrupts generiert. Auf Interrupts wartet
+man, indem man mit einem blockierenden \cmd{read()}-Aufruf einen 32-bit-Wert
+aus dem Device-File liest. Der Aufruf kehrt zurück, sobald ein Interrupt
+eintrifft. Der gelesene 32-bit-Wert gibt die Gesamtzahl der bisher
+aufgetretenen Interrupts an. Der Wert sollte idealerweise um eins größer
+sein als beim letzten Mal. Ist er noch größer, so hat man Interrupts verpasst.
+
+Man beachte, dass der Interrupt-Handler im Kernelmodul den Interrupt bereits
+quittiert haben muss. Im Fall eines pegelgetriggerten Interrupts, wie er bei
+PCI-Karten üblich ist, würde sich der Rechner sonst sang- und klanglos
+aufhängen. Bei Rückkehr des blockierenden \cmd{read()}-Aufrufs kann man sich
+also darauf beschränken, Daten zu lesen und zu schreiben, Statusregister zu
+lesen, neue Parameter zu setzen oder ähnliche Aufgaben, die beim Auftreten
+eines Interrupts anfallen. Falls die entsprechende Routine damit bis zum
+Eintreffen des nächsten Interrupts nicht fertig wird, so ist das zumindest
+softwaretechnisch kein Problem: Anhand des gelesenen Werts beim nächsten
+\cmd{read()} erkennen Sie, wie viele Interrupts Sie verpasst haben.
+
+\subsection*{GPL oder nicht GPL}
+
+Der Linux-Kernel einschließlich aller enthaltenen Module ist unter der GPL
+lizensiert. Programme im Linux-Userspace unterliegen solchen Einschränkungen
+nicht. Das gilt auch für UIO-Treiber. Mit UIO existiert daher erstmals eine
+Kernel-Schnittstelle, die es erlaubt, einen interruptfähigen Treiber zu
+schreiben, der größtenteils nicht der GPL unterliegt (das kleine Kernelmodul
+muss natürlich immer noch GPL-lizensiert werden). Diese Tatsache hat für
+einigen Wirbel in der Linux-Szene gesorgt. Das UIO-Framework wurde von
+Mitarbeitern der Firma Linutronix entwickelt und an Greg Kroah-Hartman,
+den Maintainer des Linux driver core, weiter gereicht. Kroah-Hartman
+versuchte am 13.12.2006 erstmals, UIO im Mainline-Kernel unterzubringen.
+Linus Torvalds lehnte die Aufnahme damals ab, hauptsächlich aufgrund von
+Missverständnissen bezüglich eines beigefügten Demo-Treibers. In der Folge
+entstand eine wochenlange Diskussion, die schnell vom eigentlichen Thema
+abwich und sich hauptsächlich mit der Lizensierungs-Problematik beschäftigte.
+
+Dabei lag es in erster Linie gar nicht in der Absicht der UIO-Entwickler,
+proprietäre Treiber zu ermöglichen. Dies ist eigentlich ein Nebeneffekt, der
+sich aus der Tatsache ergibt, dass man für Userspace-Software unter Linux seit
+eh und je die Lizenz frei wählen darf. Dennoch mag dieser Punkt in einigen
+Firmen für Erleichterung sorgen. Wer etwa bestimmtes Know-How in einem FPGA
+untergebracht hat, der möchte nicht unter dem Zwang stehen, den Code des
+zugehörigen Treibers öffentlich zu machen. Manchmal kann dies sogar durch den
+Endkunden vertraglich untersagt sein, zum Beispiel bei Code, der für die
+Einhaltung gesetzlich vorgeschriebener Werte sorgt, bei militärischen oder
+sonst sicherheitsrelevanten Anwendungen.
+
+Bisher waren solche Firmen gezwungen, Codeänderungen durch technische Klimmzüge
+zu verhindern, bewusst gegen die GPL zu verstoßen oder ganz auf Linux zu
+verzichten. Durch UIO wird an dieser Stelle ein gangbarer und legaler Ausweg
+geschaffen.
+
+\subsection*{Konventionelle Treiber...}
+
+Bisherige Gerätetreiber sind vollständig im Kernel integriert. Die
+Schnittstelle zum Userspace besteht typischerweise aus einer Gerätedatei, auf
+die mit den üblichen Funktionen wie \cmd{open()}, \cmd{close()}, \cmd{read()},
+\cmd{write()} und \cmd{ioctl()} zugegriffen werden kann.
+
+\begin{figure}[h]
+\centering
+\includegraphics[width=0.8\textwidth]{images/konventioneller-treiber_de.png}
+\caption{Aufbau eines konventionellen Treibers}
+\label{img:konvtreiber}
+\end{figure}
+
+
+
+Alle diese Funktionen
+müssen vollständig im Treiber implementiert werden und führen je nach Gerät
+mehr oder weniger komplexe Operationen mit der Hardware aus. Bei industriellen
+I/O-Karten liegt meist ein Schwerpunkt auf der \cmd{ioctl()}-Funktion. Die Ein-
+und Ausgabe-Funktionaltät der Karte ist oft so komplex, dass man sie nicht auf
+einfache \cmd{read()}- und \cmd{write()}-Operationen abbilden kann. Ausserdem
+haben solche Karten in der Regel zahlreiche Parameter und Optionen, die auf
+einen bestimmten Wert gesetzt oder ein- und ausgeschaltet werden wollen.
+Man findet daher häufig Treiber für derartige Industrie-Karten, die 50 oder
+mehr ioctl-Unterfunktionen implementieren.
+
+\begin{figure}[h]
+\centering
+\includegraphics[width=0.8\textwidth]{images/ioctl-vs-uio_de.png}
+\caption{Vergleich von \cmd{ioctl()}-basierten Sytemen mit UIO}
+\label{img:ioctl}
+\end{figure}
+
+Dies führt oft dazu, dass letzlich mehr Datenaustausch mit der Karte per
+\cmd{ioctl()} abgewickelt wird als über die eigentlich dafür vorgesehenen
+\cmd{read()}- und \cmd{write()}-Funktionen. Auch aus Performance-Gründen ist
+diese Vorgehensweise alles Andere als optimal. Wenn beispielsweise
+\cmd{ioctl()} dazu verwendet wird, einen 32-Bit-Wert in ein Register der
+Hardware zu schreiben, dann packt das Anwenderprogramm im Userspace zunächst
+den Wert auf den Stack und ruft über die libc \cmd{ioctl()} auf. Per syscall
+landet der Aufruf im Kernel. Dort sucht das Virtual File System (VFS) den
+Pointer auf die für das jeweilige Gerät zuständige \cmd{ioctl()}-Funktion und
+ruft diese auf. Da die übergebenen Parameter im User-Speicher liegen, muss sie
+die \cmd{ioctl()}-Implementierung zunächst mit Hilfe der Kernel-Funktion
+\cmd{copy\_from\_user()} in den Kernel-Speicher holen. Jetzt endlich kann der
+übergebene Wert in das Hardware-Register geschrieben werden. Falls der Aufruf
+auch Werte zurückgeben soll, müssen diese entsprechend erst mit
+\cmd{copy\_to\_user()} in den übergebenen Puffer geschrieben werden.
+
+Letztlich handelt es sich bei einem derartigen Konzept um einen Missbrauch von
+\cmd{ioctl()}. Die Funktion war ursprünglich nur dazu gedacht, gelegentlich
+einen Parameter einer (Geräte-)Datei zu ändern. Für häufigen, schnellen
+Datenaustausch ist sie denkbar ungeeignet und vor allem auch unnötig, wie wir
+weiter unten sehen werden. Die Kernel-Entwickler stehen daher einer
+\cmd{ioctl()}-basierten Treiberimplementierung äußerst kritisch gegenüber.
+Ein Treiber für eine exotische Karte, der 50 neue \cmd{ioctl()}-Funktionen
+einführen will, wird wahrscheinlich schon aus diesem Grund nicht in den
+Mainline-Kernel aufgenommen.
+
+Ein weiteres Problem ergibt sich aus der Größe des Treibercodes. Ein paar
+tausend (nicht-triviale) Zeilen sind schnell beieinander. Obwohl auch für die
+Kernel-Entwicklung zahlreiche mächtige Hilfsmittel zur Fehlersuche existieren,
+erfordert das Debugging doch erheblich mehr an Spezialwissen als im Userspace.
+In einem Kerneltreiber können einfache Fehler den Rechner so lahm legen, dass
+nur noch der Griff zum Resettaster Rettung bringt. In einem Industriebetrieb
+verfügen häufig auch die ansonsten sehr qualifizierten Programmierer nur über
+wenig Erfahrung mit Linux-Kernelprogrammierung. Mit den üblicherweise recht
+eingeschränkten Ressourcen an Zeit und Personal entstehen dann Treiber, die
+ebenso fehlerträchtig wie unübersichtlich sind und keinerlei Chance auf
+Aufnahme in den offiziellen Mainline-Kernel haben. Dadurch haben die
+Programmierer dann während der gesamten Laufzeit des Produkts zusätzlich das
+Problem, diesen wackligen Treiber out-of-tree warten zu müssen.
+
+\subsection*{...und UIO-Treiber}
+
+Sieht man sich Gerätetreiber etwas genauer an, so stellt man fest, dass es
+stets wiederkehrende Aufgabenstellungen gibt. Zum einen hat die Hardware
+einen oder mehrere Speicherbereiche, auf die man zugreifen möchte. Zum
+anderen erzeugt die Hardware Interrupts, auf die reagiert werden muss. Das
+UIO-Framework enthält den Code für diese Standardaufgaben und vermeidet so,
+dass Programmierer ständig ein nicht ganz einfaches Rad neu erfinden müssen.
+
+\begin{figure}[h]
+\centering
+\includegraphics[width=0.8\textwidth]{images/uio-treiber_de.png}
+\caption{Aufbau eines konventionellen Treibers}
+\label{img:konvtreiber}
+\end{figure}
+
+Um Speicherbereiche verwenden zu können, muss man dem UIO-Framework lediglich
+deren Startadresse und Länge angeben. UIO stellt dann bereits eine
+\cmd{mmap()}-Funktion zur Verfügung, die es erlaubt, die Speicherbereiche
+in den Userspace zu mappen. Im Falle einer PCI-Karte erhalten Sie die
+Informationen über Startadresse und Länge bereits vom PCI-Subsystem.
+
+Zur Behandlung von Interrupts muss lediglich ein minimaler Interrupt-Handler
+geschrieben werden. Um Interrupt-Sharing zu ermöglichen, sollte der Handler
+erkennen, ob es die eigene Karte war, die den Interrupt ausgelöst hat. Falls
+nein, gibt er einfach IRQ\_NONE zurück. Falls ja, wird er den Interrupt bei
+der Hardware quittieren und dafür sorgen, dass die Interrupt-Leitung wieder
+ihren inaktiven Zustand annimmt. Auch hier muss man lediglich die Nummer des
+Interrupts und einen Pointer auf den Handler angeben, den Rest erledigt das
+Framework.
+
+Zu den weiteren Dienstleistungen des UIO-Frameworks gehört das Anlegen und
+Behandeln von Dateien im sysfs. Unter \cmd{/sys/class/uio} finden sich
+Informationen zu allen angemeldeten UIO-Geräten. Dazu gehören der Name des
+Geräts, Version seines Kernelmoduls, Adressen und Größen seiner
+Speicherbereiche, Anzahl aufgetretener Interrupts und Ähnliches. Diese
+(dokumentierten) sysfs-Dateien ermöglichen es dem Userspace-Teil des Treibers,
+gezielt nach seinem Gerät zu suchen und beispielsweise die Größen der
+Speicherbereiche korrekt zu erfragen, anstatt sich auf fest kodierte Werte
+zu verlassen.
+
+Insgesamt enthält das UIO-Framework etwa 900 Zeilen nicht-trivialen Code, die
+man für eine ähliche Funktionalität sonst selbst schreiben müsste. Dagegen
+kommt das zu erstellende gerätespezifische Modul auf etwa 150 Zeilen Code,
+der zudem recht einfach ist und leicht von schon existierenden Treibern
+abgeleitet werden kann. Dadurch haben auch weniger erfahrene Programmierer
+die Chance, ein sauberes, übersichtliches und stabiles Modul für ihre Hardware
+zu produzieren. Es bleibt auch jederzeit die Möglichkeit, sich dieses Modul
+von einem erfahrenen Dienstleister erstellen zu lassen. Auf diese Weise ist es
+möglich, eigene Treiber zu entwickeln, ohne eine einzige Zeile Kernel-Code
+schreiben zu müssen.
+
+Der ganze Rest, also die komplette eigentliche Funktionalität des Treibers,
+wird im Userspace erledigt. Der Treiber kann als Shared Library, als
+Bestandteil eines Anwenderprogramms oder in bester Unix-Manier als Dämon
+realisiert werden. Die Programmierer des Treibers benötigen nicht mehr
+Kenntnisse und Tools, als sie zur Programmierung ihrer Applikation ohnehin
+benötigen.
+
+Im Beispiel oben haben wir gesehen, welchen Aufwand es bedeutet, einen
+einzelnen Wert per \cmd{ioctl()} in ein Hardware-Register zu befördern. Im
+Falle von UIO ist diese Operation eine einfache Zuweisung an die betreffende
+Stelle des gemappten Speichers. Wenn \cmd{a} der Zeiger auf den Speicher ist
+und an die relative Adresse 1000 der Wert 5 geschrieben werden soll, so
+schreibt man ohne Umschweife \cmd{a[1000]=5}. Jegliches Hin- und Herkopieren
+entfällt, so dass sich bei schnellen Anwendungen ein echter Performance-Vorteil
+gegenüber einem Kerneltreiber mit \cmd{ioctl()}-Konzept ergibt. Es ist also
+keinesfalls so, dass man für den Userspace-Komfort Geschwindigkeits-Nachteile
+in Kauf nehmen müsste.
+
+Was sich ebenfalls verbessert, ist das Handling von Updates. Bei einem reinen
+Kernel-Treiber ist ein Update des Kernels oder zumindest der Module nötig, was
+in der Regel root-Rechte des Anwenders erfordert und bei Fehlern zu einem
+völlig unbrauchbaren System führt. Bei einem UIO-Treiber unterscheidet sich
+ein Update des Treibers durch nichts von einem Update der Anwender-Applikation.
+
+\subsection*{Wartungsvertrag}
+
+Ein Treiber will gewartet sein. Bei industriellen Geräten findet man oft die
+Situation, dass ein Gerät über einen längeren Zeitraum mit der selben
+Kernelversion ausgeliefert wird. Möchte man später, etwa nach 6 Monaten oder
+einem Jahr, beispielsweise im Zuge eines allgemeinen Software-Updates auf einen
+aktuellen Kernel wechseln, so sind oft deutliche Änderungen am Kerneltreiber
+nötig.
+
+Konventionelle Treiber beinhalten zwangsläufig viele Aufrufe von internen
+Kernelfunktionen. Im Gegensatz zur stabilen syscall-Schnittstelle kann sich
+dieses interne Kernel-API jederzeit ändern. Sie müssen damit rechnen, dass
+Funktionen, die ihr Treiber verwendet, plötzlich nicht mehr existieren oder
+andere Parameter haben. Entsprechend hoch ist der Wartungsaufwand für einen
+solchen Treiber, wenn er nicht im Mainline-Kernel enthalten ist.
+
+UIO macht ihnen auch hier das Leben leichter. Das Framework übernimmt die
+üble Kleinarbeit, die etwa beim Umgang mit sysfs, Interrupt-Handling oder
+Memory-Mapping anfällt. Es schirmt sie sozusagen von den wilden Seiten des
+Kernels ab, indem es ihnen erlaubt, mit etwa einem halben Dutzend einfacher
+Funktionen auszukommen. Angesichts der geringen Codegröße eines
+UIO-Kernelmoduls sind selbst bei Änderungen an diesen Funktionen die
+Wartungsarbeiten sehr überschaubar und schnell ausgeführt.
+
+Betrachtet man als Beispiel den Treiber für die Hilscher CIF-Karte
+\cmd{(drivers/uio/uio\_cif.c)}, dann fällt auf, dass für die Einbindung in das
+UIO-Framework lediglich zwei Funktionen (\cmd{uio\_register\_device} und
+\cmd{uio\_unregister\_device}) sowie eine Datenstruktur
+(\cmd{struct uio\_info}) benötigt werden. Ansonsten werden lediglich 7
+Funktionen des PCI-Subsystems sowie 6 sonstige Funktionen wie \cmd{kzalloc()}
+benutzt. Alle diese Funktionen sind einfach und gängig. Das sie sich ändern,
+ist möglich, aber nicht sehr wahrscheinlich.
+
+Dennoch sollten sie den Kernelteil ihres Treibers möglichst nicht ausserhalb
+des offiziellen Mainline-Kernels pflegen wollen. Schreiben sie sauberen Code
+entsprechend dem Kernel-Coding-Style und zögern sie nicht, auf der
+Linux-Kernel-Mailingliste um die Aufnahme desselben zu bitten. Die Mühe lohnt
+sich: Zukünftige Kernel haben die Unterstützung für ihr Produkt schon
+eingebaut, Versionskonflikte oder das mühsame Kernel-Patchen entfällt.
+
+\subsection*{Los geht's...}
+
+Wie sieht nun ein UIO-Treiber konkret aus? Betrachten wir dazu einen Treiber
+für eine PCI-Karte. Die folgenden Beispiele sind Auszüge aus dem bereits
+erwähnten Treiber für die Hilscher CIF Feldbuskarte. Er befindet sich seit
+2.6.23-rc1 im Mainline-Kernel.
+
+Der Treiber unterscheidet sich zunächst nur wenig von einem normalen
+PCI-Kartentreiber. Anhand einer Tabelle mit PCI-ID-Nummern wird dem
+PCI-Subsystem mitgeteilt, für welche Karten sich der Treiber zuständig fühlt.
+Wird beim Booten eine solche Karte gefunden, so lädt das PCI-Subsystem den
+Treiber und ruft dessen probe-Funktion auf. Diese muss Karte und
+Treiber-Variablen initialisieren und das Ergebnis dieser Bemühungen
+zurückmelden. Konnten Treiber und Karte erfolgreich initialisiert werden, so
+haben sie dem System ein betriebsbereites PCI-Device hinzugefügt.
+
+Bei einem UIO-Treiber besteht ihre Hauptarbeit darin, eine Struktur vom Typ
+\cmd{struct uio\_info} zu erzeugen und auszufüllen. Beginnen wir mit Name und
+Version ihres Treibers. Dies sind beliebige strings, die später über
+sysfs-Dateien abgefragt werden können:
+
+\begin{lstlisting}
+/* Struktur anlegen */
+struct uio_info *info;
+info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
+/* Name und Version setzen */
+info->name = "Meine UIO Karte";
+info->version = "0.0.1";
+\end{lstlisting}
+
+Als Nächstes kann der von der Karte verwendete Interrupt eingetragen werden.
+Freundlicherweise übergibt der Kernel der probe-Funktion einen Pointer
+(hier \emph{dev} genannt) auf eine Struktur vom Typ \cmd{struct pci\_dev}, in der
+derartige Angaben schon vom PCI-Subsystem eingetragen wurden. Unsere Aufgabe
+ist also leicht zu erfüllen:
+
+\begin{lstlisting}
+info->irq = dev->irq;
+\end{lstlisting}
+
+Ausserdem kann man dem UIO-Framework mitteilen, dass man einen
+"Fast"-Interrupthandler möchte und für Interrupt-Sharing vorbereitet ist:
+
+\begin{lstlisting}
+info->irq_flags = IRQF_DISABLED | IRQF_SHARED;
+\end{lstlisting}
+
+Die Adresse des (noch zu erstellenden) Interrupt-Handlers darf natürlich
+nicht fehlen:
+
+\begin{lstlisting}
+info->handler = mein_irq_handler;
+\end{lstlisting}
+
+Jetzt wäre noch der Speicher der PCI-Karte anzugeben. Nehmen wir an, die Karte
+habe nur einen solchen Bereich. Wir erfahren Adresse und Größe des Bereichs
+wieder mit Hilfe des Pointers \emph{dev}. Zusätzlich geben wir an, dass es sich um
+physikalischen Speicher handelt:
+
+\begin{lstlisting}
+info->mem[0].addr = pci_resource_start(dev, 0);
+info->mem[0].size = pci_resource_len(dev, 0);
+info->mem[0].memtype = UIO_MEM_PHYS;
+\end{lstlisting}
+
+Die hier eingetragene physikalische Adresse kann nicht direkt für Zugriffe
+verwendet werden. Sie wird vom UIO-Framework beim \cmd{mmap()}-Aufruf in den
+Userspace gemappt. Allerdings wird man sicherlich auch in der Interrupt-Routine
+Zugriff auf den Speicher benötigen. Dazu mappen wir die Adresse in einen vom
+Kernel verwendbaren Bereich:
+
+\begin{lstlisting}
+info->mem[0].internal_addr = ioremap(pci_resource_start(dev, 0),
+ pci_resource_len(dev, 0) );
+\end{lstlisting}
+
+Damit haben wir unserer Pflicht Genüge getan und können unser Device beim
+UIO-Framework registrieren:
+
+\begin{lstlisting}
+uio_register_device(&dev->dev, info);
+\end{lstlisting}
+
+Das war's. Ein neues UIO-Device hat das Licht der Welt erblickt. Es gibt jetzt
+eine Gerätedatei \cmd{/dev/uio0} sowie verschiedene Dateien im Verzeichnis
+\cmd{/sys/class/uio/uio0/}, die die in \cmd{struct uio\_info} enthaltenen Daten
+wiedergeben. Natürlich wird man in der Realität dem obigen Beispielcode noch
+Fehlerüberprüfungen hinzufügen, dies wurde hier der Übersichtlichkeit halber
+weggelassen.
+
+Damit das Ganze funktioniert, muss natürlich noch der oben angegebene
+Interrupt-Handler implementiert werden. Sein Gerüst sieht so aus:
+
+\begin{lstlisting}
+static irqreturn_t mein_irq_handler(int irq, struct uio_info *dev_info)
+{
+ void *ptr = dev_info->mem[0].internal_addr;
+
+ if (Interrupt_kam_nicht_von_meiner_Karte)
+ return IRQ_NONE;
+\end{lstlisting}
+
+ Hier sind Zugriffe mit Hilfe von ioread/iowrite möglich:
+
+\begin{lstlisting}
+ ein_byte = ioread8(ptr + MEIN_REGISTER_OFFSET);
+ iowrite8(ein_byte | INTERRUPT_AUS, ptr + NOCH_EIN_OFFSET);
+
+ Hier muss sichergestellt sein, dass die Interruptleitung
+ wieder inaktiv ist!
+
+ return IRQ_HANDLED;
+}
+\end{lstlisting}
+
+Jetzt ist der Kernel-Teil des Treibers komplett. Beispiele für vollständige
+Treiber finden sich im Verzeichnis \cmd{drivers/uio/} in den Kernel-Quellen
+oder auf dem Server des Open Source Automation Development Lab (www.osadl.org).
+Ausführliche Dokumentation findet sich auch in den Kernel-Quellen in
+\cmd{Documentation/DocBook/uio-howto.tmpl}; mit \cmd{make htmldocs} erstellt
+man daraus eine lesbare Form.
+
+\subsection*{Testen mit lsuio}
+
+Hat man einen UIO-Kerneltreiber geladen, so führt der erste Weg ins Verzeichnis
+\cmd{/sys/class/uio/uio0}, wo man überprüft, ob alle Dateien die erwarteten
+Werte enthalten. Dies kann auf Dauer recht lästig sein, besonders, wenn man
+mehrere UIO-Devices gleichzeitig testen will. Hier hilft ein kleines Tool
+namens \cmd{lsuio}, das alle diese Werte übersichtlich auflistet.
+
+Der Sourcecode dieses Tools findet sich auf dem Server des OSADL. Nach dem
+Auspacken des Archivs erstellt das übliche
+
+\begin{lstlisting}
+./configure && make && make install
+\end{lstlisting}
+
+das Tool. Dabei wird auch eine manpage installiert, die die möglichen Optionen
+des Programms erläutert. Zum Beispiel sorgt die Option -m dafür, dass
+\cmd{lsuio} testweise überprüft, ob der Speicher der Karte problemlos in den
+Userspace gemappt werden kann.
+
+Der recht übersichtliche Sourcecode von \cmd{lsuio} (er besteht nur aus zwei
+C-Dateien) kann im Übrigen als Beispiel für eigene Anwendungen dienen. Der
+Userspace-Teil des Treibers sollte nämlich nie eine bestimmte Version des
+Kerneltreibers voraussetzen. Ebenso sollte er nicht als selbstverständlich
+voraussetzen, dass das eigene Device immer als \cmd{/dev/uio0} erscheint.
+Durch Überprüfen der Dateien \cmd{name} und \cmd{version} in den Verzeichnissen
+unterhalb von \cmd{/sys/class/uio} kann man diese Informationen auf sichere
+Weise gewinnen.
+
+\subsection*{Weiter geht's im Userspace}
+
+Der Userspace-Teil des Treibers wird zunächst über das sysfs den Namen des
+zuständigen Device-Files ermitteln. Im Folgenden wird der Einfachkeit halber
+\cmd{/dev/uio0} angenommen. Ausserdem wird er überprüfen, ob die Version des
+Kerneltreibers den Erwartungen entspricht. Wenn Alles im grünen Bereich ist,
+wird \cmd{/dev/uio0} geöffnet:
+
+\begin{lstlisting}
+int fd = open("/dev/uio0", O_RDWR);
+\end{lstlisting}
+
+Jetzt müssen wir uns Zugriff auf den Speicher der Karte verschaffen. Nehmen
+wir an, die Karte verfügt über einen 4kByte großen Bereich, auf den wir
+zugreifen wollen:
+
+\begin{lstlisting}
+void* map_addr = mmap( NULL, 4096, PROT_READ, MAP_SHARED, fd, 0);
+\end{lstlisting}
+
+Jetzt enthält \cmd{map\_addr} einen Zeiger, mit dem direkt auf den Speicher
+der Karte zugegriffen werden kann. Der Treiber wird jetzt die Register der
+Karte mit sinnvollen Werten beschreiben. Zuletzt wird er dafür sorgen, dass
+die Karte Interrupts generiert.
+
+Auf das Eintreffen von Interrupts wartet der Treiber, indem er in einer
+Schleife einen blockierenden \cmd{read()}-Aufruf für das Device-File ausführt.
+Dabei liest er einen vorzeichenbehafteten 32-bit-Wert. Da \cmd{read()}
+standardmäßig blockiert, wenn bei \cmd{open()} kein \cmd{O\_NONBLOCK}
+angegeben wurde, sieht das einfach so aus:
+
+\begin{lstlisting}
+s32 irq_count;
+
+while (read(fd, &irq_count, 4)==4) {
+
+/* Interrupt-Aktionen */
+
+}
+\end{lstlisting}
+
+Natürlich sollte die Schleife noch eine Abbruchbedingung haben, damit das
+Programm irgendwann einmal beendet werden kann. Der in \cmd{irq\_count}
+gelieferte Wert ist die Gesamtzahl der aufgetretenen Interrupts. Meist wird
+man sich diesen Wert merken wollen, damit man beim nächsten Interrupt
+überprüfen kann, ob der Wert genau um eins größer geworden ist.
+
+Will man gleichzeitig auf mehrere Filedeskriptoren warten, z.B. auf
+Interrupts des UIO-Device und auf das Eintreffen von Bytes in einem
+Netzwerk-Socket, so kann man auch \cmd{select()} verwenden.
+
+Insgesamt ist der Userspace-Teil des Treibers sehr Entwickler-freundlich.
+Unter der Annahme, dass man die Karte nicht kaputt programmieren kann,
+steht Experimenten kaum etwas im Weg. Sie können jedenfalls keine
+schlimmeren Abstürze verursachen als beim Programmieren jeder anderen
+Anwender-Applikation.
+
+\subsection*{UIO oder nicht UIO}
+
+Sollen jetzt in Zukunft alle Treiber mittels UIO realisiert werden? Sicher
+nicht. UIO eignet sich sehr gut für Hardware, die Interrupts erzeugt, deren
+Register durch Memory-Mapping in den Userspace gebracht werden können, und
+die vor allem nur wenig mit anderen Subsystemen des Kernels zu tun haben.
+Letzteres ist leicht einzusehen, da die Interaktion mit anderen Subsystemen
+nur innerhalb des Kernel erfolgen kann. Wollte man etwa den Treiber für
+einen SATA-Controller mit UIO realisieren, so müßte dieser ja ein gültiges
+Block-Device auf die Beine stellen. Hätte man den dazu nötigen Code, der
+eng mit anderen Kernel-Teilen zusammenarbeiten würde, fertiggestellt, so
+würde man bemerken, dass für den Userspace nicht mehr viel übrig bleibt.
+
+Auch Hardware, die keine Interrupts erzeugt, ist kein idealer Kandidat für
+UIO, da die saubere Handhabung von Interrupts die eigentliche Besonderheit
+des Frameworks darstellt. Das reine Mapping von Speicher in den Userspace
+kann man auch ohne UIO haben. Allerdings bietet eine Implementierung mit Hilfe
+von UIO immer noch den Vorteil, eine standardisierte und dokumentierte
+sysfs-Schnittstelle gratis dazu zu bekommen.
+
+Eine weitere Einschränkung besteht darin, dass UIO in seiner aktuellen Version
+kein DMA unterstützt. Die Entwickler planen, dies in einer zukünftigen Version
+nachzureichen, falls sich Anwendungen dafür finden. Ein naheliegendes Beispiel
+sind natürlich Treiber für Grafikkarten, allerdings hat sich hier durch die
+weite Verbreitung von X.org bereits ein anderer Standard etabliert, der im
+Übrigen teilweise ähnliche Ansätze wie UIO aufweist. Aber auch I/O-Karten,
+beispielsweise schnelle A/D-Wandler, könnten DMA benötigen. Die Zukunft wird
+zeigen, ob an dieser Stelle Nachfrage besteht.
+
+\subsection*{Fazit}
+
+Durch das seit Kernel-Version 2.6.23 in Linux verfügbare
+Userspace I/O-Framework wird es besonders für Industriebetriebe erheblich
+einfacher, Treiber für ihre I/O-Karten zu schreiben und zu warten. Der
+Kernel-Teil des Treibers beschränkt sich auf ein absolutes Minimum, und das
+UIO-Framework entkoppelt ihn wirkungsvoll von der Vielzahl an internen
+Kernelfunktionen, die herkömmliche Treiber verwenden müssen. Die Entwicklung der
+eigentlichen Treiber-Funktionalität erfolgt bequem im Userspace, unter Verwendung
+der für die Applikationsentwicklung gewohnten Tools und Bibliotheken.
+
+Hat man sich einmal für UIO entschieden, so sollte man unbedingt anstreben, den
+Kernelteil des Treibers im Mainline-Kernel unterzubringen. Auf diese Weise
+erspart man sich und seinen Kunden das ständige Patchen des Kernels und die
+Pflege eines out-of-tree Moduls.
+
+Verhilft man seinem Kernel zusätzlich zu Echtzeit-Fähigkeiten, indem man den
+Realtime-Preemption-Patch einspielt, so erhält man ein einfach zu
+programmierendes und vollständig aus Open Source-Software bestehendes System
+für die Automatisierungstechnik.
\end{document}
diff --git a/kernel-devel/uio-driver/images/ioctl-vs-uio_de.png b/kernel-devel/uio-driver/images/ioctl-vs-uio_de.png
new file mode 100644
index 0000000..0989d07
--- /dev/null
+++ b/kernel-devel/uio-driver/images/ioctl-vs-uio_de.png
Binary files differ
diff --git a/kernel-devel/uio-driver/images/ioctl-vs-uio_de.svg b/kernel-devel/uio-driver/images/ioctl-vs-uio_de.svg
new file mode 100644
index 0000000..a913a69
--- /dev/null
+++ b/kernel-devel/uio-driver/images/ioctl-vs-uio_de.svg
@@ -0,0 +1,383 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="210mm"
+ height="297mm"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45.1"
+ sodipodi:docbase="/home/hans/linutronix/articles/uio-ct-artikel_v2"
+ sodipodi:docname="ioctl-vs-uio.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/hans/linutronix/articles/uio-ct-artikel_v2/ioctl-vs-uio.png"
+ inkscape:export-xdpi="100"
+ inkscape:export-ydpi="100">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mend"
+ style="overflow:visible;">
+ <path
+ id="path3262"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.4) rotate(180) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ id="path3280"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(0,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="TriangleOutM"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="TriangleOutM"
+ style="overflow:visible">
+ <path
+ id="path3254"
+ d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4)" />
+ </marker>
+ <marker
+ inkscape:stockid="TriangleInM"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="TriangleInM"
+ style="overflow:visible">
+ <path
+ id="path3245"
+ d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(-0.4)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mstart"
+ style="overflow:visible">
+ <path
+ id="path3159"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path3153"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8) translate(12.5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mstart"
+ style="overflow:visible">
+ <path
+ id="path3177"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) translate(0,0)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.4"
+ inkscape:cx="246.67635"
+ inkscape:cy="792.61315"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:window-width="1672"
+ inkscape:window-height="977"
+ inkscape:window-x="0"
+ inkscape:window-y="0">
+ <sodipodi:guide
+ orientation="vertical"
+ position="69.285714"
+ id="guide3134" />
+ <sodipodi:guide
+ orientation="vertical"
+ position="372.85714"
+ id="guide3136" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="956.42857"
+ id="guide3140" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="772.85714"
+ id="guide3142" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="631.42857"
+ id="guide2349" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="682.14286"
+ id="guide2351" />
+ <sodipodi:guide
+ orientation="vertical"
+ position="665"
+ id="guide2353" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="587.14286"
+ id="guide2357" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Ebene 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.06220484;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.06220472, 2.06220472;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 67.857143,393.07647 L 665,393.07647"
+ id="path2160"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.06220484;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.06220472, 2.06220472;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 68.214289,165.93362 L 664.64285,165.93362"
+ id="path3138"
+ sodipodi:nodetypes="cc" />
+ <rect
+ style="fill:#fc5400;fill-opacity:1;stroke:#000000;stroke-width:2.06220484;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3146"
+ width="199.28641"
+ height="100.71439"
+ x="272.45969"
+ y="180.93361"
+ ry="10"
+ rx="10" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="68.571426"
+ y="283.07645"
+ id="text3398"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3400"
+ x="68.571426"
+ y="283.07645">Kernelspace</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="68.520004"
+ y="146.75792"
+ id="text3402"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan2243"
+ x="68.520004"
+ y="146.75792">Hardware</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="68.520004"
+ y="446.22791"
+ id="text3408"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3412"
+ x="68.520004"
+ y="446.22791">Userspace</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="-267.33499"
+ y="265.69397"
+ id="text3436"
+ sodipodi:linespacing="100%"
+ transform="matrix(0,-1,1,0,0,0)"><tspan
+ sodipodi:role="line"
+ id="tspan3440"
+ x="-267.33499"
+ y="265.69397">Treiber</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch"
+ x="333.15143"
+ y="465.7879"
+ id="text3442"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan2247"
+ x="333.15143"
+ y="465.7879">ioctl()</tspan></text>
+ <rect
+ style="fill:#fc9900;fill-opacity:1;stroke:#000000;stroke-width:2.41653538;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3492"
+ width="99.999985"
+ height="49.285713"
+ x="323.21429"
+ y="368.43359"
+ rx="10"
+ ry="10" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch"
+ x="331.07361"
+ y="398.45221"
+ id="text3494"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan2245"
+ x="331.07361"
+ y="398.45221">syscall</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch"
+ x="278.52625"
+ y="256.12363"
+ id="text2249"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan2253"
+ x="278.52625"
+ y="256.12363">copy_from_user()</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch"
+ x="316.38339"
+ y="214.69505"
+ id="text2255"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan2259"
+ x="316.38339"
+ y="214.69505">iowrite()</tspan></text>
+ <rect
+ style="fill:#fc9900;fill-opacity:1;stroke:#000000;stroke-width:2.41653538;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2261"
+ width="99.999985"
+ height="49.285713"
+ x="322.85718"
+ y="299.14789"
+ rx="10"
+ ry="10" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch"
+ x="355.0022"
+ y="329.1665"
+ id="text2263"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan2267"
+ x="355.0022"
+ y="329.1665">VFS</tspan></text>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 373.57142,339.33983 L 373.57142,381.48268"
+ id="path3470"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 373.57142,267.91124 L 373.57142,310.05409"
+ id="path2269"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 372.85714,407.19696 L 372.85714,449.33981"
+ id="path2271"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 374.28571,152.91125 L 374.28571,195.0541"
+ id="path2273"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 587.14285,449.50503 L 587.14285,154.50503"
+ id="path2277"
+ sodipodi:nodetypes="cc" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch"
+ x="547.81189"
+ y="465.4093"
+ id="text3450"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3456"
+ x="547.81189"
+ y="465.4093">a[n]=b;</tspan></text>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.06220484;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.06220472, 2.06220472;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 497.14286,492.67901 L 497.14286,96.964715"
+ id="path3458"
+ sodipodi:nodetypes="cc" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="306.89368"
+ y="95.47361"
+ id="text3460"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3464"
+ x="306.89368"
+ y="95.47361">a) mit ioctl():</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="507.18765"
+ y="95.509331"
+ id="text3466"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3470"
+ x="507.18765"
+ y="95.509331">b) mit mmap():</tspan></text>
+ </g>
+</svg>
diff --git a/kernel-devel/uio-driver/images/ioctl-vs-uio.png b/kernel-devel/uio-driver/images/ioctl-vs-uio_en.png
index 8536934..8536934 100644
--- a/kernel-devel/uio-driver/images/ioctl-vs-uio.png
+++ b/kernel-devel/uio-driver/images/ioctl-vs-uio_en.png
Binary files differ
diff --git a/kernel-devel/uio-driver/images/konventioneller-treiber_de.png b/kernel-devel/uio-driver/images/konventioneller-treiber_de.png
new file mode 100644
index 0000000..cbca8bc
--- /dev/null
+++ b/kernel-devel/uio-driver/images/konventioneller-treiber_de.png
Binary files differ
diff --git a/kernel-devel/uio-driver/images/konventioneller-treiber_de.svg b/kernel-devel/uio-driver/images/konventioneller-treiber_de.svg
new file mode 100644
index 0000000..5dbd773
--- /dev/null
+++ b/kernel-devel/uio-driver/images/konventioneller-treiber_de.svg
@@ -0,0 +1,332 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="210mm"
+ height="297mm"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45.1"
+ sodipodi:docbase="/home/hans/linutronix/articles/uio-ct-artikel/bilder"
+ sodipodi:docname="konventioneller-treiber.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/hans/linutronix/articles/uio-ct-artikel/bilder/konventioneller-treiber.png"
+ inkscape:export-xdpi="100"
+ inkscape:export-ydpi="100">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="TriangleOutM"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="TriangleOutM"
+ style="overflow:visible">
+ <path
+ id="path3254"
+ d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4)" />
+ </marker>
+ <marker
+ inkscape:stockid="TriangleInM"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="TriangleInM"
+ style="overflow:visible">
+ <path
+ id="path3245"
+ d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(-0.4)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mstart"
+ style="overflow:visible">
+ <path
+ id="path3159"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path3153"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8) translate(12.5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mstart"
+ style="overflow:visible">
+ <path
+ id="path3177"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) translate(0,0)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.4"
+ inkscape:cx="246.67635"
+ inkscape:cy="796.87607"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:window-width="1672"
+ inkscape:window-height="977"
+ inkscape:window-x="0"
+ inkscape:window-y="0">
+ <sodipodi:guide
+ orientation="vertical"
+ position="69.285714"
+ id="guide3134" />
+ <sodipodi:guide
+ orientation="vertical"
+ position="633.57143"
+ id="guide3136" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="956.42857"
+ id="guide3140" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="872.85714"
+ id="guide3142" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Ebene 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.06220484;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.06220472, 2.06220472;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 67.142857,339.50504 L 637.14285,339.50504"
+ id="path2160"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.06220484;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.06220472, 2.06220472;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 66.785718,268.79076 L 639.64285,268.79076"
+ id="path3138"
+ sodipodi:nodetypes="cc" />
+ <rect
+ style="fill:#f2f000;fill-opacity:1;stroke:#000000;stroke-width:2.06220484;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3144"
+ width="253.57143"
+ height="158.57143"
+ x="215.71428"
+ y="96.964714" />
+ <rect
+ style="fill:#fc5400;fill-opacity:1;stroke:#000000;stroke-width:2.06220484;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3146"
+ width="120"
+ height="158.57143"
+ x="512.85712"
+ y="96.647896"
+ ry="10"
+ rx="10" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 445.71429,123.07647 L 520,123.07647"
+ id="path3148" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 445.19192,144.50504 L 519.47763,144.50504"
+ id="path3352" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 445.19192,165.21932 L 519.47763,165.21932"
+ id="path3354" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 445.19192,186.64789 L 519.47763,186.64789"
+ id="path3356" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 445.19191,207.36218 L 519.47762,207.36218"
+ id="path3358" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 445.19192,228.07647 L 519.47763,228.07647"
+ id="path3360" />
+ <rect
+ style="fill:#fc9900;fill-opacity:1;stroke:#000000;stroke-width:2.41653538;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3382"
+ width="122.14286"
+ height="49.285713"
+ x="511.42856"
+ y="279.50504"
+ rx="10"
+ ry="10" />
+ <rect
+ style="fill:#0fe400;fill-opacity:1;stroke:#000000;stroke-width:2.41653538;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3384"
+ width="418.57144"
+ height="90"
+ x="215"
+ y="371.64789"
+ rx="10"
+ ry="10" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 534.28571,331.83982 L 534.28571,388.98267"
+ id="path3386"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 571.42858,332.55409 L 571.42858,388.98266"
+ id="path3388"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 606.42857,331.83981 L 606.42857,388.98266"
+ id="path3390"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:4.54251957;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#TriangleInM);marker-end:url(#TriangleOutM);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 575.00001,256.64789 L 575.00001,280.21932"
+ id="path3392" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="68.571426"
+ y="179.50504"
+ id="text3398"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3400"
+ x="68.571426"
+ y="179.50504">Kernelspace</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="67.805717"
+ y="310.32935"
+ id="text3402"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3406"
+ x="67.805717"
+ y="310.32935">Interface</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="67.805717"
+ y="421.04361"
+ id="text3408"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3412"
+ x="67.805717"
+ y="421.04361">Userspace</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="356.19702"
+ y="421.7579"
+ id="text3414"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3418"
+ x="356.19702"
+ y="421.7579">Applikation</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="328.55521"
+ y="159.61504"
+ id="text3420"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3430"
+ x="331.32864"
+ y="159.61504">interne </tspan><tspan
+ sodipodi:role="line"
+ id="tspan3432"
+ x="328.55521"
+ y="179.61504">Kernelfunktionen</tspan><tspan
+ sodipodi:role="line"
+ id="tspan3434"
+ x="328.55521"
+ y="199.61504">(instabiles API)</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="538.3443"
+ y="180.13646"
+ id="text3436"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3440"
+ x="538.3443"
+ y="180.13646">Treiber</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch"
+ x="524.28571"
+ y="310.21933"
+ id="text3442"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3444"
+ x="524.28571"
+ y="310.21933">/dev/xyz</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch"
+ x="533.32349"
+ y="408.64072"
+ id="text3446"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3450"
+ x="533.32349"
+ y="408.64072">read()</tspan><tspan
+ sodipodi:role="line"
+ id="tspan3452"
+ x="533.32349"
+ y="428.64072">write()</tspan><tspan
+ sodipodi:role="line"
+ id="tspan3454"
+ x="533.32349"
+ y="448.64072">ioctl()</tspan></text>
+ </g>
+</svg>
diff --git a/kernel-devel/uio-driver/images/konventioneller-treiber.png b/kernel-devel/uio-driver/images/konventioneller-treiber_en.png
index bea54da..bea54da 100644
--- a/kernel-devel/uio-driver/images/konventioneller-treiber.png
+++ b/kernel-devel/uio-driver/images/konventioneller-treiber_en.png
Binary files differ
diff --git a/kernel-devel/uio-driver/images/uio-treiber_de.png b/kernel-devel/uio-driver/images/uio-treiber_de.png
new file mode 100644
index 0000000..9e18a06
--- /dev/null
+++ b/kernel-devel/uio-driver/images/uio-treiber_de.png
Binary files differ
diff --git a/kernel-devel/uio-driver/images/uio-treiber_de.svg b/kernel-devel/uio-driver/images/uio-treiber_de.svg
new file mode 100644
index 0000000..a1cc780
--- /dev/null
+++ b/kernel-devel/uio-driver/images/uio-treiber_de.svg
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="210mm"
+ height="297mm"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45.1"
+ sodipodi:docbase="/home/hans/linutronix/articles/uio-ct-artikel_v2"
+ sodipodi:docname="uio-treiber.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/hans/linutronix/articles/uio-ct-artikel_v2/uio-treiber.png"
+ inkscape:export-xdpi="100"
+ inkscape:export-ydpi="100">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="TriangleOutM"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="TriangleOutM"
+ style="overflow:visible">
+ <path
+ id="path3254"
+ d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4)" />
+ </marker>
+ <marker
+ inkscape:stockid="TriangleInM"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="TriangleInM"
+ style="overflow:visible">
+ <path
+ id="path3245"
+ d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(-0.4)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mstart"
+ style="overflow:visible">
+ <path
+ id="path3159"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path3153"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8) translate(12.5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mstart"
+ style="overflow:visible">
+ <path
+ id="path3177"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) translate(0,0)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.4"
+ inkscape:cx="246.67635"
+ inkscape:cy="749.98402"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:window-width="1672"
+ inkscape:window-height="977"
+ inkscape:window-x="0"
+ inkscape:window-y="0">
+ <sodipodi:guide
+ orientation="vertical"
+ position="69.285714"
+ id="guide3134" />
+ <sodipodi:guide
+ orientation="vertical"
+ position="632.14286"
+ id="guide3136" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="956.42857"
+ id="guide3140" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="772.85714"
+ id="guide3142" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="631.42857"
+ id="guide2349" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="682.14286"
+ id="guide2351" />
+ <sodipodi:guide
+ orientation="vertical"
+ position="404.28571"
+ id="guide2353" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="580.71429"
+ id="guide2357" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Ebene 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="fill:#0fe400;fill-opacity:1;stroke:#000000;stroke-width:2.41653538;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2347"
+ width="227.85715"
+ height="99.285751"
+ x="404.28571"
+ y="371.29074"
+ rx="10"
+ ry="10" />
+ <path
+ style="fill:#f5cb00;fill-rule:evenodd;stroke:#000000;stroke-width:2.06220472;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;fill-opacity:1"
+ d="M 469.28571,97.362184 L 469.28571,255.21932 L 503.57143,255.21932 L 503.57143,198.79075 L 632.14286,198.79075 L 632.14286,97.362184 L 469.28571,97.362184 z "
+ id="path3458"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.06220484;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.06220472, 2.06220472;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 67.142857,339.50504 L 637.14285,339.50504"
+ id="path2160"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.06220484;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.06220472, 2.06220472;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 66.785718,268.79076 L 639.64285,268.79076"
+ id="path3138"
+ sodipodi:nodetypes="cc" />
+ <rect
+ style="fill:#f2f000;fill-opacity:1;stroke:#000000;stroke-width:2.06220484;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3144"
+ width="253.57143"
+ height="158.57143"
+ x="215.71428"
+ y="96.964714" />
+ <rect
+ style="fill:#fc5400;fill-opacity:1;stroke:#000000;stroke-width:2.06220484;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3146"
+ width="120.71497"
+ height="47.142963"
+ x="512.14288"
+ y="208.07648"
+ ry="10"
+ rx="10" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 445.71429,123.07647 L 487.14286,123.07647"
+ id="path3148"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 445.19192,144.50504 L 488.04906,144.50504"
+ id="path3352"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 445.19192,165.21932 L 488.04906,165.21932"
+ id="path3354"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 445.19192,186.64789 L 488.04906,186.64789"
+ id="path3356"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 445.19191,207.36218 L 487.33476,207.36218"
+ id="path3358"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 445.19192,228.07647 L 487.33477,228.07647"
+ id="path3360"
+ sodipodi:nodetypes="cc" />
+ <rect
+ style="fill:#fc9900;fill-opacity:1;stroke:#000000;stroke-width:2.41653538;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3382"
+ width="122.14286"
+ height="49.285713"
+ x="511.42856"
+ y="279.50504"
+ rx="10"
+ ry="10" />
+ <rect
+ style="fill:#0fe400;fill-opacity:1;stroke:#000000;stroke-width:2.41653538;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3384"
+ width="165.71431"
+ height="98.571426"
+ x="215"
+ y="371.64789"
+ rx="10"
+ ry="10" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 534.28571,331.83982 L 534.28571,388.98267"
+ id="path3386"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 571.42858,332.55409 L 571.42858,388.98266"
+ id="path3388"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 606.42857,331.83981 L 606.42857,388.98266"
+ id="path3390"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:4.54251957;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#TriangleInM);marker-end:url(#TriangleOutM);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 575.00001,256.64789 L 575.00001,280.21932"
+ id="path3392" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="68.571426"
+ y="179.50504"
+ id="text3398"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3400"
+ x="68.571426"
+ y="179.50504">Kernelspace</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="67.805717"
+ y="310.32935"
+ id="text3402"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3406"
+ x="67.805717"
+ y="310.32935">Interface</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="69.234291"
+ y="425.32932"
+ id="text3408"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3412"
+ x="69.234291"
+ y="425.32932">Userspace</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="231.19704"
+ y="426.7579"
+ id="text3414"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3484"
+ x="231.19704"
+ y="426.7579">Applikation</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="328.55521"
+ y="159.61504"
+ id="text3420"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3430"
+ x="331.32864"
+ y="159.61504">interne </tspan><tspan
+ sodipodi:role="line"
+ id="tspan3432"
+ x="328.55521"
+ y="179.61504">Kernelfunktionen</tspan><tspan
+ sodipodi:role="line"
+ id="tspan3434"
+ x="328.55521"
+ y="199.61504">(instabiles API)</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="536.91577"
+ y="237.99361"
+ id="text3436"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3440"
+ x="536.91577"
+ y="237.99361">Treiber</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch"
+ x="517.14282"
+ y="310.93362"
+ id="text3442"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3456"
+ x="517.14282"
+ y="310.93362">/dev/uioX</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch"
+ x="536.1806"
+ y="415.06927"
+ id="text3446"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3474"
+ x="536.1806"
+ y="415.06927">read()</tspan><tspan
+ sodipodi:role="line"
+ id="tspan3476"
+ x="536.1806"
+ y="435.06927">mmap()</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="564.77295"
+ y="132.99361"
+ id="text3460"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3466"
+ x="564.77295"
+ y="132.99361">UIO-</tspan><tspan
+ sodipodi:role="line"
+ id="tspan3468"
+ x="564.77295"
+ y="152.99361">Framework</tspan></text>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 525.71428,179.33982 L 525.71428,221.48267"
+ id="path3470"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 616.42857,179.33982 L 616.42857,221.48267"
+ id="path3472"
+ sodipodi:nodetypes="cc" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans"
+ x="431.8024"
+ y="425.4736"
+ id="text3486"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3490"
+ x="431.8024"
+ y="425.4736">Treiber</tspan></text>
+ <rect
+ style="fill:#fc9900;fill-opacity:1;stroke:#000000;stroke-width:2.41653538;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3492"
+ width="99.999985"
+ height="49.285713"
+ x="404.64285"
+ y="279.86218"
+ rx="10"
+ ry="10" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch"
+ x="422.50214"
+ y="309.16647"
+ id="text3494"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3498"
+ x="422.50214"
+ y="309.16647">sysfs</tspan></text>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:4.54251957;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#TriangleInM);marker-end:url(#TriangleOutM);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 485.71429,255.57646 L 485.71429,279.14789"
+ id="path3500" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 458.57142,331.83982 L 458.57142,388.98267"
+ id="path3502"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:4.54251957;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#TriangleInM);marker-end:url(#TriangleOutM);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 381.07143,421.64789 L 404.64286,421.64789"
+ id="path2355" />
+ </g>
+</svg>
diff --git a/kernel-devel/uio-driver/images/uio-treiber.png b/kernel-devel/uio-driver/images/uio-treiber_en.png
index caa2152..caa2152 100644
--- a/kernel-devel/uio-driver/images/uio-treiber.png
+++ b/kernel-devel/uio-driver/images/uio-treiber_en.png
Binary files differ
diff --git a/kernel-devel/uio-driver/pres_uio-driver_en.tex b/kernel-devel/uio-driver/pres_uio-driver_en.tex
index 8468894..ca9ff44 100644
--- a/kernel-devel/uio-driver/pres_uio-driver_en.tex
+++ b/kernel-devel/uio-driver/pres_uio-driver_en.tex
@@ -6,7 +6,6 @@
\usepackage{graphicx}
\title{The Userspace I/O Framework (UIO)}
-\author{Hans-Jürgen Koch}
\institute{Linutronix GmbH}
\begin{document}
@@ -69,12 +68,12 @@
% ----- Slide "In-kernel driver" ------------------
\begin{frame}
-\includegraphics[width=11cm]{images/konventioneller-treiber.png}
+\includegraphics[width=11cm]{images/konventioneller-treiber_en.png}
\end{frame}
% ----- Slide "UIO driver" ------------------
\begin{frame}
-\includegraphics[width=11cm]{images/uio-treiber.png}
+\includegraphics[width=11cm]{images/uio-treiber_en.png}
\end{frame}
% ----- Slide "How UIO works" --------------------------
@@ -210,7 +209,7 @@ while (read(fd, &irq_cnt, 4)) {
% ----- Slide "ioctl vs. UIO" ------------------
\begin{frame}
-\includegraphics[width=10cm]{images/ioctl-vs-uio.png}
+\includegraphics[width=10cm]{images/ioctl-vs-uio_en.png}
\end{frame}
% ----- Slide "Publish your driver!" --------------