]> rtime.felk.cvut.cz Git - mf6xx.git/commitdiff
Diploma thesis text.
authorRostislav Lisovy <lisovy@gmail.com>
Sat, 2 Apr 2011 21:40:19 +0000 (23:40 +0200)
committerRostislav Lisovy <lisovy@gmail.com>
Sat, 2 Apr 2011 21:40:19 +0000 (23:40 +0200)
doc/diploma_thesis/text/dip_text.tex

index 54be174dce4428d7a3f2b474657f6a189a97b921..fbba26a35357212ea6944fa2bd1e273fa94d88ad 100644 (file)
@@ -1,5 +1,5 @@
-\documentclass[a4paper, 12pt]{report} 
-\usepackage[hscale=0.75, vscale=0.75]{geometry}
+\documentclass[11pt,twoside,a4paper]{book}
+%\usepackage[hscale=0.75, vscale=0.75]{geometry}
 \usepackage[utf8]{inputenc}
 \usepackage[czech]{babel}
 \usepackage{indentfirst}
@@ -8,7 +8,7 @@
 \usepackage{amssymb,amsmath}
 \usepackage{url}
 
-\newcommand{\ibox}[1]{ \begin{center}\begin{small} \fbox{\parbox{14cm}{ #1 }} \end{small}\end{center}}
+\newcommand{\ibox}[1]{ \begin{center}\begin{small} \fbox{\parbox{12cm}{ #1 }} \end{small}\end{center}}
 
 %opening
 \title{\textsf{\begin{huge}Prostředí pro výuku vývoje PCI ovladačů do OS GNU/Linux\end{huge}\\
@@ -19,19 +19,18 @@ Fakulta elektrotechnická ČVUT}
 \begin{document}
 
 \maketitle
-\newpage
 
 \tableofcontents
 \newpage
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-\begin{abstract}
+%\begin{abstract}
 Cílem této práce je vysvětlit základní principy komunikace ovladače operačního systému s hardwarem. Pro názornost jsou v práci popsány postupy implementace UIO a Comedi ovladače pro měřící kartu Humusoft MF624 pro operační systém GNU/Linux.
 
 Součástí této práce je i implementace základních funkcí (DAC, ADC, DIO) karty Humusoft MF624 do emulátoru Qemu, aby si případný zájemce mohl popsané postupy vyzkoušet, aniž by vlastnil potřebný hardware.
 
 Od čtenáře se očekává základní znalost používání operačního systému GNU/Linux, dobrá znalost programovacího jazyka C a základní znalost anglického jazyka.
-\end{abstract}
+%\end{abstract}
 \newpage
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -57,7 +56,7 @@ Jak je možné ovládat hardware pomocí programu (software) je nejsnazší uká
 
 }
 
-V případě, že budeme chtít změnit hodnotu GPIO pinu, je první možností provedení operace zápisu na určitou adresu v paměťovém adresním prostoru (ta je pevně daná a liší mezi jednotlivými architekturami mikrokontrolérů), tato adresa odpovídá \textbf{registru}\footnote{Registr může být pro zjednodušení považován za malou paměťovou buňku. Změna její hodnoty přímo ovliňuje stav hardware. V dokumentaci ke konkrétnímu mikrokontrolerů/\-mikroprocesoru/\-programovatelnému integrovanému obvodu je uvedeno, jakou funkci mají jednotlivé bity registru.} GPIO pinu. Vnitřní uspořádání mikrokontroleru, dle adresy na kterou jsme zapisovali, rozpozná, že provedená operace zápisu nebyla určena pro změnu hodnoty vnitřní paměti, ale je určena pro změnu hodnoty registru a z toho plynoucí změny stavu určité části hardwaru. Námi zapsaná hodnota se tedy projeví změnou výstupní hodnoty GPIO pinu. Tato možnost je nejjednodušší a je možná v případě, že jsou hardwarové periferie mapovány do určité části tzv. \textbf{paměťového prostoru}.\footnote{Také označováno jako MMIO -- \textit{Memory-mapped input/output}}
+V případě, že budeme chtít změnit hodnotu GPIO pinu, je první možností provedení operace zápisu na určitou adresu v paměťovém adresním prostoru (ta je pevně daná a liší mezi jednotlivými architekturami mikrokontrolérů), tato adresa odpovídá \textbf{registru}\footnote{Registr může být pro zjednodušení považován za malou paměťovou buňku. Změna její hodnoty přímo ovliňuje stav hardware. V dokumentaci ke konkrétnímu mikrokontrolerů/\-mikroprocesoru/\-programovatelnému integrovanému obvodu je uvedeno, jakou funkci mají jednotlivé bity registru.} GPIO pinu. Vnitřní uspořádání mikrokontroleru, dle adresy na kterou jsme zapisovali, rozpozná, že provedená operace zápisu nebyla určena pro změnu hodnoty vnitřní paměti, ale je určena pro změnu hodnoty registru a z toho plynoucí změny stavu určité části hardwaru. Zapsaná hodnota se tedy projeví změnou výstupní hodnoty GPIO pinu. Tato možnost je nejjednodušší a je možná v případě, že jsou hardwarové periferie mapovány do určité části tzv. \textbf{paměťového prostoru}.\footnote{Také označováno jako MMIO -- \textit{Memory-mapped input/output}}
 
 \begin{figure}[h!]
        \begin{center}
@@ -79,7 +78,7 @@ Hlavní rozdíly mezi chováním paměťové buňky a registru zařízení jsou:
 \end{itemize}
 }
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\section{PCI sběrnice a komunikační protokol}\label{pcich}
+\section{PCI sběrnice}\label{pcich}
 Přesný popis PCI sběrnice je mimo rozsah a zaměření této práce. Pokusím se však zmínit a názorně vysvětlit principy využívané touto sběrnicí, které je nutné alespoň částečně znát při implementaci ovladačů PCI zařízení.
 
 \begin{figure}[h!]
@@ -135,7 +134,7 @@ Výše popsané registry (a ostatní, které nejsou pro čtenáře podstatné) s
 Měřící karta Humusoft MF624 (dále jen MF624), připojitelná k počítači pomocí PCI sběrnice, má pro účely výkladu psaní ovladačů několik nesporných výhod:
 \begin{itemize}
 \item Komunikace (na úrovni ovladače) s kartou probíhá snadno pochopitelným, přímo\-čarým způsobem (bude vysvětleno dále).
-\item Je snadné si ověřit funkci napsaného ovladače -- např. připojením LED diody k digitálnímu výstupu.
+\item Je snadné si ověřit správnou funkci napsaného ovladače -- např. připojením LED diody k digitálnímu výstupu.
 \end{itemize}
 
 Karta MF624 najde své uplatnění hlavně v laboratorním prostředí -- v případech, když je potřeba vytvořit styk mezi počítačem a senzorem/jiným zařízením, které poskytuje analogový, resp. digitální signál (v tom případě využijeme A/D převodníků, resp. digitálních vstupů). Kartu je možné použít pro řízení akčního členu/zařízení -- na výběr máme D/A převodníky a digitální výstupy.
@@ -152,13 +151,13 @@ Komunikace s kartou probíhá celkem přímočarým způsobem:
 \item V případě čtení A/D převodníku nejprve zapíšeme do konfiguračního registru A/D převodníku slovo odpovídající požadované konfiguraci. Poté již z registru náležícího A/D převodníku vyčteme požadovanou hodnotu.
 \end{itemize}
 
-Abychom zjistili, které registry karta obsahuje, jakou mají funkci a kde jsou umístěny je nejprve potřeba si z oficiálních stránek výrobce stáhnout\footnote{\url{http://www2.humusoft.cz/www/datacq/manuals/mf624um.pdf}} manuál ke kartě.
+Které registry karta obsahuje, jakou mají funkci a kde jsou umístěny je možné zjistit z manuálu ke kartě -- ten je možné stáhnout z oficiálních internetových stránek výrobce.\footnote{\url{http://www2.humusoft.cz/www/datacq/manuals/mf624um.pdf}}
 
 Na straně 11 je k vidění první důležitá tabulka (zde tab. \ref{tab_bar}):
 
 \begin{table}[h!]
        \begin{center}
-       \begin{tabular}{|p{2cm}|p{6cm}|c|c|}
+       \begin{tabular}{|p{2cm}|p{4cm}|c|c|}
        \hline \textbf{Region} & \textbf{Function} & \textbf{Size (bytes)} & \textbf{Width (bytes)} \\ 
        \hline BADR0 (memory mapped) & PCI chipset, interrupts, status bits, special functions & 32 & 32 \\ 
        \hline BADR1 (memory mapped) & A/D, D/A, digital I/O & 128 & 16/32 \\ 
@@ -170,32 +169,32 @@ Na straně 11 je k vidění první důležitá tabulka (zde tab. \ref{tab_bar}):
        \end{center}
 \end{table}
 
-Z ní je patrné, že karta využívá 3 regiony mapované do paměťovém adresním prostoru (sloupec 1) -- o velikostech 32, 128 a 128 bajtů (sloupce 3). Pro čtení/zápis z/do nich je potřeba používat 32-, 16-, 32bitové operace (sloupec 4).\footnote{V manuálu je uvedeno, že za určitých podmínek je možné k BAR1 přistupovat i pomocí 32bitových operací. V této práci bych se tomuto složitějšímu přístupu rád vyhnul. Částečná implementace karty MF624 do emulátoru Qemu (Popsaná v příloze \ref{qemu}) umožňuje \textbf{pouze} 16bitový přístup do BAR1 paměťového regionu.}
+Z ní je patrné, že karta využívá 3 regiony\footnote{V manuálu je uvedeno, že se jedná o regiony odpovídající BAR0, BAR1 a BAR2 registrům -- skutečnost je však taková, že karta využívá regiony odpovídající registrům BAR0, BAR2 a BAR4. Rozdíl mezi skutečností a manuálem spočívá v tom, že v muálu jsou registry popsány tak, jak je vidí operační systém Microsoft Windows. Na tuto skutečnost se musí při implementaci ovladače brát zřetel. FIXME} mapované do paměťového adresního prostoru (sloupec 1) -- o velikostech 32, 128 a 128 bajtů (sloupce 3). Pro čtení/zápis z/do nich je potřeba používat 32-, 16-, 32bitové operace (sloupec 4).\footnote{V manuálu je uvedeno, že za určitých podmínek je možné k BAR1 přistupovat i pomocí 32bitových operací. V této práci bych se tomuto složitějšímu přístupu rád vyhnul. Částečná implementace karty MF624 do emulátoru Qemu (Popsaná v příloze \ref{qemu}) umožňuje \textbf{pouze} 16bitový přístup do BAR1 paměťového regionu.}
 
 \subsection{Digitální vstupy a výstupy}
-Z tabulky \ref{tab_bar} jsme se navíc dozvěděli informaci, že registry ovládající digitální vstupy a výstupy budou ležet zřejmě v regionu BAR1 (sloupec 2). Podíváme se na přehled registrů náležejících tomuto paměťovému regionu (v oficiálním manuálu na straně 12) -- tomu odpovídá tabulka \ref{tab_bar1}.
+Z tabulky \ref{tab_bar} lze vyčíst informaci, že registry ovládající digitální vstupy a výstupy budou ležet zřejmě v regionu BAR1 (sloupec 2). Dále je potřeba se podívat na přehled registrů náležejících tomuto paměťovému regionu (v oficiálním manuálu na straně 12) -- tomu odpovídá tabulka (s menšími úpravami) \ref{tab_bar1}.
 
 \begin{table}[h!]
        \begin{center}
-       \begin{tabular}{|c|c|c|}
-       \hline \textbf{Address} & \textbf{Read} & \textbf{Write} \\ 
-       \hline BADR1 + 0x00 & \textbf{ADDATA} -- A/D data & ADCTRL -- A/D control \\ 
-       \hline BADR1 + 0x02 & \textbf{ADDATA} -- A/D data mirror &  \\ 
-       \hline BADR1 + 0x04 & \textbf{ADDATA} -- A/D data mirror &  \\ 
-       \hline BADR1 + 0x06 & \textbf{ADDATA} -- A/D data mirror &  \\ 
-       \hline BADR1 + 0x08 & \textbf{ADDATA} -- A/D data mirror &  \\ 
-       \hline BADR1 + 0x0A & \textbf{ADDATA} -- A/D data mirror &  \\ 
-       \hline BADR1 + 0x0C & \textbf{ADDATA} -- A/D data mirror &  \\ 
-       \hline BADR1 + 0x0E & \textbf{ADDATA} -- A/D data mirror &  \\ 
-       \hline BADR1 + 0x10 & \textbf{DIN} -- Digital input & \textbf{DOUT} -- Digital output \\ 
-       \hline BADR1 + 0x20 & \textbf{ADSTART} -- A/D SW trigger & \textbf{DA0} -- D/A 0 data \\ 
-       \hline BADR1 + 0x22 &  & \textbf{DA1} -- D/A 1 data \\ 
-       \hline BADR1 + 0x24 &  & \textbf{DA2} -- D/A 2 data \\ 
-       \hline BADR1 + 0x26 &  & \textbf{DA3} -- D/A 3 data \\ 
-       \hline BADR1 + 0x28 &  & \textbf{DA4} -- D/A 4 data \\ 
-       \hline BADR1 + 0x2A &  & \textbf{DA5} -- D/A 5 data \\ 
-       \hline BADR1 + 0x2C &  & \textbf{DA6} -- D/A 6 data \\ 
-       \hline BADR1 + 0x2E &  & \textbf{DA7} -- D/A 7 data \\ 
+       \begin{tabular}{|p{17mm}|c|c|}
+       \hline \textbf{Address (BADR1 offset)} & \textbf{Read} & \textbf{Write} \\ 
+       \hline 0x00 & \textbf{ADDATA} -- A/D data & ADCTRL -- A/D control \\ 
+       \hline 0x02 & \textbf{ADDATA} -- A/D data mirror &  \\ 
+       \hline 0x04 & \textbf{ADDATA} -- A/D data mirror &  \\ 
+       \hline 0x06 & \textbf{ADDATA} -- A/D data mirror &  \\ 
+       \hline 0x08 & \textbf{ADDATA} -- A/D data mirror &  \\ 
+       \hline 0x0A & \textbf{ADDATA} -- A/D data mirror &  \\ 
+       \hline 0x0C & \textbf{ADDATA} -- A/D data mirror &  \\ 
+       \hline 0x0E & \textbf{ADDATA} -- A/D data mirror &  \\ 
+       \hline 0x10 & \textbf{DIN} -- Digital input & \textbf{DOUT} -- Digital output \\ 
+       \hline 0x20 & \textbf{ADSTART} -- A/D SW trigger & \textbf{DA0} -- D/A 0 data \\ 
+       \hline 0x22 &  & \textbf{DA1} -- D/A 1 data \\ 
+       \hline 0x24 &  & \textbf{DA2} -- D/A 2 data \\ 
+       \hline 0x26 &  & \textbf{DA3} -- D/A 3 data \\ 
+       \hline 0x28 &  & \textbf{DA4} -- D/A 4 data \\ 
+       \hline 0x2A &  & \textbf{DA5} -- D/A 5 data \\ 
+       \hline 0x2C &  & \textbf{DA6} -- D/A 6 data \\ 
+       \hline 0x2E &  & \textbf{DA7} -- D/A 7 data \\ 
        \hline 
        \end{tabular} 
        \caption{Registry karty obsažené v regionu BAR1}
@@ -203,9 +202,10 @@ Z tabulky \ref{tab_bar} jsme se navíc dozvěděli informaci, že registry ovlá
        \end{center}
 \end{table}
 
-Asi uprostřed tabulky je řádek, ve kterém je napsáno \textit{DIN -- Digital input, DOUT -- Digital output} -- ten značí registr, který se stará o nastavování digitálních výstupů a čtení digitálních vstupů (Všimněme si, že registr DIN a DOUT mají stejnou adresu i přesto, že na kartě jsou vstupy a výstupy realizovány oddělenými vodiči). 
+Na devátém řádku je napsáno \textit{DIN -- Digital input, DOUT -- Digital output} -- to značí registr, který se stará o nastavování digitálních výstupů a čtení digitálních vstupů (Všimněme si, že registr DIN a DOUT mají stejnou adresu i přesto, že na kartě jsou vstupy a výstupy realizovány oddělenými vodiči). 
 
-Abychom přesně věděli, jak jsou data v registrech reprezentována, podíváme se (v oficiálním manuálu) na stranu 16, kde jsou tyto dva registry podrobně popsány (zde tabulka \ref{tab_din} a \ref{tab_dout}). První sloupec nám určuje, kterých bitů se daný řádek týká. V druhém sloupci je informace o funkci. Třetí sloupec udává výchozí hodnotu. Z toho, co je v tabulkách uvedeno, tedy vidíme, že pro čtení 8bitového digitálního vstupu stačí přečíst spodních 8 bitů DIN registru, horních 8 bitů je potřeba ignorovat. Stejně tak pro nastavení 8bitového digitálního výstupu se zapíše požadovaná hodnota do spodních 8bitů registru DOUT, horních 8 bitů je potřeba ignorovat.
+Jak jsou data v registrech reprezentována, je možné si přečíst (v oficiálním manuálu) na straně 16, kde jsou tyto dva registry podrobně popsány (zde tabulka \ref{tab_din} a \ref{tab_dout}). 
+První sloupec určuje, kterých bitů se daný řádek týká. V druhém sloupci je informace o funkci. Třetí sloupec udává výchozí hodnotu. Z toho, co je v tabulkách uvedeno, plyne, že pro čtení 8bitového digitálního vstupu stačí přečíst spodních 8 bitů DIN registru, horních 8 bitů je potřeba ignorovat. Stejně tak pro nastavení 8bitového digitálního výstupu se zapíše požadovaná hodnota do spodních 8bitů registru DOUT, horních 8 bitů je potřeba ignorovat.
 
 \begin{table}[h!]
        \begin{center}
@@ -235,11 +235,28 @@ Abychom přesně věděli, jak jsou data v registrech reprezentována, podívám
 
 
 \subsection{A/D převodníky}
-TODO
+Karta MF624 obsahuje osm 14bitových A/D převodníků s pevně stanoveným rozsahem $\pm$10 V. Jejich vyčtení může probíhat následujícím způsobem:
+
+\begin{itemize}
+\item Nejprve se v registru ADCTRL zvolí, které A/D převodníky mají být čteny. 
+Každý z A/D převodníků je reprezentován jedním bitem. Zápisem 1 do daného bitu se nastaví, že bude daný A/D převodník aktivní -- 0 ho deaktivuje.
+\item Čtením registru ADSTART se spustí převod na zvolených A/D převod\-nících. Přečtená hodnota se dále nepoužívá.
+\item V případě, že se provedl převod na všech zvolených A/D převodnících, je EOLC bit GPIOC registru nastaven na 0 (jinak je v 1).
+\item Výslednou hodnotu je možné přečíst z registru ADDATA typu FIFO nebo mnohem jednodušší je čtení z jeho zrcadlených hodnot v registrech ADDATA0--ADDATA7 (v manuálu jsou označeny pouze jako \textit{BADR1 + 0x02} až \textit{BADR1 + 0x0E}).
+\end{itemize}
+
+Hodnota vyčtená z A/D převodníků je ve formátu dvojkového doplňku.
 
-Přerušení?
 \subsection{D/A převodníky}
-TODO
+Karta MF624 obsahuje také osm 14bitových D/A převodníků s rozsahem $\pm$10 V.
+
+Nastavení výstupních hodnot D/A převodníků může probíhat následujícícm způsobem:
+
+\begin{itemize}
+\item Hodnota v aditivním kódu (tabulka 23 v originálním manuálu) se zapíše do jednoho z osmi registrů DA0--DA7 odpovídajícího D/A převodníku, který chceme nastavovat
+\item Bit DACEN registru GPIOC je potřeba nastavit na 0, jinak jsou výstupy D/A převodníků připojeny na \textit{zem}.
+\item Bit LDAC registru GPIOC je potřeba nastavit na 0, aby byl spuštěn samotný převod D/A převodníků.
+\end{itemize}
 
 
 
@@ -275,17 +292,17 @@ Jak se takový jaderný modul může vypadat, je nejlepší si ukázat na přík
 
 První věc, na kterou je potřeba upozornit je, že většina jaderných modulů (stejně jako zdrojových kódů jádra samotného) je psána v programovacím jazyce C (jedná se o mírně modifikovaný standard C90).
 \begin{description}
-\item[Řádky 1 a 2] obsahují vložení hlavičkových souborů -- obsahují prototypy námi volaných funkcí a jsou nutné pro tvorbu jaderného modulu.
+\item[Řádky 1 a 2] obsahují vložení hlavičkových souborů -- obsahují prototypy volaných funkcí a jsou nutné pro tvorbu jaderného modulu.
 \item[Na řádcích 4--8] je funkce, která bude spuštěna ihned po zavedení našeho modulu do jádra. Ta obsahuje pouze volání funkce \texttt{printk()}.
 
-Pro jednoduchost můžeme s funkcí \texttt{printk()} pracovat jako s pro nás známou funkcí \texttt{printf()} -- narozdíl od standardního výstupu se však text vypsaný funkcí \texttt{printk()} zapíše do \textit{logu} jádra. Jedním ze způsobů, jak ho zobrazit je pomocí programu \texttt{dmesg}.\\Jak se zařídí, že se tato funkce vykoná ihned po zavedení modulu do jádra? O to se postará příkaz na $\rightarrow$
+Pro jednoduchost můžeme s funkcí \texttt{printk()} pracovat jako s, pro čtenáře známou, funkcí \texttt{printf()} -- narozdíl od standardního výstupu se však text vypsaný funkcí \texttt{printk()} zapíše do \textit{logu} jádra. Jedním ze způsobů, jak ho zobrazit je pomocí programu \texttt{dmesg}.\\Jak se zařídí, že se tato funkce vykoná ihned po zavedení modulu do jádra? O to se postará příkaz na $\rightarrow$
 \item[řádku 15] -- ten obsahuje makro \texttt{module\_init()}, kterému řekneme právě to, která funkce se má po načtení spustit.
 \item[Řádek 16] obsahuje naopak makro, které udává, která funkce se má zavolat v případě, že se bude modul uvolňovat z jádra. V našem případě je to funkce na $\rightarrow$
 \item[řádcích 10--13.] Tato funkce nemá na starost nic jiného než výpis krátkého textu do logu jádra.
 \end{description}
 
 \subsection{Kompilace modulu}
-Nyní je potřeba jaderný modul přeložit\footnote{Před samotným překladem jádra je potřeba mít k dispozici zdrojové kódy jádra. Ty buď stáhneme přímo z \texttt{kernel.org} nebo v distribuci Debian nainstalujeme pomocí příkazu\\\texttt{apt-get install ... FIXME}}. K tomu nám poslouží následující \texttt{Makefile}:
+Dále je potřeba jaderný modul přeložit\footnote{Před samotným překladem jádra je potřeba mít k dispozici zdrojové kódy jádra. Ty buď stáhneme přímo z \texttt{kernel.org} nebo v distribuci Debian nainstalujeme pomocí příkazu\\\texttt{apt-get install ... FIXME}}. K tomu poslouží následující \texttt{Makefile}:
 \begin{verbatim}
 1 |  KERNEL_VER=`uname -r`
 2 |  obj-m += hello.o
@@ -299,7 +316,7 @@ Linux využívá při kompilaci systému \texttt{KBUILD}. Ten je tvořen množst
 
 \begin{description}
 \item[Na prvním řádku] se do proměnné \texttt{KERNEL\_VER} přiřadí verze aktuálně běžícího jádra (po zavolání příkazu \texttt{uname -r}, který tuto informaci vrací)
-\item[Druhý řádek] nám říká, že chceme vytvořit modul ze zdrojového souboru \texttt{hello.c} (pod tímto názvem jsme uložili náš ukázkový modul)
+\item[Druhý řádek] říká, že modul bude vytvářen ze zdrojového souboru \texttt{hello.c} (pod tímto názvem jsme uložili náš ukázkový modul)
 \item[Na pátém řádku] (uvozeném tabelátorem) se volá (pomocí přepínače \texttt{-C}) Makefile ze systému \texttt{KBUILD}, který se nachází v adresáří spolu se zdrojovými kódy jádra. Parametrem \texttt{M} říkáme, které moduly si přejeme vytvořit -- v tomto případě jsou to ty, jejichž zdrojové soubory jsou v aktuálním adresáři (tj. \texttt{PWD}).
 \end{description}
 
@@ -354,7 +371,7 @@ V logu je opět nachází text vypisovaný modulem při uvolňování z jádra.
 
 První věc, kterou ovladač PCI zařízení potřebuje udělat, aby se stal součástí systému, je registrace do seznamu všech PCI ovladačů v operačním systému. To se provede voláním funkce \texttt{pci\_register\_driver()}, které se jako parametr předá ukazatel na strukturu \texttt{struct pci\_driver}. 
 
-\subsection*{Struktura \texttt{struct pci\_driver}}
+\subsection{Struktura \texttt{struct pci\_driver}}
 Tato struktura obsahuje základní informace o našem ovladači. Mezi hlavní položky patří:
 \begin{description}
 \item[\texttt{const char name*}] -- Název ovladače. Tento název by měl být unikátní mezi všemi ovladači PCI zařízení. Většinou je totožný s názvem modulu.
@@ -374,7 +391,7 @@ Příklad, jak může být struktura \texttt{pci\_driver} inicializována a nás
 pci_register_driver(&mf624_pci_driver);
 \end{verbatim}
 
-\subsection*{Struktura \texttt{struct pci\_device\_id}}
+\subsection{Struktura \texttt{struct pci\_device\_id}}
 Jak již bylo zmíněno, struktura \texttt{struct pci\_device\_id} slouží k identifikaci, pro která zařízení je ovladač určen. Mezi hlavní položky struktury patří \texttt{vendor}, \texttt{device}, \texttt{subvendor}, \texttt{subdevice} (typu \texttt{\_\_u32}) -- jejichž hodnota odpovídá stejnojmenným registrům v konfiguračním prostoru PCI zařízení. Jelikož může být ovladač napsán pro více zařízení, je tato struktura inicializována jako prvek pole, které je zakončeno prvkem prázdným. Možná inicializace vypadá následovně:
 
 \begin{verbatim}
@@ -395,7 +412,7 @@ Jak již bylo zmíněno, struktura \texttt{struct pci\_device\_id} slouží k id
 \end{verbatim}
 
 
-\subsection*{Funkce \texttt{probe()}}
+\subsection{Funkce \texttt{probe()}}
 \ibox{\texttt{int probe(struct pci\_dev *dev, const struct pci\_device\_id *id)}}
 
 Funkce \texttt{probe()} náležící danému ovladači zařízení je volána poté, co subsystém PCI zařízení zjistí, že se v systému nachází zařízení, pro které je tento ovladač určen. Tato funkce má na starosti inicializaci zařízení.
@@ -406,7 +423,7 @@ V prvním parametru PCI subsystém předává strukturu \texttt{struct pci\_dev}
 
 V rámci inicializace je nejprve potřeba zavolat funkci \texttt{pci\_enable\_device()} -- ta se postará o inicializaci karty na úrovni hardware -- např.: přiřazení linky přerušení, zresetování registrů karty a její probuzení. Poté již můžeme začít přistupovat ke zdrojům zařízení.
 
-\subsection*{Přístup ke zdrojům karty}
+\subsection{Přístup ke zdrojům karty}
 Jak bylo popsáno v kapitole \ref{pcich}, PCI zařízení může využívat až 6 paměťových nebo vstupně-výstupních regionů (označovaných jako \textit{zdroje} karty). Jejich alokace do paměťového nebo I/O prostoru počítače je zajištěna dynamicky PCI mostem. Pro přístup do nich si musí ovladač zařízení zjistit jejich adresu a vyžádat si u operačního systému výlučný přístup. 
 
 \ibox{\texttt{int pci\_request\_regions(struct pci\_dev *pdev, const char *res\_name);}}
@@ -429,7 +446,7 @@ K ukazateli, který vrátí volání \texttt{pci\_ioremap\_bar()} je již možn
 
 \ibox{FIXME povídání o out-of-order execution a cache a proč musíme používat speciální funkce}
 
-\subsection*{Funkce \texttt{remove()}}
+\subsection{Funkce \texttt{remove()}}
 
 \ibox{\texttt{void remove(struct pci\_dev *dev);}}
 
@@ -468,7 +485,7 @@ Většina z těchto úkonů byla již popsána v kapitole \ref{pcich} a jsou zce
 \ibox{FIXME co je \&pci\_device-dev?}
 Ta se provede zavoláním funkce \texttt{uio\_register\_device()}, kde se jako druhý parametr předá ukazatel na strukturu \texttt{struct uio\_info}.
 
-\subsection*{Struktura \texttt{struct uio\_info}}
+\subsubsection{Struktura \texttt{struct uio\_info}}
 Mezi její hlavní položky patří:
 \begin{description}
 \item[\texttt{const char *name}] -- Název ovladače
@@ -478,7 +495,7 @@ Mezi její hlavní položky patří:
 %\item[\texttt{}]
 \end{description}
 
-\subsection*{Struktura \texttt{struct uio\_mem} a \texttt{struct uio\_port}}
+\subsubsection{Struktura \texttt{struct uio\_mem} a \texttt{struct uio\_port}}
 Tyto struktury obsahují imformace o regionech zařízení -- která ze dvou struktur bude inicializována se rozhoduje na základě toho, zda karta mapuje regiony do paměťového nebo vstupně-výstupního prostoru.
 
 Struktura \texttt{struct uio\_mem} obsahuje položky:
@@ -529,11 +546,36 @@ Příklad, jak taková jednoduchá inicializace struktury \texttt{struct uio\_in
 Na posledním řádku je, dosud nepopsané, volání \texttt{pci\_set\_drvdata()}. To (v tomto případě) zajistí, že struktura \texttt{struct uio\_info} se stane součástí struktury reprezentující zařízení (\texttt{struct pci\_dev}) -- což umožní přístup ke struktuče \texttt{struct uio\_info} z funkcí jako je například funkce \texttt{remove()}, která jako parametr získá ukazatel na strukturu \texttt{struct pci\_dev}
 
 \subsection{Program v uživatelském prostoru}
+Poté, co je jaderná část UIO ovladače úspěšně zkompilována a zavedena do systému, je rozhraní mezi tímto modulem a uživatelským prostorem tvořeno:
+\begin{itemize}
+\item souborem \texttt{/dev/uio0\footnote{Pro názornost zde uvádím konkrétní zařízení \texttt{uio0}. V případě, že systém obsahuje více aktivních UIO ovladačů, jsou postupně číslovány od 0 výše.}}.
+\item složkou \texttt{/sys/class/uio/uio0}, která obsahuje informace o regionech, které jsou zpřístupněny skrze UIO modul v jádře.
+\end{itemize}
+
+\subsubsection{Obsah složky \texttt{/sys/class/uio/uio0}}
+Tato složka obsahuje soubory převážně pouze pro čtení. Obsahuje podložku \texttt{maps}, ve které se nachází pro každý region PCI zařízení mapovaný do paměti (zpřístupněný jaderným ovladačem) složka obsahující soubory popisující tyto regiony (Soubor \texttt{addr} obsahuje fyzickou adresu regionu; \texttt{name} slovní pojmenování; \texttt{size} velikost regionu).
+
+\subsubsection{Soubor \texttt{/dev/uio0}}
+Tento soubor je využíván k samotnému přístupu k regionům karty. K souboru se přistupuje pomocí volání \texttt{mmap()}.
+
+\ibox{void *mmap(void *addr, size\_t length, int prot, int flags, int fd, off\_t offset);}
+
+\begin{description}
+\item[Parametr \texttt{addr}] -- v případě, že není nulový -- určí, na jakou adresu by měla být paměť mapována.
+\item[Parametr \texttt{length}] udává velikost mapované paměti v násobcích velikosti paměťové stránky. 
+\item[Parametr \texttt{prot}] obsahuje příznaky definující, zda bude mapovaná paměť pro čtení/zápis.
+\item[Parametr \texttt{flags}] říká FIXME
+\item[Parametr \texttt{fd}] obsahuje \textit{filedescriptor} na zařízení, které chceme mapovat (v tomto případě \texttt{/dev/uio0}).
+\item[Parametr \texttt{offset}] určuje, zda se zaný soubor/zařízení začne mapovat od posunuté adresy. V případě UIO ovladače je možné jako offset používat násobky velikosti paměťové stránky. Tento offset určí, který z regionů má být namapován.
+\end{description}
+
+FIXME
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \section{Comedi ovladač}
 
-\appendix
-\chapter{Qemu a Humusoft MF624}\label{qemu}
-Měřící karta Humusoft MF624 je hardware vhodný pro výklad implementace ovladače, je ale poměrně drahý. Pro účely výuky proto byly do emulačního software Qemu implementovány základní funkce této měřící karty -- konkrétně se jedná o A/D převodníky, D/A převodníky a digitální vstupy a výstupy. 
+%\appendix
+%\chapter{Qemu a Humusoft MF624}\label{qemu}
+%Měřící karta Humusoft MF624 je hardware vhodný pro výklad implementace ovladače, je ale poměrně drahý. Pro účely výuky proto byly do emulačního software Qemu implementovány základní funkce této měřící karty -- konkrétně se jedná o A/D převodníky, D/A převodníky a digitální vstupy a výstupy. 
 \end{document}