]> rtime.felk.cvut.cz Git - mf6xx.git/blob - doc/diploma_thesis/text/dip_text.tex
6b8c685995d261c96056a60e425e7139df469388
[mf6xx.git] / doc / diploma_thesis / text / dip_text.tex
1 % ==Typografie==
2 % vlna
3 % \item[] a \item s tečkou na konci
4 % odsazování zdrojaku ve verbatim: __X_|__  nebo jen __
5 % Popisy obrázků bez tečky (i s více větami)
6 % Funkce v \ibox{} na konci se středníkem
7
8 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9 \chapter{Úvod}
10 \section{Motivace, cíl}
11 Tato práce vnikla na základě potřeby připravit, zdokumentovat a otestovat prostředí vhodné pro výuku hardwarově zaměřených předmětů. Jedná se především o seznámení s~nízko\-úrovňovým přístupem k hardwaru a vývoj ovladačů. Práce předkládá návod a vlastní řešení určené pro PCI karty a operační systém GNU/Linux. Vytvořená emulace hardwaru jedné z karet umožňuje vytváření a testování vlastních ovladačů bez nutnosti fyzického přístupu k~dané kartě a je přímo použitelná i při vývoji ovladačů pro jiné operační systémy.
12
13 Zvolené vstupně výstupní karty jsou na Katedře řídicí techniky využívané i v mnoha dalších předmětech k propojení počítačů s řízenými modely fyzikálních soustav. Navržené ovladače a otestovaný přístup z operačního systému GNU/Linux tedy umožňuje použít i~variantu plně preemptivního jádra Linux pro řízení modelů s využitím i rozsáhlého matematického aparátu v reálném čase. Reálné nasazení pro přizpůsobený GNU/Linux umožní řízení s reálnými maximálními latencemi menšími než 200 mikrosekund. Robustnost řešení umožňuje další vývoj řídicích algoritmů a v budoucnu po delším testování i využití v reálných průmyslových aplikacích.
14
15
16 Text popisuje základní aspekty práce s PCI zařízeními v jádře Linux a uvádí dva konkrétní způsoby implementace ovladače zařízení PCI -- pro přístup k hardwaru z uživatelského prostoru s minimální nutnou podporou z jádra (UIO ovladač) a plnohodnotný ovladač na úrovni jádra operačního systému začleněný do subsystému určeného pro měřící a řídicí vstupně-výstupní zařízení (Comedi).
17
18  Text obsahuje pouze nezbytné množství teorie, která je podložena četnými příklady pro snadnější pochopení. Pro čtenáře neznalého psaní programů těsně svázaných s hardwarem, jsou názorně vysvětleny základní principy a úskalí tohoto druhu programování.
19 %V případě dalšího zájmu o problematiku může čtenář sáhnout po knize \cite{devicedriver}.
20
21 Jako ukázková zařízení na sběrnici PCI byly zvoleny karty Humusoft MF624 a MF614. Podrobně je popsána jejich funkce, včetně způsobu obsluhy ovladačem. Tyto karty byly zvoleny také z důvodu snadno pochopitelného způsobu obsluhy.
22   
23 Výsledkem práce jsou, kromě popisu vývoje PCI ovladačů, i ovladače typu UIO a Comedi podporující základní funkce (A/D, D/A převodníky a digitální vstupy a výstupy) karet Hu\-musoft MF614 a MF624, které slouží jako jednoduché ukázkové ovla\-dače.
24
25 Pro maximální možné zhodnocení návodů, je cílem práce implementovat některé funkce karty Humusoft MF624 do emulačního programu Qemu tak, aby bylo možné popsané postupy implementace ovladačů vyzkoušet i bez fyzického přístupu ke kartě.
26
27 \section{Dostupné materiály}
28 V českém jazyce dosud vyšla pouze jedna tištěná kniha, která se zabývá problematikou programování v prostředí jádra Linux. Jedná se o knihu Jádro systému Linux \cite{jadrosystemu} od Lukáše Jelínka. Je dělena do 3 základních částí:
29 \textit{Vnější rozhraní jádra}, \textit{Vývoj ovladačů}, \textit{Pohled dovnitř jádra}.
30
31 Jednotlivá témata jsou popsána pouze stručně (kniha je koncipována spíše jako příručka než jako učebnice) a pro čtenáře, neznalého vývoje ovladačů zařízení, nemá příliš velký přínos.
32
33 Za nejpřínosnější knihu, zabývající se problematikou jaderného programování, považuji anglicky psanou knihu Linux Device Drivers \cite{devicedriver} od autorů Jonathan Corbet, Alessandro Rubini a Greg Kroah-Hartman. Tato kniha podrobně vysvětluje jak obecné principy a funkce používané u jaderných ovladačů, tak i způsob implementace ovladačů zařízení konkrétních typů.
34
35 Knihu je možné stáhnout zdarma ve formátu PDF.\footnote{\url{http://lwn.net/Kernel/LDD3/}}
36
37 \begin{figure}[h!]
38         \begin{center}
39         \begin{minipage}[b]{0.4\linewidth}
40                 \includegraphics[width=50mm]{img/jadro-systemu-linux.jpg}
41         \end{minipage}
42         \begin{minipage}[b]{0.4\linewidth}
43                 \includegraphics[width=50mm]{img/lddrivers.jpg}
44         \end{minipage}
45         \caption{\textit{Vlevo}: Kniha Lukáše Jelínka (v českém jazyce). 
46                 \textit{Vpravo}: kniha od autorů Jonathan Corbet, Alessandro Rubini a Greg Kroah-Hartman (v anglickém jazyce)}
47         \label{knihy}
48         \end{center}
49 \end{figure}
50
51
52
53 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
54 \chapter{Hardware}
55 \section{Základní principy komunikace s hardwarem}
56 Komunikace s periferiemi je v nejjednodušších případech založena na čtení a zápisu obsa\-hu registrů mapovaných do adresního prostoru procesoru. V případě jednočipového počítače (mikrokontroléru) již žádné další softwarové a systémové vrstvy do hry nevstupují a~princip lze snadno popsat.
57
58 \ibox{Mikrokontrolér, neboli jednočipový počítač, má velikost pouze jednoho čipu. Obsahuje přitom procesor, paměť, vstupně-výstupní zařízení a jiné. Je obvyklé, aby mikrokontrolér obsahoval tzv. GPIO piny. 
59 \begin{description}
60 \item[GPIO piny (General Purpose Input/Output)] -- u těchto pinů je možné nastavit, zda má být jejich hodnota čtena (slouží jako piny pro vstup informace) nebo zda má být jejich hodnota nastavována (tj. výstupní piny).%
61 %\item[A/D převodník] -- Převádí analogový (spojitý) signál na diskrétní (nespojitý). Příklad: Na vstup A/D převodníku přivedeme napětí 2,4 V. Z registru odpovídajícímu tomuto převodníku si v digitální podobě mikroprocesor vyčte hodnotu odpovídající 2,4.
62 %\item[D/A převodník] -- Opačně od A/D převodníku převádí digitální signál na analogový. Příklad: Do registru odpovídajícímu D/A převodníku zapíše mikroprocesor hodnotu odpovídající např. 3,5 V. Na výstupu bude možné změřit napětí 3,5 V (s určitou malou odchylkou).
63 \end{description}%
64 }
65
66 Prvním způsobem, jak změnit stav (obecného) GPIO pinu (ať už nastavení, zda se má jednat o~vstupní/výstupní pin nebo jakou hodnotu má mít v případě, že je výstupní) je provedení operace zápisu na určitou adresu v paměťovém adresním prostoru (ta je pro konkrétní typ součástky -- nebo celou rodinu příbuzných typů -- pevně daná). 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 ovlivňuje stav hardware. V dokumentaci ke konkrétnímu mikrokontroléru/mikroprocesoru/programo\-vatelnému integrovanému obvodu je uvedeno, jakou funkci mají jednotlivé bity registru.} GPIO pinu. Adresa zápisu je přivedena na adresový dekodér, který zjistí, do které oblasti (vnitřní paměť dat, programu, oblast periferních registrů) adresa náleží. Pokud se jedná o oblast periferií, provede další podrobnější určení, které periferii připojené ke sběrnici data náleží a pověří obvody vybrané periferie dalším zpracováním zapisovaných dat. Zapsaná hodnota se tedy projeví změnou stavu 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 adresního prostoru}.\footnote{Také označováno jako MMIO -- \textit{Memory-mapped input/output}}
67
68 \begin{figure}[h!]
69         \begin{center}
70         \includegraphics[width=130mm]{img/gpio.pdf}
71         \caption{Registr odpovídající GPIO pinům. Změnou hodnoty tohoto registru je možné měnit chování nebo stav GPIO pinů}
72         \label{gpio_pins}
73         \end{center}
74 \end{figure}
75
76
77 U některých procesorových architektur se změna hodnoty registru provede jiným způso\-bem -- použitím, při zápisu do registru, jiné instrukce než která se používá pro paměťové operace -- tj. místo zápisu na adresu v paměťovém prostoru vyhrazenou pro GPIO registr, se provede zápis do tzv. \textbf{vstupně-výstupního adresního prostoru}\footnote{Také označován zkratkou PIO -- \textit{Programmed input/output} nebo jako I/O adresní prostor} na adresu (v~tomto případě označovanou jako \textbf{port}) odpovídající registru GPIO pinů. Adresy paměťového a~vstupně-výstupního adresního prostoru jsou nezávislé. V případě zápisu a čtení do/z portu I/O adresního prostoru je potřeba z dokumentace \textbf{přesně vědět} jak široká (kolikabitová) slova je možné zapisovat/číst. 
78
79 \ibox{V případě architektury IA-32 (označované také jako x86) máme k dispozici paměťový a vstupně-výstupní adresní prostor. Adresy vstupně výstupního adresního prostoru jsou pouze 16bitové, zatímco paměťového jsou (\textit{pro zjednodušení není brán ohled na PAE -- Physical Address Extension}) 32bitové. Toto rozdělení přetrvává z historických důvodů -- i~přesto je již možné některá zařízení mapovat do paměťového prostoru. (Znázorněno na obrázku \ref{mmio}.)
80
81 \vspace{1mm}
82 Informace o obsazenosti paměťového a vstupně-výstupního adresního prostoru je možné v GNU/Linuxu zjistit čtením souboru \texttt{/proc/iomem} a \texttt{/proc/ioports}.
83 }
84
85 Hlavní rozdíly mezi chováním paměťové buňky a registru zařízení jsou:
86 \begin{itemize}
87 \item Změnou hodnoty registru je možné měnit stav zařízení/periferie odpovídající danému registru.
88 \item V případě zápisu do registru a jeho okamžitém čtení, nemusí být přečtená hodnota shodná se zapisovanou -- v tom případě byla hodnota registru změněna hardwarem.
89 \item V případě čtení z registru může být spuštěn tzv. \textbf{side effect}, kdy hardware na toto čtení reaguje změnou stavu, podobně jako by byl proveden zápis do registru (Příklad: ihned po vyčtení hodnoty registru A/D převodníku se spustí nový převod a původní hodnota se přepíše novou). Side effects mohou nastat i při zápisu do registru. 
90 \item Při zápisu a čtení do/z registru je nutné přesně rozlišovat, kolika-bitové operace zápisu/ čtení smějí být použity (8-, 16-, 32bitové).
91 \item Při přístupu k registrům mapovaným do paměťového adresního prostoru (z jádra operačního systému nebo z uživatelského programu), je nutné o této skutečnosti \textit{upozornit} jak překladač, tak samotný procesor. Důvodem jsou optimalizace, které mohou být provedeny -- které při přístupu do obyčejné paměti mohou program zrychlit, ale při přístupu do registru mohou způsobit nesprávnou funkci programu. Podrobněji je tento problém popsán v kapitole \ref{iofce}.
92 \end{itemize}
93
94 \vspace{1.5cm}
95
96 \begin{figure}[h!]
97         \begin{center}
98         \includegraphics[width=100mm]{img/mmio.pdf}
99         \caption{Paměťový a vstupně-výstupní adresní prostor u architektury IA-32}
100         \label{mmio}
101         \end{center}
102 \end{figure}
103
104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
105 \clearpage
106 %\newpage
107 \section{PCI sběrnice}\label{pcich}
108 %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í.
109
110 PCI (\textit{Peripheral Component Interconnect}) je standard paralelní sběrnice využívaný v~počí\-ta\-čích různých architektur. Šířka paralelně přenášených dat je 32 nebo v modernější, méně často používané verzi, 64 bitů. Sběrnice je orientována na přenos zpráv oproti přímé komunikaci mezi zařízeními.\footnote{Tj. místo toho, aby PCI most přistupoval přímo k paměti jednotlivých zařízení, vyšle se na sběrnici zprá\-va s požadavkem. V případě, že je některé zařízení schopno požadavek obsloužit, umístí na datovou sběrnici požadovaná data. (Takto probíhá komunikace na úrovni sběrnice -- ze strany procesoru se jedná pouze o~zápis/ čtení paměťového/vstupně-výstupního adresního prostoru.)}
111
112 Komunikace mezi zařízeními připojenými na sběrnici a procesorem zajišťuje tzv. \textit{PCI most} (PCI bridge). Propojení více nezávislých sběrnic v jednom počítači jsou zajištěny také PCI mosty.
113
114 \subsection{Historie}
115 V roce 1990 začala práce na specifikaci PCI v laboratořích firmy Intel. První specifikace definující jak komunikační protokol, tak vzhled konektoru a slotu, byla zveřejněna 30. dubna 1993 (jedná se o PCI 2.0). PCI sběrnice se poté začala objevovat v počítačích architektury IBM PC a PowerPC.
116
117 V pozdějších letech se původní standard dočkal vylepšení -- zvýšení šířky paralelní sběrnice z 32 bitů na 64 bitů a zrychlení z 33 MHz na 66 Mhz a výše. Tyto pokročilejší verze se však příliš neujaly.
118 \subsection{Konektory}
119 Pro spojení mezi kartou a sběrnicí je potřeba pouze konektor na straně sběrnice -- tzv. slot. V závislosti na napájecím napětí (3,3 V nebo 5 V) jsou na kartách \textit{klíčovací} zářezy -- tyto zářezy znemožňují zasunutí \textit{napěťově nekompatibilní} karty do slotu. Existují však univerzální karty, které mají tyto zářezy oba, díky čemuž mohou být použity v libovolném slotu (obr. \ref{pci}).
120
121 \begin{figure}[h!]
122         \begin{center}
123         \begin{minipage}[b]{0.4\linewidth}
124                 \includegraphics[width=57mm]{img/pci_schema2.png}
125         \end{minipage}
126         \begin{minipage}[b]{0.4\linewidth}
127                 \includegraphics[width=50mm]{img/pci2.jpg}
128         \end{minipage}
129         \caption{\textit{Vlevo}: Schéma znázorňující rozdíly mezi konektory pro karty s napájením 3,3 V a 5 V. \textit{Vpravo}: Reálná fotografie PCI konektorů}
130         \label{pci}
131         \end{center}
132 \end{figure}
133
134
135 \subsection{Dynamická konfigurace a konfigurační adresní prostor}\label{pci_conf}
136 Mezi hlavní výhody PCI sběrnice (oproti její předchůdkyni -- sběrnici ISA) patří dynamická konfigurace připojených zařízení: Ve většině případů probíhá komunikace mezi hostitelským systémem a připojenou (a nakonfigurovanou) PCI kartou zápisem/čtením do určité paměťové (nebo vstupně-výstupní) oblasti. U starší sběrnice ISA bylo při návrhu karty nebo propojkami na kartě, při jejím zapojení do PC, pevně určeno, kam se její část paměti namapuje -- v takovém případě mohl nastat problém, že více než jedna karta mapovala svoji paměť na stejnou adresu (nebo se jednotlivá mapování překrývala). PCI sběrnice tomuto problému předchází takovým způsobem, že každá z karet nese informaci o~tom, kolik jak velkých paměťových nebo I/O regionů potřebuje namapovat -- o samotné mapování se poté dynamicky postará BIOS počítače nebo PCI subsystém operačního systému.
137
138 Informaci o tom, kolik (a jaké) paměti karta bude potřebovat má před nakonfigurováním uloženu v tzv. \textbf{Base Address Registrech} -- BAR0--BAR5\footnote{Informace o velikosti požadované oblasti je v registru uložena takovým způsobem, že je pouze jeho část určena k zápisu a zbytek je pouze pro čtení. PCI most se pokusí do registru zapsat hodnotu 0xFFFFFFFF, poté je hodnota zpět vyčtena -- z bitů náležejících do zapisovatelné části registru, je přečtena $1_2$, zbývající část obsahuje hodnoty $0_2$.}. Poté co se (při konfiguraci) podaří tuto hodnotu přečíst a požadovanou paměť alokovat, zapíše se zpět do daného registru adresa, na které se alokovaná paměť nachází. Tu si poté pro potřeby komunikace vyčte ovladač zařízení, který je součástí operačního systému.
139
140
141 Kromě výše zmíněných 6 BAR registrů, obsahují PCI zařízení i následující registry:
142 \begin{description}
143 \item[Vendor ID]~\\Obsahuje unikátní 16bitové číslo identifikující výrobce zařízení. Za poplatek je udělo\-váno PCI-SIG (\textit{PCI Special Interest Group}) organizací.\footnote{V Debianu, po nainstalování balíčku \texttt{hwdata}, se seznam těchto identifikátorů nachází v souboru \texttt{/usr/share/hwdata/pci.ids}}
144 \item[Device ID]~\\Obsahuje 16bitové číslo identifikující model zařízení. Hodnotu tohoto identifikátoru si volí sám výrobce zařízení.
145 \item[Class code]~\\Označuje (ve 24 bitech) druh zařízení -- zda se jedná např. o grafickou kartu, zvukovou kartu nebo kartu zpracovávající signál.
146 \item[Subsystem Vendor ID]~\\Podobá se Vendor ID. V případě, že karta využívá PCI řadič třetí strany, jako Vendor ID se zobrazí ID výrobce tohoto řadiče. Aby bylo možné zařízení odlišit od jiného, které využívá stejný řadič, skutečné ID zařízení bude uloženo v tomto registru.
147 \item[Subsystem ID]~\\Opět se jedná o údaj podobný Device ID sloužící k rozlišení karet postavených na univerzálním řadiči.
148 \end{description}
149
150 Registry Vendor ID, Device ID (příp. ještě Subsystem Vendor ID a Subsystem ID) slouží operačnímu systému k jednoznačné identifikaci zařízení, při volbě správného ovladače.
151
152
153 \begin{figure}[h!]
154         \begin{center}
155         \includegraphics[width=100mm]{img/pci-config-space2.pdf}
156         \caption{Obsah 256 bajtů konfiguračního prostoru PCI karty (zvýrazněny jsou nejdůle\-žitější registry)}
157         \label{sa1}
158         \end{center}
159 \end{figure}
160
161 Výše popsané registry (spolu s ostatními, které zde nebyly popsány) se nacházejí v~256bito\-vém tzv. \textbf{konfiguračním adresním prostoru} karty (obr. \ref{sa1}).\footnote{Po paměťovém a vstupně-výstupním adresním prostoru je zde třetí -- konfigurační -- adresní prostor.} Pro \textit{konfigurační} adresní prostor není hardwarová podpora v téměř žádné procesorové architektuře -- přístup do něj je například na architektuře IA-32 možný pomocí zapsání adresy (\textit{kam má být v~konfiguračním prostoru zapisováno}) a dat (\textit{která mají být do konfiguračního prostoru zapsána}) do dvou speciálních I/O portů, které jsou pro tuto operaci vyhrazeny.\footnote{Toto je možné považovat za \textit{klasický} způsob přístupu. Na moderních procesorech architektury IA-32 je již možné konfigurační adresní prostor namapovat do paměťového adresního prostoru.}
162
163
164 \subsection{Přerušení}
165 Sběrnice PCI obsahuje čtyři linky přerušení a všechny z nich jsou dostupné každému zařízení. Přerušení mohou být sdílená, tudíž o jedno přerušení se může dělit více zařízení. Pro snazší sdílení, jsou přerušení úrovňově spouštěná (oproti hranovému spouštění nedochází k promeškání přerušení).
166
167 V pozdějších revizích PCI specifikací je přidána podpora pro přerušení signalizované zprávou. V tomto případě zařízení oznamuje svůj požadavek na obsloužení zápisem do paměti PCI mostu -- ten poté tento požadavek směruje dále k procesoru.
168
169 \subsection{Budoucnost}
170 V posledních letech je na poli osobních počítačů PCI sběrnice nahrazována její nástupkyní -- sběrnicí PCIe (\textit{PCI Express}). Ta je na rozdíl od PCI sériová a dosahuje rychlostí až 16 GiB/s. I~přesto je sběrnice PCI stále využívána mnohými zařízeními -- převážně v průmyslu.
171
172 PCI Express zařízení využívají, podobně jako PCI, konfigurační prostor (o velikosti 4 KiB). Prvních 256 bajtů je totožných s konfiguračním prostorem PCI zařízení (registry jako Vendor ID, BAR, apod. jsou totožné). PCIe sběrnice umožňuje nejen připojení jiné PCI sběrnice pomocí PCIe--PCI mostu, ale také připojení zařízení na sběrnici PCIe, jehož logická funkce je totožná s PCI zařízením. Postupy týkající se PCI sběrnice, popsané v této práci, jsou tedy přímo aplikovatelné i na zařízení typu PCIe.
173
174 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
175 \newpage
176 \section{Humusoft MF624}
177 \begin{figure}[h!]
178         \begin{center}
179         \includegraphics[width=150mm]{img/mf624.jpg}
180         \caption{Měřící karta Humusoft MF624}
181         \label{mf624}
182         \end{center}
183 \end{figure}
184
185 Měřící karta Humusoft MF624 (obr. \ref{mf624}), připojitelná k počítači pomocí PCI sběrnice, má pro účely výkladu psaní ovladačů několik nesporných výhod:
186 \begin{itemize}
187 \item Komunikace (na úrovni ovladače) s kartou probíhá snadno pochopitelným, přímo\-čarým způsobem, kdy je pouze zapisováno (nebo čteno) do registrů karty (bude vysvětleno dále).
188 \item Je možné si ověřit správnou funkci napsaného ovladače -- např. připojením LED diody k digitálnímu výstupu nebo měřením napětí na výstupu D/A převodníku.
189 \end{itemize}
190
191 Karta MF624 najde své uplatnění hlavně v laboratorním prostředí -- v případech, kdy je potřeba zpřístupnit měřené hodnoty senzorů. V případě analogových, resp. digitálních signálů jsou použity A/D převodníky, resp. digitální vstupy. Kartu je možné použít i pro řízení akčního členu/zařízení -- k dispozici jsou D/A převodníky a digitální výstupy.
192
193 ~\\~\\
194
195 Karta disponuje následujícími funkcemi (v popisu implementace ovladačů se omezím pouze na A/D, D/A převodníky a digitální vstupy/výstupy):
196 \begin{itemize}
197 \item 8 digitálních vstupů (TTL kompatibilní logické úrovně)
198 \item 8 digitálních výstupů (TTL kompatibilní logické úrovně)
199 \item 8 14bitových A/D převodníků (rozsah $\pm$10 V)
200 \item 8 14bitových D/A převodníků (rozsah $\pm$10 V)
201 \item 4 časovače/čítače
202 \item 4 vstupy inkrementálních snímačů
203 \end{itemize}
204
205 \subsection{Komunikace s kartou}\label{hum_komunikace}
206 Komunikace s kartou není nijak složitá -- zjednodušeně by se dala popsat následovně:
207 \begin{itemize}
208 \item V případě čtení hodnoty digitálních vstupů, přečte se hodnota registru určeného právě digitálním vstupům -- v případě zápisu na digitální výstupy, se zapíše do registru určeného digitálním výstupům.
209 \item V případě čtení hodnoty A/D převodníku, se nejprve zapíše do konfiguračního registru A/D převodníku hodnota odpovídající požadované konfiguraci. Poté se již z registru náležícího A/D převodníku vyčte požadovaná hodnota.
210 \end{itemize}
211
212 Které registry karta obsahuje, jakou mají funkci a na jakých adresách jsou umístěny je možné zjistit z oficiálního manuálu ke kartě -- ten je možné stáhnout z internetových stránek výrobce: \url{http://www2.humusoft.cz/www/datacq/manuals/mf624um.pdf}.
213
214 Po jeho otevření je na straně 11 k vidění první důležitá tabulka (zde tab. \ref{tab_bar}):
215
216 \begin{table}[h!]
217         \begin{center}
218         \begin{tabular}{|p{2cm}|p{4cm}|c|c|}
219         \hline \textbf{Region} & \textbf{Function} & \textbf{Size (bytes)} & \textbf{Width (bytes)} \\ 
220         \hline BADR0 (memory mapped) & PCI chipset, interrupts, status bits, special functions & 32 & 32 \\ 
221         \hline BADR1 (memory mapped) & A/D, D/A, digital I/O & 128 & 16/32 \\ 
222         \hline BADR2 (memory mapped) & Counter/timer chip & 128 & 32 \\ 
223         \hline 
224         \end{tabular} 
225         \caption{Paměťové regiony, které využívá karta MF624}
226         \label{tab_bar}
227         \end{center}
228 \end{table}
229
230 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 -- na počítačích s procesory rodiny IA-32 a s operačním systémem GNU/Linux však karta využívá BAR0, BAR2 a BAR4. Důvod rozdílu mezi skutečností a manuálem není jasný. Skutečné použití BAR registrů musí být před implementací ovladače zkontrolováno na konkrétním systému.} mapované do paměťového adresního prostoru -- o velikostech 32, 128 a 128 bajtů. \\
231 Pro čtení/zápis z/do nich je potřeba používat 32-, 16- a 32bitové operace.\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 raději vyhnul. Částečná implementace karty MF624 do emulátoru Qemu (popsaná v kapitole \ref{qemu}) umožňuje \textbf{pouze} 16bitový přístup do BAR1 paměťového regionu.}
232
233 \subsection{Digitální vstupy a výstupy}
234 Z tabulky \ref{tab_bar} lze vyčíst informaci, že registry ovládající digitální vstupy a výstupy leží 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 -- tomu odpovídá tabulka (s menšími úpravami) \ref{tab_bar1}.
235
236 \begin{table}[h!]
237         \begin{center}
238         \begin{tabular}{|p{17mm}|c|c|}
239         \hline \textbf{Address (BADR1 offset)} & \textbf{Read} & \textbf{Write} \\ 
240         \hline 0x00 & \textbf{ADDATA} -- A/D data & ADCTRL -- A/D control \\ 
241         \hline 0x02 & \textbf{ADDATA} -- A/D data mirror &  \\ 
242         \hline 0x04 & \textbf{ADDATA} -- A/D data mirror &  \\ 
243         \hline 0x06 & \textbf{ADDATA} -- A/D data mirror &  \\ 
244         \hline 0x08 & \textbf{ADDATA} -- A/D data mirror &  \\ 
245         \hline 0x0A & \textbf{ADDATA} -- A/D data mirror &  \\ 
246         \hline 0x0C & \textbf{ADDATA} -- A/D data mirror &  \\ 
247         \hline 0x0E & \textbf{ADDATA} -- A/D data mirror &  \\ 
248         \hline 0x10 & \textbf{DIN} -- Digital input & \textbf{DOUT} -- Digital output \\ 
249         \hline 0x20 & \textbf{ADSTART} -- A/D SW trigger & \textbf{DA0} -- D/A 0 data \\ 
250         \hline 0x22 &  & \textbf{DA1} -- D/A 1 data \\ 
251         \hline 0x24 &  & \textbf{DA2} -- D/A 2 data \\ 
252         \hline 0x26 &  & \textbf{DA3} -- D/A 3 data \\ 
253         \hline 0x28 &  & \textbf{DA4} -- D/A 4 data \\ 
254         \hline 0x2A &  & \textbf{DA5} -- D/A 5 data \\ 
255         \hline 0x2C &  & \textbf{DA6} -- D/A 6 data \\ 
256         \hline 0x2E &  & \textbf{DA7} -- D/A 7 data \\ 
257         \hline 
258         \end{tabular} 
259         \caption{Registry karty MF624 obsažené v regionu BAR1}
260         \label{tab_bar1}
261         \end{center}
262 \end{table}
263
264 Na devátém řádku jsou zmíněny \texttt{DIN} (Digital input) a \texttt{DOUT} (Digital output) registry. Z~této tabulky je zřejmá pozice těchto registrů v paměťovém prostoru (tj. offset v bytech vůči adrese BAR1).
265
266 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}). 
267 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 8 bitů registru DOUT, horních 8 bitů je potřeba ignorovat.
268
269 \begin{table}[h!]
270         \begin{center}
271         \begin{tabular}{|c|c|c|}
272         \hline \textbf{Bit} & \textbf{Description} & \textbf{Default} \\ 
273         \hline 7:0 & \textbf{Digital input 7:0.} Reads digital input port. & 1 \\ 
274         \hline 15:8 & Reserved & N/A \\ 
275         \hline 
276         \end{tabular} 
277         \caption{DIN -- Digital Input Register Format}
278         \label{tab_din}
279         \end{center}
280 \end{table}
281
282 \begin{table}[h!]
283         \begin{center}
284         \begin{tabular}{|c|c|c|}
285         \hline \textbf{Bit} & \textbf{Description} & \textbf{Default} \\ 
286         \hline 7:0 & \textbf{Digital output 7:0.} Writes to digital output port. & 0 \\ 
287         \hline 15:8 & Reserved & N/A \\ 
288         \hline 
289         \end{tabular} 
290         \caption{DOUT -- Digital Output Register Format}
291         \label{tab_dout}
292         \end{center}
293 \end{table}
294
295
296 \subsection{A/D převodníky}
297 Karta MF624 obsahuje osm 14bitových A/D převodníků s pevně stanoveným měřeným rozsahem $\pm$10 V. Jejich vyčtení může probíhat následujícím způsobem:
298
299 \begin{itemize}
300 \item Nejprve se v registru ADCTRL zvolí, které A/D převodníky mají být čteny. 
301 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. Je možné zvolit více než jeden A/D převodník.
302 \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á.
303 \item V případě, že se úspěšně provedl převod na všech zvolených A/D převodnících, je EOLC bit (17. bit) GPIOC registru nastaven na 0 (jinak je v 1).
304 \item Výslednou hodnotu je možné přečíst z registru ADDATA, který je typu FIFO. To zna\-mená, že opětovným čtením jednoho registru jsou vyčítány jednotlivé naměřené hod\-noty z měřených A/D převodníků v pořadí od 0 do 7.
305
306 Jinou možností je místo čtení registru ADDATA číst některý z jeho \textit{zrcadlených registrů} (celkem je jich 7, v manuálu jsou označeny jako \textit{BADR1 + 0x02} až \textit{BADR1 + 0x0E}). Tyto registry se chovají \textbf{zcela stejně} jako registr ADDATA, pouze leží na jiných adresách. Příklad: pokud byly aktivovány první čtyři A/D převodníky, po převodu je možné výslednou hodnotu vyčíst opakovaným čtením registru ADDATA nebo čtením registru ADDATA, ADDATA1, ADDATA2, ADDATA3 přesně v tomto pořadí. Čtení z registrů v jiném pořadí bude stále vracet hodnoty převodníků 0--4.
307 \end{itemize}
308
309 Hodnota vyčtená z A/D převodníků je ve formátu dvojkového doplňku -- příklad konkrét\-ních hodnot je v tabulce \ref{tab_adval}.
310
311
312 \subsection{D/A převodníky}
313 Karta MF624 obsahuje také osm 14bitových D/A převodníků s rozsahem $\pm$10 V.
314
315 Nastavení výstupních hodnot D/A převodníků může probíhat následujícím způsobem:
316
317 \begin{itemize}
318 \item Hodnota v aditivním kódu (tabulka \ref{tab_daval}) se zapíše do jednoho z osmi registrů DA0--DA7 odpovídajícího D/A převodníku, který má být nastaven.
319 \item Bit DACEN (26. bit) registru GPIOC je potřeba nastavit na 1, jinak jsou výstupy D/A převodníků připojeny na \textit{zem}.
320 \item Bit LDAC (23. bit) registru GPIOC je potřeba nastavit na 0, aby byl spuštěn samotný převod D/A převodníků (jinak zůstane zapsaná hodnota pouze v registru, výstupní hodnota D/A převodníku zůstane nezměněna).
321 \end{itemize}
322
323
324 \begin{table}[h!]
325         \begin{center}
326         \begin{tabular}{|c|c|}
327         \hline \textbf{Digitální hodnota} & \textbf{Analogová hodnota} \\ 
328         \hline 0x3FFF & -0.0012 V \\ 
329         \hline 0x2000 & -10.0000 V \\ 
330         \hline 0x1FFF &  9.9988 V \\ 
331         \hline 0x0000 &  0.0000 V \\ 
332         \hline 
333         \end{tabular} 
334         \caption{Kódování vstupních hodnot A/D převodníku}
335         \label{tab_adval}
336         \end{center}
337 \end{table}
338
339
340 \begin{table}[h!]
341         \begin{center}
342         \begin{tabular}{|c|c|}
343         \hline \textbf{Digitální hodnota} & \textbf{Analogová hodnota} \\ 
344         \hline 0x3FFF &  9.9988 V \\ 
345         \hline 0x2000 &  0.0000 V \\ 
346         \hline 0x1FFF & -0.0012 V \\ 
347         \hline 0x0000 & -10.0000 V \\ 
348         \hline 
349         \end{tabular} 
350         \caption{Kódování vstupních hodnot D/A převodníku}
351         \label{tab_daval}
352         \end{center}
353 \end{table}
354
355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
356 \newpage
357 \section{Humusoft MF614}
358 \begin{figure}[h!]
359         \begin{center}
360         \includegraphics[width=150mm]{img/mf614.jpg}
361         \caption{Měřící karta Humusoft MF614}
362         \label{mf614}
363         \end{center}
364 \end{figure}
365
366 Karta Humusoft MF614 má podobné funkce a využití jako karta MF624. Ve skutečnosti se jedná o její předchůdkyni. 
367
368 Karta disponuje následujícími funkcemi:
369
370 \begin{itemize}
371 \item 8 digitálních vstupů (TTL kompatibilní logické úrovně)
372 \item 8 digitálních výstupů (TTL kompatibilní logické úrovně)
373 \item 8 12bitových A/D převodníků (volitelné rozsahy $\pm$10 V, $\pm$5 V, 0--5 V, 0--10 V)
374 \item 4 12bitových D/A převodníků (rozsah $\pm$10 V)
375 \item 4 časovače/čítače
376 \item 4 vstupy inkrementálních snímačů
377 \end{itemize}
378
379 \subsection{Komunikace s kartou}
380 Způsob komunikace s kartou MF614 se mírně liší od MF624.
381
382 Po nahlédnutí do manuálu (dostupný ze stránek výrobce: \url{http://www2.humusoft.cz/www/datacq/manuals/mf614um.pdf}) je z tabulky 9 (zde tab. \ref{tab_mf614_bars}) patrné, že karta využívá více regionů než MF624, přičemž některé jsou mapovány do paměti, jiné do vstupně-výstup\-ního adresního prostoru. Po prohlédnutí tabulky popisující rozložení registrů (zde tab. \ref{tab_mf614_regs}) je zřejmé, že pro přístup k digitálním vstupům/výstupům a analogovým vstupům/výstupům jsou použity vstupně-výstupní regiony BAR0, BAR2. 
383
384 \begin{table}[h!]
385         \begin{center}
386         \begin{tabular}{|c|c|c|}
387         \hline \textbf{Region}          & \textbf{Function}                                             & \textbf{Size (bytes)} \\ 
388         \hline BADR0 (I/O mapped)       & Board programming registers                           & 32 \\ 
389         \hline BADR1 (I/O mapped)       & Reserved                                                                      & 4 \\ 
390         \hline BADR2 (I/O mapped)       & OX9162 local configuration registers          & 32 \\ 
391         \hline BADR3 (memory mapped) & OX9162 local configuration registers     & 4096 \\ 
392         \hline BADR4 (memory mapped) & Board programming registers                              & 4096 \\ 
393         \hline 
394         \end{tabular} 
395         \caption{Paměťové a vstupně-výstupní regiony, které využívá karta MF614}
396         \label{tab_mf614_bars}
397         \end{center}
398 \end{table}
399
400
401 \begin{table}[h!]
402         \begin{center}
403         \begin{tabular}{|c|c|c|}
404         \hline \textbf{Address} & \textbf{Read} & \textbf{Write} \\ 
405         \hline BADR0 + 0x0 & \textbf{ADLO} -- A/D data low                      & \textbf{ADCTRL} -- A/D control \\ 
406         \hline BADR0 + 0x1 & \textbf{ADHI} -- A/D data high                     &  \\ 
407         \hline BADR0 + 0x2 & \textbf{9513A} -- Data read                                & \textbf{9513A} -- Data write \\ 
408         \hline BADR0 + 0x3 & \textbf{9513A} -- Command read                     & \textbf{9513A} -- Command write \\ 
409         \hline BADR0 + 0x4 &  &  \\ 
410         \hline BADR0 + 0x5 &  &  \\ 
411         \hline BADR0 + 0x6 & \textbf{DIN} -- Digital input                      & \textbf{DOUT} -- Digital output \\ 
412         \hline BADR0 + 0x7 &  &  \\ 
413         \hline BADR0 + 0x8 & \textbf{DALE} -- D/A latch enable          & \textbf{DA0LO} -- D/A 0 data low byte \\ 
414         \hline BADR0 + 0x9 &                                                                            & \textbf{DA0HI} -- D/A 0 data high byte \\ 
415         \hline BADR0 + 0xA &                                                                            & \textbf{DA1LO} -- D/A 1 data low byte \\ 
416         \hline BADR0 + 0xB &                                                                            & \textbf{DA1HI} -- D/A 1 data high byte \\ 
417         \hline BADR0 + 0xC &                                                                            & \textbf{DA2LO} -- D/A 2 data low byte \\ 
418         \hline BADR0 + 0xD &                                                                            & \textbf{DA2HI} -- D/A 2 data high byte \\ 
419         \hline BADR0 + 0xE &                                                                            & \textbf{DA3LO} -- D/A 3 data low byte \\ 
420         \hline BADR0 + 0xF &                                                                            & \textbf{DA3HI} -- D/A 3 data high byte \\ 
421         \hline \ldots & \ldots & \ldots \\      
422         \hline BADR2 + 0x10 & \textbf{STATUS} -- Status register & \\   
423         \hline 
424         \end{tabular} 
425         \caption{Registry karty MF614 náležící digitálním vstupům/výstupům a analogovým vstupům/výstupům}
426         \label{tab_mf614_regs}
427         \end{center}
428 \end{table}
429
430 Jednotlivé registry v těchto regionech jsou 8bitové, proto je potřeba při čtení/zápisu používat pouze 8bitové funkce. 16bitové hodnoty jsou rozděleny do dvou 8bitových registrů -- v takovém případě, obsahuje-li registr ve svém názvu písmena \textbf{LO}, jedná se o spodní bajt, zatímco \textbf{HI} značí horní bajt. Výsledná 16bitová hodnota se získá složením dvou 8bitových:
431 \begin{verbatim}
432   u8 regAHI, regALO;
433   u16 regA;
434    
435   regA = regALO | (regAHI << 8);
436 \end{verbatim}
437
438 \subsection{Digitální vstupy a výstupy}
439 Pro nastavení hodnoty digitálních výstupů se zapíše požadovaná hodnota do registru DOUT, kde jeden bit odpovídá jednomu digitálnímu výstupu. Pro čtení digitálních vstupů je potřeba přečíst hodnotu registru DIN.
440
441 \subsection{A/D převodníky}
442 Čtení A/D převodníků je u karty MF614 oproti MF624 trochu složitější, hlavně díky tomu, že je u převodníků potřeba nastavit, v jakém rozsahu bude provedeno měření. Je možné vybírat mezi rozsahy -10--10 V, -5--5 V, 0--10 V, 0--5 V. 
443
444 K nastavení vlastností A/D převodníků slouží registr ADCTRL (přeložená tab. \ref{tab_mf614_adctrl}). Bity 2:0 slouží k volbě jednoho z osmi A/D převodníků, které budou při příštím měření použity. Dekadická hodnota určující pořadí A/D převodníku je uložena ve třech bitech jako binární číslo (tj. $0_{10} = 000_{2}$, $1_{10} = 001_{2}$, $2_{10} = 010_{2}$, $3_{10} = 011_{2}$, $4_{10} = 100_{2}$, \ldots). 
445
446 Bity 3 a 4 slouží k nastavení použitého rozsahu (způsob nastavení viz tabulka \ref{tab_mf614_rng}).
447
448 Bity 5, 6 a 7 nemají žádnou funkci a musí bát nastaveny na 0, 1, 0.
449
450 \begin{table}[h!]
451         \begin{center}
452         \begin{tabular}{|c|c|c|}
453         \hline \textbf{Bit} & \textbf{Jméno} & \textbf{Popis} \\ 
454         \hline  7                       &                               & Musí být nastaveno na 0 \\ 
455         \hline  6                       &                               & Musí být nastaveno na 1 \\ 
456         \hline  5                       &                               & Musí být nastaveno na 0 \\ 
457         \hline  4                       & RNG                   & Nastavení měřeného rozsahu A/D převodníku (tab. \ref{tab_mf614_rng}) \\ 
458         \hline  3                       & BIP                   & Nastavení, zda bude měřený rozsah \textit{bipolární} (tab. \ref{tab_mf614_rng}) \\ 
459         \hline  2, 1, 0         & A2, A1, A0    & Výběr A/D převodníku pro příští měření \\ 
460         \hline 
461         \end{tabular} 
462         \caption{Funkce jednotlivých bitů registru ADCTRL}
463         \label{tab_mf614_adctrl}
464         \end{center}
465 \end{table}
466
467 \begin{table}[h!]
468         \begin{center}
469         \begin{tabular}{|c|c|c|}
470         \hline \textbf{RNG} & \textbf{BIP} & \textbf{Vstupní rozsah [V]} \\ 
471         \hline  0                       &       0                       & 0--5 V \\ 
472         \hline  1                       &       0                       & 0--10 V \\ 
473         \hline  0                       &       1                       & -5--5 V \\ 
474         \hline  1                       &       1                       & -10--10 V \\ 
475         \hline 
476         \end{tabular} 
477         \caption{Volba rozsahu A/D převodníku}
478         \label{tab_mf614_rng}
479         \end{center}
480 \end{table}
481
482 Vyčtení hodnoty A/D převodníku může probíhat následujícím způsobem:
483
484 \begin{itemize}
485 \item Nejprve se v registru ADCRTL zvolí, který A/D převodník bude čten a který měřící rozsah bude použit.
486 \item Zápis do registru ADCTRL automaticky spouští převod.
487 \item Je-li CC bit (2. bit) registru STATUS nastaven na 0, převod již byl ukončen.
488 \item Data je poté možné přečíst z registru ADLO a ADHI -- jedná se o 8bitové registry, které je potřeba pro získání 12 bitové výsledné hodnoty \textit{složit} dohromady. Je-li nastaven unipolární rozsah měření (tj. 0--5 V nebo 0--10 V) je měřená hodnota kódována jako binární číslo. V případě bipolárního rozsahu je hodnota kódována pomocí dvojkového doplňku.
489 \end{itemize}
490
491 \subsection{D/A převodníky}
492 Karta MF614 obsahuje 4 D/A převodníky. Ty mají pevně nastavený výstupní rozsah -10--10 V a nevyžadují žádnou konfiguraci.
493
494 Nastavení výstupu D/A převodníků může probíhat následujícím způsobem:
495 \begin{itemize}
496 \item Do registru DA$x$LO a DA$x$HI (kde $x$ může nabývat hodnot 0, 1, 2, 3 a určuje, ke kterému D/A převodníku registr patří) se zapíše hodnota k převodu. 12bitová hodnota je do 8bitových registrů rozdělena takovým způsobem, že 8 LSB je zapsáno do DA$x$LO a zbývající čtyři bity jsou zapsány do DA$x$HI na 4 nejnižší bity, nepoužité 4 MSB registru DA$x$HI jsou vyplněny nulami.
497
498 Hodnota je zapsána v aditivním kódu (tab. \ref{tab_mf614_dac}).
499
500 \item Čtením registru DALE se spustí převod všech D/A převodníků.
501 \end{itemize}
502
503 \begin{table}[h!]
504         \begin{center}
505         \begin{tabular}{|c|c|}
506         \hline \textbf{Digitální hodnota} & \textbf{Analogová hodnota} \\ 
507         \hline 0xFFF & 9.9951 V \\ 
508         \hline 0x800 & 0.0000 V \\ 
509         \hline 0x7FF & -0.0049 V \\ 
510         \hline 0x000 & -10.0000 V \\ 
511         \hline 
512         \end{tabular} 
513         \caption{Kódování vstupních hodnot D/A převodníku}
514         \label{tab_mf614_dac}
515         \end{center}
516 \end{table}
517
518 \ibox{
519 \textbf{MSB} (Most Significant Bit) je označení pro bit s nejvyšší hodnotou v binárním vyjádření čísla. V obvyklém dvojkovém zápisu jde o bit nejvíce vlevo.
520 %\\~\\
521 \\
522 \textbf{LSB} (Least Significant Bit) je bit s nejnižší hodnotou. Jde o bit nejvíce vpravo.
523
524 \begin{center}
525 \texttt{1 0 1 0 1 0 1 0}\\
526 \texttt{MSB\hspace{2.6cm}LSB}
527 \end{center}}
528
529 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
530 \chapter{Implementace ovladačů}
531 \section{Operační systém GNU/Linux}
532 Jako cílový operační systém, na kterém bude vysvětlena implementace základních ovla\-da\-čů, byl zvolen GNU/Linux\footnote{Operační systém sestávající z GNU nástrojů a jádra Linux je označován jako GNU/Linux.}. Hlavním důvodem je svobodné šíření zdrojových kódů, velké množství kvalitní dokumentace, rozšířenost a vysoká kvalita. \textit{Distribucí} použitou při vývoji je Debian GNU/Linux (verze jádra Linux 2.6.35) -- popsané postupy by však měly fungovat i pro jiné distribuce.
533
534 \subsection{Práce s PCI zařízeními z uživatelského prostoru}
535 Pro výpis všech zařízení připojených pomocí sběrnice PCI k počítači slouží program \texttt{lspci}.
536 Po jeho spuštění bez udání parametrů bude vypsán základní seznam PCI zařízení. 
537
538 Mezi důležité parametry patří:
539 \begin{description}
540 \item[\texttt{-t}] Zobrazí diagram znázorňující jednotlivé PCI sběrnice a mosty.
541 \item[\texttt{-v}, \texttt{-vv}, \texttt{-vvv}]
542  Umožňuje vypisování podrobných informací o zařízeních. (Postupně od \textit{střední podrobnosti} k \textit{vysoké podrobnosti}).
543 \item[\texttt{-nn}] Zobrazí Vendor ID a Device ID v číselné a zároveň i textové podobě
544 \item[\texttt{-d [<vendor>]:[<device>]}] Zobrazí informace pouze o zařízeních odpovídajících Vendor ID, případně i Device ID
545 \end{description}
546
547 Příklad, jak takový výpis může vypadat:
548 \begin{verbatim}
549 $ lspci -nn -d 186c:0624 -vvv
550 01:0b.0 Signal processing controller [1180]: Humusoft, s.r.o. MF624 
551              Multifunction I/O Card [186c:0624]
552         Subsystem: Humusoft, s.r.o. MF624 Multifunction I/O Card [186c:0624]
553         Control: I/O+ Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- 
554              Stepping- SERR- FastB2B- DisINTx-
555         Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- 
556              <TAbort- <MAbort- >SERR- <PERR- INTx-
557         Interrupt: pin A routed to IRQ 22
558         Region 0: Memory at d2dffc00 (32-bit, non-prefetchable) [size=128]
559         Region 1: I/O ports at b800 [size=128]
560         Region 2: Memory at d2dff800 (32-bit, non-prefetchable) [size=128]
561         Region 4: Memory at d2dff400 (32-bit, non-prefetchable) [size=128]
562         Kernel driver in use: mf624
563 \end{verbatim}
564
565
566 Jinou možností, jak zjistit informace o PCI zařízení, je nahlédnutí do souborového systému \textit{sysfs}, kde jsou pro jednotlivá zařízení (nejen na PCI sběrnici) soubory\footnote{Tyto soubory ve skutečnosti nejsou uloženy nikde na disku, ale jsou dynamicky vytvářeny operačním systémem.}, které obsahují informace o zařízeních.
567
568 \ibox{Fyzická adresa PCI zařízení je tvořena adresou \textit{sběrnice}, adresou \textit{zařízení} a adresou \textit{logického zařízení}. PCI specifikace umožňuje, aby jeden systém obsahoval až 256 sběrnic. Každá sběrnice může obsahovat až 32 zařízení. Jedno fyzické zařízení může obsahovat až 8 logických.}
569
570 Informace o PCI zařízeních se nacházejí ve složce \texttt{/sys/bus/pci/devices/} -- jednotlivá zařízení jsou reprezentována podsložkou, jejíž název je tvořen fyzickou adresou PCI zařízení. Mezi nejdůležitější soubory, které tato podsložka obsahuje patří:
571
572 \begin{description}
573 \item[\texttt{vendor}] -- Obsahuje Vendor ID zařízení.
574 \item[\texttt{device}] -- Obsahuje Device ID zařízení.
575 \item[\texttt{class}] -- Obsahuje 24bitový identifikátor třídy zařízení.
576 \item[\texttt{subsystem\_vendor}] -- Obsahuje Subsystem Vendor ID.
577 \item[\texttt{subsystem\_device}] -- Obsahuje Subsystem ID.
578 \item[\texttt{resource}] -- Soubor obsahuje popis jednotlivých regionů využívaných zařízením (také ozna\-čo\-váno jako \textit{obsah} BAR registrů).
579 \end{description}
580
581 Struktura souboru \texttt{resource} může vypadat následovně:
582 \begin{verbatim}
583   0x00000000d2dffc00 0x00000000d2dffc7f 0x0000000000020200
584   0x000000000000b800 0x000000000000b87f 0x0000000000020101
585   0x00000000d2dff800 0x00000000d2dff87f 0x0000000000020200
586   0x0000000000000000 0x0000000000000000 0x0000000000000000
587   0x00000000d2dff400 0x00000000d2dff47f 0x0000000000020200
588   0x0000000000000000 0x0000000000000000 0x0000000000000000
589 \end{verbatim}
590
591 První sloupec označuje adresu začátku regionu, druhý jeho konec. Třetí sloupec obsahuje příznaky daného regionu. Díky nim je možné zjistit, zda se např. jedná o paměťový nebo I/O region. Tyto příznaky jsou popsány v souboru \texttt{include/linux/ioport.h} (ve zdrojových souborech jádra Linux). 
592
593
594
595
596 \subsection{Základní jaderný modul}\label{kern_mod}
597 Jádro operačního systému GNU/Linux je monolitické -- to znamená, že po zkompilování a slinkování je tvořeno jedním kusem kódu. Tento druh jádra je léty prověřen a mezi výhody patří hlavně jeho snadná implementace a stabilita. Aby běžící jádro nemuselo obsahovat veškeré dostupné ovladače zařízení (nebo aby v případě potřeby přidat do jádra ovladač pro nový hardware nebylo nutné celé jádro znovu kompilovat), existuje mechanismus načítání jaderných modulů za běhu, tzv. LKM -- \textit{Loadable Kernel Module}. V praxi to vypadá tak, že jsou v~běžícím jádře zakompilovány pouze nejnutnější ovladače, všechny ostatní si může systém nebo uživatel za běhu do jádra načíst -- v případě, že již nejsou potřeba, je možné je z jádra uvolnit.
598
599 Jak se takový jaderný modul může vypadat, je nejlepší si ukázat na příkladu:
600 \begin{verbatim}
601   1 |  #include <linux/init.h>
602   2 |  #include <linux/module.h>
603   3 | 
604   4 |  static int hello_init(void)
605   5 |  {
606   6 |      printk("Hello, world!\n");
607   7 |      return 0;
608   8 |  }
609   9 | 
610  10 |  static void hello_exit(void)
611  11 |  {
612  12 |      printk("Goodbye, cruel world!\n");
613  13 |  }
614  14 | 
615  15 |  module_init(hello_init);
616  16 |  module_exit(hello_exit);
617  17 |  
618  18 |  MODULE_LICENSE("Dual BSD/GPL");
619 \end{verbatim}
620
621 Z příkladu je patrné, že je modul napsán v programovacím jazyce C. To platí pro většinu jaderných modulů (stejně jako zdrojových kódů jádra samotného). Ve skutečnosti se jedná o mírně modifikovaný standard ANSI C90.
622
623 Z čeho se modul skládá:
624 \begin{description}
625 \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.
626 \item[Na řádcích 4--8] je funkce, která bude spuštěna ihned po zavedení modulu do jádra. Ta obsahuje pouze volání funkce \texttt{printk()}.
627
628 Pro jednoduchost je možné s funkcí \texttt{printk()} pracovat jako s, jistě známou, funkcí \texttt{printf()} dostupnou v uživatelském prostoru -- na rozdí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}.\\O to, že se tato funkce vykoná ihned po zavedení modulu do jádra, se postará příkaz na $\rightarrow$
629 \item[řádku 15] -- ten obsahuje makro \texttt{module\_init()}, kterému je sděleno právě to, která funkce se má po načtení spustit.
630 \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 tomto případě je to funkce na $\rightarrow$
631 \item[řádcích 10--13.] Tato funkce nemá na starost pouze výpis krátkého textu do logu jádra.
632
633 \item[Na řádku 18] je použito makro udávající licenci definující práva a povinnosti pro šíření/ používání zdrojových kódů daného modulu. Uvedení licence je důležité z toho důvodu, že jaderné moduly nevyužívající některou z opensource licencí nemají dostupná všechna jaderná volání (to platí i pro případ, že není uvedena žádná licence).
634 \end{description}
635
636 \subsubsection{Kompilace modulu}
637 Poté co je vytvořen zdrojový kód modulu, je třeba jej přeložit\footnote{Před samotným překladem modulu je potřeba mít k dispozici zdrojové kódy jádra. Ty je možné stáhnout z \url{http://kernel.org/} nebo v distribuci Debian nainstalovat pomocí příkazu \texttt{apt-get install linux-source}.}. K tomu poslouží následující \texttt{Makefile}:
638 \begin{verbatim}
639   1 |  KERNEL_VER=`uname -r`
640   2 |  obj-m += hello.o
641   3 |
642   4 |  all:
643   5 |      make -C /lib/modules/$(KERNEL_VER)/build M=$(PWD) modules
644   6 |  clean:
645   7 |      make -C /lib/modules/$(KERNEL_VER)/build M=$(PWD) clean
646 \end{verbatim}
647
648 Linux využívá při kompilaci systému \texttt{KBUILD}. Ten je tvořen větším množstvím samostat\-ných Makefile souborů a~jeho smyslem je umožnit uživateli snadnou konfiguraci před kompilací -- určující, které části se do jádra zakompilují a které nikoliv. Výše uvedený (základní) Makefile soubor je tvořen následovně:
649
650 \begin{description}
651 \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í).
652 \item[Druhý řádek] říká, že modul bude vytvářen ze zdrojového souboru \texttt{hello.c} (tj. modul popisovaný v kapitole \ref{kern_mod}).
653 \item[Na pátém řádku] (uvozeném tabelátorem) se volá (pomocí přepínače \texttt{-C}) Makefile ze sys\-tému \texttt{KBUILD}, který se nachází v adresáři spolu se zdrojovými kódy jádra. Parametr \texttt{M} určuje, které moduly mají být vytvořeny -- v tomto případě jsou to ty, které jsou uvedeny v Makefile, nacházejícím se v aktuálním adresáři (tj. \texttt{PWD}).
654 \end{description}
655
656 V případě, že se v adresáři, ve kterém se nachází zdrojový soubor modulu \texttt{hello.c} a~výše popsaný soubor \texttt{Makefile}, spustí příkaz \texttt{make}, měl by proběhnout samotný překlad:
657 \begin{verbatim}
658   $ make
659   make -C /lib/modules/`uname -r`/build M=/tmp/kernel_module_example modules
660   make[1]: Entering directory `/usr/src/linux-headers-2.6.35-28-generic'
661     CC [M]  /tmp/kernel_module_example/hello.o
662     Building modules, stage 2.
663     MODPOST 1 modules
664     CC      /tmp/hello.mod.o
665     LD [M]  /tmp/hello.ko
666   make[1]: Leaving directory `/usr/src/linux-headers-2.6.35-28-generic'
667 \end{verbatim}
668
669 V aktuálním adresáři by se měl nacházet kromě různých souborů, které vzniky při překladu, i potřebný \texttt{hello.ko} -- tj. zkompilovaný jaderný modul připravený na zavedení do jádra.
670
671 \begin{verbatim}
672   $ ls
673   hello.c  hello.ko  hello.mod.c  hello.mod.o  hello.o  
674   Makefile  modules.order  Module.symvers
675 \end{verbatim}
676
677 \subsubsection{Zavedení modulu}
678 Po úspěšném zkompilování jaderného modulu již pouze zbývá ho zavést do jádra. To se provede programem \texttt{insmod} -- ten musí být spouštěn se superuživatelským oprávněním:
679 \begin{verbatim}
680   $ sudo insmod ./hello.ko 
681 \end{verbatim}
682
683 V případě, že vše proběhlo správně, měl by být v logu jádra text vypisovaný modulem po jeho zavedení. To je možné ověřit:
684 \begin{verbatim}
685   $ dmesg | tail -1
686   [ 9245.757491] Hello, world!
687 \end{verbatim}
688 %A skutečně je posledním řádkem v logu text vypsaný úspěšně zavedeným modulem.
689
690 Pro plné otestování funkčnosti ukázkového modulu, je potřeba ho ještě z jádra uvolnit. K tomu slouží program \texttt{rmmod} (opět je potřeba spouštět se superuživatelskými privilegii).
691 \begin{verbatim}
692   $ sudo rmmod hello 
693
694   $ dmesg | tail -1
695   [ 9612.256929] Goodbye, cruel world!
696 \end{verbatim}
697 V logu se opět nachází text vypisovaný modulem při uvolňování z jádra.
698
699 \ibox{V případě, že má být do jádra zaveden modul, jehož funkčnost a stabilita není jistá, je vhodné si veškerou práci uložit (případně zálohovat) a před zavedením/uvolněním modulu do/z jádra spustit program \texttt{sync}, který uloží obsah diskových bufferů na disky.}
700
701 \subsubsection{Na co si dávat pozor}
702 Při psaní základního modulu pro jádro Linux nejsou patrné větší rozdíly oproti psaní programů pro uživatelský prostor. I~přesto, že tyto rozdíly nejsou vidět, stále tady jsou. Mezi ty nejdůležitější, kterých si má být programátor vědom, patří:
703
704 \begin{description}
705 \item[Žádná ochrana paměti]~\\Libovolný jaderný modul má přístup k veškeré paměti počítače. V případě, že se chybně pokusí zapsat do paměti, do které by zapisovat neměl, není zde žádný mechanismus, který by mu v tom zabránil.
706 \item[Uvolňování paměti]~\\Stejně jako pro programy psané v uživatelském prostoru platí, že nepotřebná dynamicky alokovaná paměť by měla být dealokována. V případě neuvolňování paměti programem v uživatelském prostoru je zde stále operační systém, který po skončení programu veškerou paměť uvolní. Nic takového však v jádře operačního systému nefunguje -- po uvolnění modulu z jádra není nic, co by se postaralo o alokovanou paměť.
707 \item[Přímý přístup k hardwaru]~\\Základní jaderný modul psaný například nezkušeným studentem má zcela stejné možno\-sti přístupu k hardware jako subsystémy jádra, které se starají o správnou funkci jednotlivých ovladačů. V lepším případě může špatný ovladač způsobit pád systému, v~horším např. zničení dat na disku nebo dokonce zničení hardware\footnote{Například velmi těžko opravitelné poškození firmware síťových karet Intel e1000e: \\ \url{http://www.abclinuxu.cz/clanky/jaderne-noviny/jaderne-noviny-22.-10.-2008\#pricina-chyby-poskozujici-e1000e}}.
708 \item[Globální proměnné]~\\Každý ovladač může být spuštěn ve více instancích, proto by v kódu neměly být globální proměnné. Proměnné, které je potřeba zpřístupnit z více míst ovladače se vloží do jedné struktury, která je poté přístupná skrze ukazatel na \textit{privátní data} ovladače. Struktura reprezentující daný ovladače většinou obsahuje ukazatel s názvem \texttt{private} nebo \texttt{priv}, který slouží k~tomuto účelu.
709
710 V případě ukončení funkce ovladače musí být tato paměť uvolněna.
711 \end{description}
712
713 \subsubsection{Příkaz GOTO}
714 Obecně je doporučováno příkaz \texttt{goto} nepoužívat. Najdou se ale případy, kdy jeho použití usnadní práci a i přesto neznepřehlední kód. V jádře Linux se tento příkaz používá při postupném uvolňování zdrojů zařízení.
715
716 Příklad pro lepší názornost:
717 \begin{verbatim}
718   1 |  int mf614_attach(...)
719   2 |  {
720   3 |      if(pci_enable_device(devpriv->pci_dev))
721   4 |          goto out_exit;
722   5 |  
723   6 |      if(pci_request_regions(devpriv->pci_dev, "mf614"))
724   7 |          goto out_disable;
725   8 |  
726   9 |      if (!pci_iomap(devpriv->pci_dev, 0, 0))
727  10 |          goto out_release;
728  11 |   
729  12 |  out_release:
730  13 |      pci_release_regions(devpriv->pci_dev);
731  14 |  out_disable:
732  15 |      pci_disable_device(devpriv->pci_dev);
733  16 |  out_exit:
734  17 |      return -ENODEV;
735  18 |  }
736 \end{verbatim}
737
738 Na řádcích 3, 6 a 9 jsou volány funkce, které mají za následek alokaci zdrojů zařízení. Po skončení funkce ovladače je potřeba zavolat jiné funkce, které tyto zdroje uvolní.
739
740 V případě, že by volání na řádku 6 skončilo neúspěchem, musela by být zavolána funkce \texttt{pci\_disable\_device()}, která deaktivuje zařízení (aktivované příkazem na řádku 3). V pří\-padě, že by poslední volání proběhlo neúspěšně, musela by být zavolána kromě funkce \texttt{pci\_disable\_device()} ještě funkce \texttt{pci\_release\_regions()}. V případě, že by tyto funkce byly volány z více míst, došlo by k duplikaci kódu -- ta vede k nepřehlednosti a může způsobovat chyby (v případě, že se omylem místo všech výskytů dealokační sekvence opraví pouze některé).
741
742 Za pomoci volání \texttt{goto} je výše popsaný problém elegantně vyřešen.
743
744 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
745 \section{Základní funkce v prostředí jádra Linux}
746 V jádře Linux je kromě funkcí specifických pro práci se zařízením určitého typu, také sada obecných funkcí používaných napříč všemi ovladači. Mezi ně patří například funkce pro vypisování ladících zpráv, funkce pro alokaci a uvolňování paměti.
747
748 \subsection{Funkce \texttt{printk()} pro vypisování ladících zpráv}
749 \ibox{\texttt{int printk(const char *s, ...)};}
750
751 V kapitole \ref{kern_mod} již byla zmíněna funkce \texttt{printk()} v základní verzi, přirovnaná k funkci \texttt{printf()} z uživatelského prostoru. Kromě \textit{obyčejného} vypisování textu do logu jádra podporuje tato funkce navíc \textit{nastavení úrovně důležitosti} zprávy a speciální \textit{formátovací řetězce}.
752
753 Nastavení úrovně důležitosti zprávy se provede vložením \textit{nastavovacího} makra \textbf{před} samotný řetězec obklopený uvozovkami. Možné druhy zpráv jsou (od nejkritičtější po nejméně důležitou):
754 \begin{description}
755 \item[\texttt{KERN\_EMERG}]~\\Zpráva nejvyšší důležitosti. Většinou předchází neodvratnému pádu jádra.
756 \item[\texttt{KERN\_ERR}]~\\Informace o vzniklé chybě (např. při informování o špatné funkci hardware).
757 \item[\texttt{KERN\_WARNING}]~\\Upozornění o nezávažné chybě.
758 \item[\texttt{KERN\_INFO}]~\\Informační zpráva (např. od ovladače zařízení o úspěšném spuštění).
759 \item[\texttt{KERN\_DEBUG}]~\\Obyčejná ladící zpráva.
760 \end{description}
761
762 \vspace{5mm}
763
764 Formátovací řetězce fungují podobně jako u funkce \texttt{printf()}. Kromě známých, \texttt{\%s}, \texttt{\%u}, \texttt{\%d} a \texttt{\%x} je zde navíc \texttt{\%p}, který slouží k výpisu hodnoty ukazatele.
765
766 Možné způsoby použití jsou:
767 \begin{description}
768 \item[\texttt{\%pF}] Pro ukazatel na funkci vypíše název dané funkce.
769 \item[\texttt{\%pf}] Pro ukazatel na funkci vypíše název dané funkce včetně offsetu.
770 \item[\texttt{\%pR}] Pro ukazatel na strukturu vypíše adresy paměti příslušející dané struktuře, včetně příznaků.
771 \item[\texttt{\%pr}] Pro ukazatel na strukturu vypíše adresy paměti příslušející dané struktuře, bez příznaků.
772 \end{description}
773
774 Příklad nastavení typu zprávy a použití formátovacího řetězce:
775 \begin{verbatim}
776   printk(KERN_DEBUG "Hodnota ukazatele ptr je %p\n", ptr);
777 \end{verbatim}
778
779
780 \subsection{Funkce \texttt{kzalloc()} pro alokaci paměti}
781 Problematika alokace paměti v prostředí jádra Linux je velice rozsáhlá. Pomocí speciálních funkcí je možné alokovat fyzickou paměť, velké bloky virtuální paměti nebo celé paměťové stránky.
782
783 \ibox{\texttt{void *kzalloc(size\_t size, gfp\_t flags);}}
784 Základní funkce pro alokaci malé paměťové oblasti (např. pro strukturu obsahující privátní data ovladače) je \texttt{kzalloc()}. Prvním parametrem je velikost alokované paměti (maximálně však 128 KB), druhým je příznak určující o jaký druh alokace se jedná. Nejuniverzálnější možností je \texttt{GFP\_KERNEL}.
785
786 Nově alokovaná paměť je vždy vynulována.
787
788 Příklad alokace a uvolnění paměti (včetně ošetření chybových stavů):
789 \begin{verbatim}
790   1 |  struct uio_info *info;
791   2 |  info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
792   3 |  if (!info) {
793   4 |      return -ENOMEM;
794   5 |  }
795   6 |  /* práce s pamětí */
796   7 |           
797   8 |  kfree(info);
798 \end{verbatim}
799
800
801 \subsection{Funkce \texttt{kfree()} pro uvolňování alokované paměti}
802 \ibox{\texttt{void kfree(void *obj);}}
803
804 Když již alokovaná paměť není potřeba, je nutné ji voláním \texttt{kfree()} uvolnit. 
805
806
807 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
808 \vspace{1cm}
809 \section{Ovladače PCI zařízení}\label{pci_driv}
810 \ibox{Jako nejlepší reference jednotlivých funkcí slouží zdrojové kódy jádra. Pro snadné procházení je vhodné využít nástroje vytvářející křížové odkazy (mezi voláním a~defi\-nicí funkce, použitím a deklarací proměnné apod.). 
811
812 \vspace{1mm}
813 Nejpohodlnějším způsobem je použití online nástroje \textit{The Linux Cross Reference} -- \url{http://lxr.linux.no/linux/}.
814
815 \vspace{1mm}
816 Jinou možností je přímé čtení a procházení zdrojových kódů jádra. Pro vytváření indexu křížových odkazů poslouží programy \texttt{ctags} a \texttt{cscope}. Samotné procházení je poté možné například pomocí programů \texttt{vim} a \texttt{Kscope}.}
817
818
819 Ovladače PCI zařízení jsou ve většině případů kompilovány jako jaderné moduly, dynamicky načítané za běhu jádra. Takový modul je možné buď načíst ručně, pomocí příkazu \texttt{insmod} (se zadanou absolutní cestou) nebo, nachází-li se v adresáři \texttt{/lib/modules/\$(uname -r)/} a je součástí seznamu \texttt{modules.dep}\footnote{Tento seznam je aktualizován pomocí příkazu \texttt{depmod}.} (v témže adresáři), je možné ho načíst pomocí příkazu \texttt{modprobe} (kde se jako parametr předá pouze název modulu bez koncovky \texttt{.ko}) -- ten také zajistí i načtení modulů potřebných pro splnění případných závislostí načítaného modulu. Druhá varianta se týká všech ovladačů standardně zkompilovaných s jádrem.
820
821 V případě, že se v systému objeví nové PCI zařízení, je jádrem informován subsystém v~uživatelském prostoru, který má na starosti správu \textit{hotplug} zařízení (např. \textit{udev}). Tento subsystém poté na základě získaných informací, jako je Vendor ID a Device ID, rozhodne, který ovladač má být pro dané zařízení načten. Seznam, dle kterého je ovladač vybírán, je v souboru \texttt{/lib/modules/\$(uname -r)/modules.pcimap}.
822
823 Proto, aby mohl být ovladač součástí výše popsaného seznamu, musí ve struktuře \texttt{struct pci\_device\_id} obsahovat informaci o tom, pro které zařízení je určen.
824
825
826
827 \subsection{Struktura \texttt{struct pci\_device\_id}}\label{pci_dev_id}
828 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á hodnotě stejnojmenných registrů v konfiguračním prostoru daného 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 vždy zakončeno prázdným prvkem. Různé způsoby inicializace mohou vypadat následovně:
829
830 \begin{verbatim}
831   1 |  #define PCI_VENDOR_ID_HUMUSOFT          0x186c
832   2 |  #define PCI_DEVICE_ID_MF624             0x0624
833   3 |  #define PCI_DEVICE_ID_MF614             0x0614
834   4 |  #define PCI_SUBVENDOR_ID_HUMUSOFT       0x186c
835   5 |  #define PCI_SUBDEVICE_MF624             0x0624
836   6 |  
837   7 |  static struct pci_device_id mf624_pci_id[] = {
838   8 |      {
839   9 |          .vendor = PCI_VENDOR_ID_HUMUSOFT,
840  10 |          .device = PCI_DEVICE_ID_MF624,
841  11 |          .subvendor = PCI_SUBVENDOR_ID_HUMUSOFT,
842  12 |          .subdevice = PCI_SUBDEVICE_MF624,
843  13 |      },
844  14 |
845  15 |      { PCI_VENDOR_ID_HUMUSOFT, PCI_DEVICE_ID_MF614, 
846  16 |          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
847  17 |
848  18 |      { 0, } /* seznam je vždy zakončen prázdným prvkem */
849  19 |  };
850 \end{verbatim}
851
852 V případě, že je u zařízení rozhodující Vendor ID, ale na Subvendor ID nezáleží, je možné použít makro \texttt{PCI\_ANY\_ID} (to platí 
853 i pro Subdevice ID).
854
855 \ibox{\texttt{MODULE\_DEVICE\_TABLE(type, struct pci\_device\_id* name);}}
856
857 Tato struktura se -- pro nástroje v uživatelském prostoru vytvářející seznamy ovladačů -- exportuje pomocí makra \texttt{MODULE\_DEVICE\_TABLE(pci, mf624\_pci\_id)}, kde první parametr určuje typ zařízení a druhý je ukazatel na seznam typu \texttt{struct pci\_device\_id}.
858
859 \subsection{Struktura \texttt{struct pci\_driver}}\label{pci_reg}
860 Pro to, aby se mohl ovladač PCI zařízení stát součástí jaderného PCI subsystému, je potřeba ho do něj zaregistrovat. To se provede voláním funkce \texttt{pci\_register\_driver()}, které se jako parametr předá ukazatel na strukturu \texttt{struct pci\_driver}. 
861
862 Tato struktura obsahuje základní informace o ovladači. Mezi hlavní položky patří:
863 \begin{description}
864 \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.
865 \item[\texttt{const struct pci\_device\_id *id\_table}]~\\Pole struktur popisujících, pro která zařízení je ovladač vytvořen (viz kap. \ref{pci_dev_id}).
866 \item[\texttt{int (*probe) (struct pci\_dev *dev, const struct pci\_device\_id *id)}]~\\Ukazatel na funkci, která je volána PCI subsystémem, v případě, že je přítomno zařízení, pro které je tento ovladač vytvořen.
867 \item[\texttt{void (*remove) (struct pci\_dev *dev)}]~\\Ukazatel na funkci, která je volána poté, co je tento ovladač odstraňován ze seznamu ovladačů aktuálně používaných PCI subsystémem nebo v případě, že dochází k uvolnění modulu.
868 \end{description}
869
870 Příklad, jak může být struktura \texttt{pci\_driver} inicializována a následně zaregistrována:
871 \begin{verbatim}
872   1 |  static struct pci_driver mf624_pci_driver = {
873   2 |      .name = "mf624",
874   3 |      .id_table = mf624_pci_id,
875   4 |      .probe = mf624_pci_probe, 
876   5 |      .remove = mf624_pci_remove,
877   6 |  };
878   7 |  pci_register_driver(&mf624_pci_driver);
879 \end{verbatim}
880
881
882 \subsection{Funkce \texttt{probe()}}\label{pci_init}
883 \ibox{\texttt{int (*probe) (struct pci\_dev *dev, const struct pci\_device\_id *id);}}
884
885 Funkce \texttt{probe()} náležící danému ovladači zařízení je volána poté, co jaderný 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í.
886
887 Prvním parametrem funkce předává PCI subsystém ukazatel na strukturu \texttt{struct pci\_dev}, která repre\-zentuje fyzické zařízení. V druhém parametru je předán ukazatel na strukturu, na základě které byl zvolen daný ovladač (viz kap. \ref{pci_dev_id}).
888
889 \ibox{\texttt{pci\_enable\_device(struct pci\_dev *dev);}}
890
891 V rámci inicializace ovladače 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é je již možné začít přistupovat ke zdrojům zařízení.
892
893 \subsection{Přístup ke zdrojům karty}
894 Jak bylo popsáno v kapitole \ref{pci_conf}, 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 regionů si musí ovladač zařízení zjistit jejich adresu a vyžádat si u operačního systému \textit{výlučný přístup}. 
895
896 \ibox{\texttt{int pci\_request\_regions(struct pci\_dev *pdev, const char *res\_name);}}
897
898 Nejprve je potřeba operační systém požádat o výlučný přístup ke zdrojům zařízení. To se provede voláním funkce \texttt{pci\_request\_regions()}. Je-li návratová hodnota zavolané funkce negativní, není ovladači umožněn přístup (jiný ovladač přistupuje ke stejné kartě nebo po jeho odstranění nedošlo k uvolnění zdrojů karty). V takovém případě by ovladač měl korektním způsobem ukončit svoji funkci a nesnažit se k zařízení přistupovat.
899
900 \ibox{\texttt{unsigned long pci\_resource\_start(struct pci\_dev *dev, int bar);}}
901
902 V případě, že volání \texttt{pci\_request\_regions()} proběhlo úspěšně, je již možné získat přístup přímo k jednotlivým regionům karty. Fyzickou adresu jednotlivých regionů lze zjistit voláním funkce \texttt{pci\_resource\_start()}, kde se jako druhý parametr uvede číslo BAR registru určují\-cího region (tj. 0--5). 
903 %Volání této funkce má pouze informativní charakter
904
905 \ibox{\texttt{unsigned long pci\_resource\_len(struct pci\_dev *dev, int bar);}}
906
907 V případě, že je potřeba zjistit velikost daného paměťového nebo I/O regionu, slouží k~tomu funkce \texttt{pci\_resource\_len()}.
908
909 \ibox{\texttt{void \_\_iomem *pci\_ioremap\_bar(struct pci\_dev *pdev, int bar);}}
910
911 S ukazatelem, který vrátí funkce \texttt{pci\_request\_regions()} však není možné přímo pracovat -- je to totiž \textbf{fyzická adresa} daného regionu, ke které neumí procesor přímo přistupovat. Aby tato fyzická adresa byla přemapována na adresu \textbf{virtuální}, je potřeba zavolat funkci \texttt{pci\_ioremap\_bar()}.
912
913 K ukazateli, který vrátí volání \texttt{pci\_ioremap\_bar()} je již možné pomocí speciálních funkcí (popsány v kap. \ref{iofce}) přistupovat.
914
915 \subsection{Funkce \texttt{remove()}}
916
917 \ibox{\texttt{void remove(struct pci\_dev *dev);}}
918
919 Funkce je volána, když PCI subsystém ze svého seznamu odstraňuje strukturu \texttt{struct pci\_dev} reprezentující dané zařízení, nebo v případě, že dochází k uvolnění modulu.
920
921 Tato funkce by se měla postarat o úklid všech naalokovaných prostředků. Měla by obsahovat volání:
922 \begin{description}
923 \item[\texttt{iounmap()}]~\\Uvolnění virtuální paměti namapované voláním \texttt{pci\_ioremap\_bar()}.
924 \item[\texttt{pci\_release\_regions()}]~\\Uvolnění zdrojů karty, které byly zarezervovány voláním \texttt{pci\_request\_regions()}.
925 \item[\texttt{pci\_disable\_device()}]~\\Opak k volání \texttt{pci\_enable\_device()}.
926 \end{description}
927
928 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
929 \section{Přístup k paměti zařízení}\label{iofce}
930 Poté co se ovladači podařilo získat přístup ke zdrojům zařízení, je nutné (důvody jsou popsány dále v textu) využít speciálních volání pro zápis/čtení do/z těchto zdrojů.
931
932 \subsection{Vstupně-výstupní adresní prostor}
933 Stejně jako program v jazyku symbolických instrukcí využívá pro přístup k vstupně-výstupnímu adresnímu prostoru (tj. I/O portům) zvláštní instrukce, je nutné využít speciální funkce v programech psaných ve \textit{vyšších} programovacích jazycích. V případě čtení jsou v~jádře k dispozici tři volání:
934
935 \ibox{\texttt{unsigned inb(unsigned port);}}
936
937 \ibox{\texttt{unsigned inw(unsigned port);}}
938
939 \ibox{\texttt{unsigned inl(unsigned port);}}
940
941 Třetí písmeno značí o \textit{kolika-bitové} čtení se jedná: b = 8 b, w = 16 b, l = 32 b.
942
943 Pro zápis je možné využít volání:
944 \ibox{\texttt{void outb(unsigned char byte, unsigned port);}}
945
946 \ibox{\texttt{void outw(unsigned char byte, unsigned port);}}
947
948 \ibox{\texttt{void outl(unsigned char byte, unsigned port);}}
949
950
951 Třetí písmeno, stejně jako u funkcí pro čtení, značí o kolika-bitový přístup se jedná.
952
953 Funkce se stejným \textit{prototypem} jsou k dispozici i v uživatelském prostoru (potřebný hla\-vičkový soubor je \texttt{<sys/io.h>}).
954
955 \subsection{Paměťový adresní prostor}
956 I přesto, že se k přístupu k paměti zařízení mapované do paměťového adresního prostoru používá virtuální adresa (stejně jako v případě přístupu do operační paměti), není možné k paměti zařízení přistupovat přímo \textit{přes ukazatel}. Důvodem je to, že buď překladač (při kompilaci) nebo procesor (za běhu) zoptimalizují\footnote{Tyto optimalizace, v~případě přístupu k operační paměti, urychlují vykonávání programu, aniž by negativně ovlivnily jeho funkci. V případě zápisu/čtení do/z registrů, u kterých mohou tyto operace vyvolávat tzv. \textit{side effects}, již může dojít k nesprávné funkci programu.
957
958 Příklad optimalizace: V programu se do jedné paměťové buňky ihned po sobě zapíší dvě různé hodnoty, poté se výsledná hodnota přečte -- optimalizace možná u klasického programu je taková, že se ve skutečnosti provede pouze druhý zápis, protože ten první nemá žádný efekt (hodnota je ihned přepsána druhým zápisem). V~případě přístupu do registru zařízení může zápis například spouštět převod A/D převodníků -- po optimalizaci se však provede pouze jednou, nikoliv dvakrát.} sekvenci zápisů/čtení do/z paměti zařízení takovým způsobem, že se výsledek může lišit od toho, jak to bylo v programu zamýšleno.
959
960 Těmto optimalizacím lze nejsnáze zabránit použitím volání pro čtení:
961
962 \ibox{\texttt{unsigned int ioread8(void *addr);}}
963
964 \ibox{\texttt{unsigned int ioread16(void *addr);}}
965
966 \ibox{\texttt{unsigned int ioread32(void *addr);}}
967
968 a pro zápis:
969
970 \ibox{\texttt{void iowrite8(u8 value, void *addr);}}
971
972 \ibox{\texttt{void iowrite16(u16 value, void *addr);}}
973
974 \ibox{\texttt{void iowrite32(u32 value, void *addr);}}
975
976 Číslo na konci funkce označuje o kolika-bitový přístup se jedná.
977
978 V případě, že se na paměť ve vstupně-výstupním adresním prostoru zavolá funkce 
979 \ibox{\texttt{void *ioport\_map(unsigned long port, unsigned int count);}} 
980 nebo v případě PCI zařízení funkce
981 \ibox{\texttt{void *pci\_iomap(struct pci\_dev *dev, int bar, unsigned long maxlen);}}
982
983 se rozsah I/O portů chová jakoby byl součástí paměťového adresního prostoru. Pro přístup je poté nutné používat volání popsaná v této kapitole, která zakryjí rozdílný charakter přístupu do vstupně-výstupního adresního prostoru.
984
985 Na procesorových architekturách využívajících reorganizaci pořadí přístupu k operandům na úrovni CPU je nutné definovat i vlastní sadu operací pro tvorbu paměťových bariér. Archi\-tektury IA-32 se tyto potíže netýkají, při portaci na architektury jiné bude třeba tyto funkce podle požadavků příslušné architektury doplnit. Bohužel přenositelné hlavičkové soubory nejsou ve standardních GNU/Linuxových distribucích založených na GNU LibC pro uživatelský prostor (na rozdíl od jádra) k dispozici.
986
987 Příklad jak takové funkce (používané na architektuře IA-32) mohou vypadat:
988
989 \begin{verbatim}
990   1 |  static inline void mf624_write32(uint32_t val, uint32_t *ptr)
991   2 |  {
992   3 |      *(volatile uint32_t*) ptr = val;
993   4 |  }
994   5 |
995   6 |  static inline uint32_t mf624_read32(uint32_t *ptr)
996   7 |  {
997   8 |      return (volatile uint32_t) *ptr;
998   9 |  }
999 \end{verbatim}
1000
1001 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1002 \newpage
1003 \section{UIO ovladač}
1004 V~případě, že je vytvářen ovladač pro linuxové jádro, mělo by být rozhodnuto, kterého subsystému se stane součástí -- např. zda jde o jednoduché znakové zařízení, síťovou kartu nebo USB zařízení. Tato volba určí, kterou sadu pomocných funkcí bude moci ovladač používat a jakým způsobem bude zařízení zpřístupněno do uživatelského prostoru.
1005
1006 V~případě, že zařízení nelze snadno zařadit do žádné kategorie (jedná-li se například o~neobvyklou průmyslovou PCI kartu), je možné vytvořit tzv. UIO (\textit{Userspace I/O}) ovladač. Tento ovladač se skládá ze dvou částí: jednoduchého jaderného modulu a aplikace v uživatel\-ském prostoru (viz diagram na obrázku \ref{uio_diagram}).
1007
1008 \begin{figure}[h!]
1009         \begin{center}
1010         \includegraphics[width=150mm]{img/uio.pdf}
1011         \caption{Diagram znázorňující funkci UIO ovladače}
1012         \label{uio_diagram}
1013         \end{center}
1014 \end{figure}
1015
1016
1017 Mezi jeho hlavní výhody patří to, že v jádře je obsažena pouze malá obecná část, která zpřístupňuje zdroje zařízení do uživatelského prostoru. Druhou částí je aplikace v~uživatel\-ském prostoru, která přistupuje k jednotlivým zdrojům karty a tvoří hlavní logiku ovladače. Většina vývoje tedy probíhá v uživatelském prostoru, čímž klesá riziko narušení stability jádra.
1018
1019 \subsection{Jaderný modul}
1020 Jaderný modul UIO ovladače PCI zařízení by měl obsahovat:
1021 \begin{itemize}
1022 \item Funkci volanou PCI subsystémem při registraci ovladače
1023         \begin{itemize}
1024         \item Volání funkcí pro namapování regionů zařízení
1025         \item Inicializaci struktury \texttt{struct uio\_info} a registraci do UIO subsystému
1026         \end{itemize}
1027 \item Funkce pro \textit{úklid} a uvolnění regionů karty
1028 \end{itemize}
1029
1030 Většina z těchto úkonů již byla popsána v kapitole \ref{pci_driv} a jsou zcela standardní pro jaký\-koliv ovladač PCI zařízení. Co nebylo dosud popsáno je pouze úkon \textit{registrace do UIO subsystému}.
1031
1032 \ibox{\texttt{int uio\_register\_device(struct device *parent, struct uio\_info *info);}}
1033
1034 Registrace UIO ovladače PCI zařízení se provede zavoláním funkce \texttt{uio\_register\_device()}, které se jako první parametr předá ukazatel na strukturu obecného zařízení \texttt{dev} vnořenou do struktury \texttt{struct pci\_dev}. Důvod je ten, že ovladač typu UIO může být vytvořen i pro jiná zařízení než ta na sběrnici PCI.
1035 Druhý parametr předá ukazatel na strukturu \texttt{struct uio\_info}.
1036
1037 \subsubsection{Struktura \texttt{struct uio\_info}}
1038
1039 Jedná se o strukturu vyplněnou informacemi o zařízení, která je předána při registraci UIO subsystému.
1040 Mezi její hlavní položky patří:
1041 \begin{description}
1042 \item[\texttt{const char *name}]~\\Název ovladače. Většinou se shoduje s názvem modulu.
1043 \item[\texttt{const char *version}]~\\Verze ovladače v textové podobě.
1044 \item[\texttt{struct uio\_mem mem[MAX\_UIO\_MAPS]}]~\\Pole struktur obsahujících informace o regionech zařízení mapovaných do paměťo\-vého prostoru (bude vysvětleno dále).
1045 \item[\texttt{struct uio\_port port[MAX\_UIO\_PORT\_REGIONS]}]~\\Pole struktur obsahujících informace o regionech zařízení mapovaných do vstupně-výstupního prostoru (bude vysvětleno dále).
1046 \end{description}
1047
1048 \subsubsection{Struktura \texttt{struct uio\_mem} a \texttt{struct uio\_port}}\label{uio_mem_port}
1049 Tyto struktury obsahují informace o regionech zařízení. Které (a kolik) z těchto dvou struktur budou inicializovány záleží na tom, zda zařízení mapuje regiony do paměťového nebo vstupně-výstupního prostoru.
1050
1051 Struktura \texttt{struct uio\_mem} obsahuje položky:
1052 \begin{description}
1053 \item[\texttt{const char *name}]~\\Textový popis daného regionu (viditelný z uživatelského prostoru).
1054 \item[\texttt{unsigned long addr}]~\\Fyzická adresa regionu. V případě PCI zařízení získána voláním \texttt{pci\_resource\_start()}.
1055 \item[\texttt{unsigned long size}]~\\Délka regionu. V případě PCI zařízení nejsnáze získána voláním \texttt{pci\_resource\_len()}.
1056 \item[\texttt{int memtype}]~\\Typ paměti. Pro fyzickou paměť na zařízení se použije \texttt{UIO\_MEM\_PHYS}.
1057 \item[\texttt{void \_\_iomem *internal\_addr}]~\\Virtuální adresa. V případě PCI zařízení získána voláním \texttt{pci\_ioremap\_bar()}.
1058 \end{description}
1059
1060 Struktura \texttt{struct uio\_port} obsahuje položky:
1061 \begin{description}
1062 \item[\texttt{const char *name}]~\\Textový popis daného regionu (viditelný z uživatelského prostoru).
1063 \item[\texttt{unsigned long start}]~\\Fyzická adresa regionu. V případě PCI zařízení  získána voláním \texttt{pci\_resource\_start()}.
1064 \item[\texttt{unsigned long size}]~\\Délka regionu. V případě PCI zařízení nejsnáze získána voláním \texttt{pci\_resource\_len()}.
1065 \item[\texttt{int porttype}]~\\Typ portu (tj. vstupně-výstupní paměti). Pro porty na architektuře IA-32 se použije \texttt{UIO\_PORT\_X86}.
1066 \end{description}
1067
1068 ~\\
1069
1070 Příklad, jak taková jednoduchá inicializace struktury \texttt{struct uio\_info} včetně registrace může vypadat (bez ošetření chybových stavů):
1071 \begin{verbatim}
1072   1 |  /* struct pci_dev *dev */
1073   2 |  struct uio_info *info;
1074   3 |  info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
1075   4 |  
1076   5 |  info->name = "mf624";
1077   6 |  info->version = "0.0.1";
1078   7 |  
1079   8 |  info->mem[0].name = "PCI chipset, ...";
1080   9 |  info->mem[0].addr = pci_resource_start(dev, 0);
1081  10 |  info->mem[0].size = pci_resource_len(dev, 0);
1082  11 |  info->mem[0].memtype = UIO_MEM_PHYS;
1083  12 |  info->mem[0].internal_addr = pci_ioremap_bar(dev, 0);
1084  13 |  
1085  14 |  info->port[0].name = "Board programming registers";
1086  15 |  info->port[0].porttype = UIO_PORT_X86;
1087  16 |  info->port[0].start = pci_resource_start(dev, 1);
1088  17 |  info->port[0].size = pci_resource_len(dev, 1);
1089  18 |  
1090  19 |  uio_register_device(&dev->dev, info);
1091  20 |  pci_set_drvdata(dev, info);
1092 \end{verbatim}
1093 \vspace{1cm}
1094
1095 \ibox{\texttt{void pci\_set\_drvdata(struct pci\_dev *pdev, void *data);}}
1096
1097 Na posledním řádku je, dosud nepopsané, volání \texttt{pci\_set\_drvdata()}. To (v tomto pří\-pa\-dě) zajistí, že struktura \texttt{struct uio\_info} se stane součástí struktury reprezentující zařízení (\texttt{struct pci\_dev}) -- což umožní pozdější přístup ke struktuře \texttt{struct uio\_info} z funkcí jako je například \texttt{remove()}, která jako parametr získá ukazatel na strukturu \texttt{struct pci\_dev}.
1098
1099 \ibox{\texttt{static inline void *pci\_get\_drvdata(struct pci\_dev *pdev);}}
1100
1101 Funkce \texttt{pci\_get\_drvdata()} slouží k \textit{získání} dat uložených do struktury \texttt{struct pci\_dev} pomocí volání \texttt{pci\_set\_drvdata()}.
1102
1103 Příklad použití:
1104 \begin{verbatim}
1105   1 |  static void mf624_pci_remove(struct pci_dev *dev)
1106   2 |  {
1107   3 |      struct uio_info *info = pci_get_drvdata(dev);
1108   4 |      /* ... */
1109   5 |  }
1110 \end{verbatim}
1111
1112
1113 \subsection{Program v uživatelském prostoru}
1114 Poté, co je jaderná část UIO ovladače úspěšně zkompilována a zavedena do systému, ve kterém se nachází požadované zařízení, je rozhraní mezi tímto modulem a uživatelským prostorem tvořeno:
1115 \begin{itemize}
1116 \item souborem \texttt{/dev/uio0\footnote{Pro názornost je v textu uvedeno 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.}}.
1117 \item složkou \texttt{/sys/class/uio/uio0}, která obsahuje informace o regionech, které jsou zpří\-stup\-něny skrze UIO modul v jádře.
1118 \end{itemize}
1119
1120 \subsubsection{Obsah složky \texttt{/sys/class/uio/uio0}}
1121 Tato složka obsahuje soubory převážně pouze pro čtení. Obsahuje podsložku \texttt{maps}, ve které se nachází pro každý region 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).
1122
1123 V případě, že jsou zpřístupněny regiony zařízení, které jsou mapovány do vstupně-výstupního adresního prostoru, nacházejí se jednotlivé podsložky a soubory popisující regiony ve složce \texttt{portio}.
1124
1125 \subsubsection{Soubor \texttt{/dev/uio0}}
1126 Tento soubor tvoří rozhraní mezi jaderným subsystémem UIO a uživatelským prostorem. Skrze něj je přistupováno k regionům zařízení. K souboru se přistupuje pomocí funkce \texttt{mmap()}.
1127
1128 \ibox{\texttt{void *mmap(void *addr, size\_t length, int prot, int flags, int fd, off\_t offset);}}
1129
1130 Tato funkce slouží k \textit{namapování} souboru nebo zařízení do operační paměti. V případě, že je funkce zavolána na soubor, proběhne-li vše správně, návratová hodnota bude obsahovat ukazatel do paměti, kam je možné přistu\-povat k obsahu souboru pomocí ukazatelové aritmetiky -- stejně, jako by to byla paměť.
1131  
1132 Popis jednotlivých parametrů:\begin{description}
1133 \item[\texttt{addr}]~\\V případě, že není nulový, určí na jakou adresu ve virtuálním adresním prostoru apli\-kace by měla být paměť mapována. Není-li adresa určena, volnou oblast vybere pod\-půrná C knihovna (LibC).
1134
1135 \item[\texttt{length}]~\\ Udává velikost mapované paměti v násobcích velikosti paměťové stránky. 
1136 \item[\texttt{prot}]~\\ Obsahuje příznaky definující, zda bude mapovaná paměť pro čtení/zápis, apod.
1137 \item[\texttt{flags}]~\\ Pomocí příznaků určuje, zda se mají změny zapisovat pouze do \textit{lokální kopie} (příznak \texttt{MAP\_PRIVATE}) nebo zda mají být zapisovány do původního souboru/zařízení (příznak \texttt{MAP\_SHARED}).
1138 \item[\texttt{fd}]~\\ Obsahuje \textit{filedescriptor} na zařízení, které má být namapováno (v tomto případě file\-desc\-riptor vrácený voláním \texttt{open("/dev/uio0", ... );}).
1139 \item[\texttt{offset}]~\\ Určuje, zda se daný 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ů zpřístupněných jadernou částí ovladače má být namapován.
1140 \end{description}
1141
1142 \newpage
1143 Příklad, jak takové volání může vypadat (bez ošetření chybových stavů):
1144 \begin{verbatim}
1145   1 |  #define BAR2_offset       (1 * sysconf(_SC_PAGESIZE))
1146   2 |  
1147   3 |  void* mf624_BAR2 = NULL;
1148   4 |  int device_fd = open("/dev/uio0", O_RDWR);
1149   5 |  
1150   6 |  mf624_BAR2 = mmap(0, 1 * sysconf(_SC_PAGESIZE), 
1151   7 |                    PROT_READ | PROT_WRITE, MAP_SHARED, 
1152   8 |                    device_fd, BAR2_offset);
1153 \end{verbatim}
1154
1155 S adresou vrácenou voláním \texttt{mmap()} však není možné vždy ihned pracovat. Může se stát, že mapovaný region zařízení (reprezentovaný zařízením \texttt{/dev/uio0}, na které je \texttt{mmap()} volán) je menší než je velikost celé stránky, \texttt{mmap()} však vrací ukazatel zarovnaný na velikost stránky. Je tedy potřeba se v rámci této stránky posunout na tu část, která odpovídá požadovanému regionu.
1156
1157 Jak velký je potřeba udělat \textit{posun} pomůže zjistit soubor \texttt{/sys/class/uio/uio0/maps/ /map1/addr}\footnote{Pro názornost je uvedena konkrétní cesta -- jedná se tedy o \textit{druhý} paměťový region zařízení \textit{uio0}.} -- ten obsahuje fyzickou adresu požadovaného regionu. Z té je možné následují\-cím trikem získat ukazatel, se kterým je již možné pracovat (nejnižší bity totiž budou zachovány z fyzické adresy):
1158 \begin{verbatim}
1159   mf624_BAR2 += (BAR2_phys_addr & (sysconf(_SC_PAGESIZE) - 1));
1160     |                \-- Fyzická adresa
1161      \-- Ukazatel vrácený voláním mmap()                 
1162 \end{verbatim}
1163
1164 \subsubsection{Přístup k paměti zařízení}
1165 Jelikož se jedná o paměť zařízení, je potřeba i v uživatelském prostoru k této paměti přistupovat pomocí speciálních funkcí. Ty jsou popsány v kapitole \ref{iofce}.
1166
1167 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1168 \newpage
1169 \section{Comedi ovladač}
1170 Kromě popsaných výhod UIO ovladače jsou zde i nevýhody. Jednou z nich je pomalejší odezva než v případě plnohodnotného jaderného ovladače. Další nevýhodou je neexistence knihovny v uživatelském prostoru, která by poskytovala jednotné API pro přístup k zařízení (v případě UIO ovladače je potřeba vytvořit pro každé zařízení specifický program).
1171
1172 Pro ovladače měřících karet existuje v Linuxu subsystém -- tzv. Comedi (\textit{Control and Measurement Device Interface}).
1173
1174 Comedi se skládá ze tří částí:
1175
1176 \begin{description}
1177 \item[Comedi] -- jsou jednotlivé nízkoúrovňové ovladače zařízení, včetně hlavního ovladače \texttt{comedi}, který poskytuje základní funkce.
1178 \item[Comedilib] -- je knihovnou v uživatelském prostoru, která poskytuje jednotné rozhraní pro ovládání jednotlivých zařízení. 
1179 \item[Kcomedilib] -- je jaderný modul, který poskytuje stejné rozhraní jako Comedilib v uživatel\-ském prostoru. Používá se v případě potřeby ovládat zařízení v reálném čase.
1180 \end{description}
1181
1182
1183 \subsection{Registrace ovladače}
1184 Pro správnou funkci je potřeba, aby byl ovladač ihned po načtení modulu (tj. v \textit{init} funkci) zaregistrován -- jak do PCI subsystému, tak do subsystému Comedi. Registrace do PCI subsystému je popsána v kapitole \ref{pci_reg}. Registrace mezi Comedi ovladače se provede voláním \texttt{comedi\_driver\_register()}, kde jako parametr se předá ukazatel na strukturu \texttt{struct comedi\_driver}.
1185
1186 \subsection{Struktura \texttt{struct comedi\_driver}}
1187 Jednotlivé položky struktury \texttt{struct comedi\_driver} popisují daný ovladač. Mezi nej\-důle\-ži\-tější položky patří:
1188 \begin{description}
1189 \item[\texttt{const char *driver\_name;}]~\\Obsahuje textový název ovladače.
1190 \item[\texttt{struct module *module;}]~\\Ukazatel na modul, kterému tato struktura náleží. Inicializuje se makrem \texttt{THIS\_MODULE}.
1191 \item[\texttt{int (*attach) (struct comedi\_device *, struct comedi\_devconfig *);}]~\\Ukazatel na funkci, která má být zavolána při aktivaci ovladače.
1192 \item[\texttt{int (*detach) (struct comedi\_device *);}]~\\Ukazatel na funkci, která má být zavolána při deaktivaci ovladače.
1193 \end{description}
1194
1195 Na rozdíl od předchozích příkladů je v tomto případě tou hlavní \textit{inicializační} funkcí nikoliv funkce \texttt{probe()} volaná PCI subsystémem v případě, že se v systému nachází hardware, který umí ovladač obsloužit, ale funkce \texttt{attach()}, která je volána Comedi subsystémem v~závislosti na tom, zda má být ovladač použit nebo ne.
1196
1197 \subsection{Funkce \texttt{attach}}
1198 Funkce \texttt{attach} je volána v případě aktivace Comedi ovladače. Dříve než dojde na popis inicializačních kroků je nutné vysvětlit názvosloví, které je u Comedi ovladačů používáno.
1199
1200 \begin{description}
1201 \item[Board] označuje konkrétní zařízení -- měřící kartu. Některé ovladače podporují celou sadu zařízení (např. od stejného výrobce).
1202 \item[Subdevice (\textit{podzažízení})] je jedna z mnoha funkcí zařízení. V případě ovladače karty Humusoft MF614 budou implementovány 4 podzařízení: digitální vstupy, digitální výstupy, analogové vstupy, analogové výstupy. Každé z těchto podzařízení bude schopno obsluhovat více \textit{kanálů}.
1203 \end{description}
1204
1205 \vspace{1cm}
1206
1207 Kromě obvyklých operací, jako je \textit{aktivace zařízení}, žádos o \textit{výhradní přístup} ke zdrojům zařízení a \textit{mapování} paměťových nebo I/O regionů, popsaných v kapitole \ref{pci_driv}, je nutné alokovat a inicializovat struktury \texttt{struct comedi\_subdevice} odpovídající jednotlivým pod\-zařízením.
1208
1209 \subsection{Struktura \texttt{struct comedi\_subdevice}}
1210 Každé podporované funkci zařízení (tj. měřící karty) by měla odpovídat jedna struktura \texttt{struct comedi\_subdevice}. Hlavní položky, které struktura obsahuje jsou:
1211
1212 \begin{description}
1213 \item[\texttt{int type}]~\\ Označuje druh \textit{podzařízení}. Na výběr jsou např. možnosti: 
1214 \texttt{COMEDI\_SUBD\_AI} (analogový vstup), \texttt{COMEDI\_SUBD\_AO} (analogový výstup), \texttt{COMEDI\_SUBD\_DI} (digitální vstup), \texttt{COMEDI\_SUBD\_DO} (digitální výstup).
1215
1216 \item[\texttt{int subdev\_flags}]~\\ Označuje základní vlastnost podzařízení. Nejpoužívanější hodnoty: \texttt{SDF\_READABLE} (z~pod\-zařízení může být čteno), \texttt{SDF\_WRITABLE} (do podzařízení může být zapisováno).
1217
1218 \item[\texttt{int n\_chan}]~\\ Počet kanálů podzařízení (např. pro 8 digitálních vstupů bude tato hodnota 8).
1219
1220 \item[\texttt{unsigned int maxdata}]~\\ Maximální hodnota, která může být do podzařízení zapsána/čtena.
1221 \item[\texttt{const struct comedi\_lrange *range\_table}]~\\Označuje rozsah, ve kterém dané podzařízení měří (např. u A/D převodníku 0--10 V). K dispozici jsou definované struktury (stačí pouze předat ukazatel na některou z nich):\\
1222 \texttt{range\_digital},\\ \texttt{range\_bipolar10},\\ \texttt{range\_bipolar5},\\ \texttt{range\_unipolar10},\\ \texttt{range\_unipolar5}.\\ Jejich názvy jsou samovysvětlující.
1223
1224 \item[\texttt{int (*insn\_read) ( ... );}]~\\Ukazatel na funkci, která má na starosti čtení z podzařízení (většinou se používá pro A/D převodníky).
1225 \item[\texttt{int (*insn\_write) ( ... );}]~\\Ukazatel na funkci, která má na starosti zápis do zařízení (většinou se používá pro D/A převodníky).
1226 \item[\texttt{int (*insn\_bits) ( ... );}]~\\Ukazatel na funkci použitou pro zápis a čtení digitálních výstupů a vstupů,
1227 \item[\texttt{int (*insn\_config) ( ... );}]~\\Ukazatel na funkci, která má na starosti konfiguraci podzařízení.
1228
1229 Poslední čtyři funkce mají parametry: \\ \texttt{(struct comedi\_device *dev, 
1230 struct comedi\_subdevice *s, struct comedi\_insn *insn, unsigned int *data)}. První z nich je ukazatel na strukturu popisující Come\-di ovladač. Druhý je ukazatelem na strukturu odpovídající podzařízení. Třetí obsahuje ukazatel na strukturu popisující \textit{instrukci}, která má být provedena. Poslední obsahuje ukazatel na proměnnou, ze které je vyčtena zapisovaná hodnota nebo je do ni čtená hodnota zapsána.
1231  
1232 \end{description}
1233
1234 \ibox{\texttt{int alloc\_subdevices(struct comedi\_device *dev, unsigned int num\_subdevices);}}
1235
1236 Alokace paměti pro struktury se provede voláním \texttt{alloc\_subdevices()}, které je poskytováno Comedi subsystémem. Prvním parametrem je předán ukazatel na strukturu \texttt{struct comedi\_device}, pro kterou má být alokace provedena. Alokovaná paměť je přístupná skrze proměnnou \texttt{subdevices} náležící struktuře \texttt{struct comedi\_device}. 
1237
1238 V případě dealokace zdrojů ovladače není potřeba tuto paměť dealokovat -- o uvolnění paměti se postará Comedi subsystém. 
1239
1240 \subsection{Funkce pro čtení a zápis z/do podzařízení}
1241 Funkce pro čtení, zápis a konfiguraci A/D, D/A převodníků a~digitálních vstupů a~výstupů mají stejné parametry. Jsou to: \texttt{(struct comedi\_device *dev, 
1242 struct comedi\_subdevice *s, struct comedi\_insn *insn, unsigned int *data)}.
1243
1244 V prvním parametru je předán ukazatel na strukturu reprezentující Comedi zařízení. Díky tomu je možné prostřednictvím její proměnné \texttt{private} získat ukazatel na strukturu obsahující privátní data ovladače.
1245
1246 Druhý parametr je ukazatel na strukturu reprezentující podzařízení. Tato struktura obsahuje, kromě položek inicializovaných ve funkci \textit{attach} i proměnnou \texttt{state}. Tato proměnná popisuje \textit{stav zařízení} a používá se především pro zjištění stavu digitálních výstupů (stav digitálních výstupů většinou není možné ze zařízení přečíst, pro změnu pouze jednoho bitu je tedy potřeba znát stav ostatních).
1247
1248 Třetí parametr obsahuje ukazatel na strukturu popisující danou \textit{instrukci}, která má být provedena. Důležité položky, které tato struktura obsahuje:
1249 \begin{description}
1250 \item[\texttt{unsigned int n}]~\\Udává počet instrukcí, které mají být provedeny.
1251 \item[\texttt{unsigned int chanspec}]~\\Obsahuje informace o kanálu podzařízení, na kterém má být operace provedena. V~jedné proměnné typu \texttt{unsigned int} je obsaženo více údajů, proto je potřeba ke čtení používat speciální makro
1252 \texttt{CR\_CHAN()}, které vrací číslo zvoleného kanálu.
1253 \end{description}
1254
1255 Čtvrtý parametr obsahuje ukazatel na pole zapisovaných/čtených položek. Počet prvků pole odpovídá proměnné \texttt{n} struktury \texttt{struct comedi insn}. V případě čtení A/D převodníku obsahuje opakovaně čtené položky. Podobně to platí pro nastavování hodnoty D/A převodní\-ku. V případě čtení/zápisu digitálních vstupů/výstupů má toto pole pouze dva prvky. Čtenou/ zapisovanou hodnotu obsahuje položka \texttt{data[1]}. Položka \texttt{data[0]} obsahuje jako binární masku zadané kanály čtených/ zapiso\-vaných digitálních vstupů/výstupů.  
1256
1257 Příklad, jak může být implementováno čtení digitálních vstupů:
1258 \begin{verbatim}
1259   1 |  static int mf614_di_insn_bits(struct comedi_device *dev, 
1260   2 |                                struct comedi_subdevice *s, 
1261   3 |                                struct comedi_insn *insn,
1262   4 |                                unsigned int *data)
1263   5 |  {
1264   6 |      if(insn->n != 2) {
1265   7 |          return -EINVAL;
1266   8 |      }
1267   9 |  
1268  10 |      data[1] = ioread8(devpriv->BAR0_io + DIN_reg);
1269  11 |      
1270  12 |      return 2;
1271  13 |  }
1272 \end{verbatim}
1273
1274 \subsection{Funkce \texttt{detach}}
1275 Tato funkce je volána, jak v případě ukončení funkce ovladače, tak v případě, že funkce \textit{attach} neproběhla v pořádku. Proto je potřeba rozlišit, které zdroje ovladače již byly úspěšně naalokovány a mají být uvolněny.
1276
1277 Odregistrování ovladače z PCI a Comedi subsystému by mělo být voláno v \textit{úklidové fun\-kci} modulu. O samotné odregistrování se starají funkce:
1278 \texttt{pci\_unregister\_driver()} a \texttt{comedi\_driver\_unregister()}, kterým se jako parametr předá ukazatel na strukturu po\-uži\-tou při registraci.
1279
1280
1281 \subsection{Přístup z uživatelského prostoru}
1282 Pro správnou funkci konkrétního Comedi ovladače je nejprve potřeba načíst modul Comedi (\texttt{modprobe comedi}). Poté je již možné načíst ovladač zařízení (v případě ručně kompilovaného ovladače, pomocí příkazu \texttt{insmod}, jinak opět pomocí \texttt{modprobe}).
1283
1284 V případě, že proběhlo načtení modulu a spuštění funkce \textit{attach} bez problémů, měl by se ve složce \texttt{/dev} objevit nový soubor odpovídající načtenému ovladači zařízení -- \texttt{comedi0}\footnote{Pro názornost je uveden konkrétní příklad, v případě načtení více ovladačů budou odpovídající soubory číslovány od 0 výše.} K tomuto souboru je poté možné pomocí knihovních funkcí Comedilib přistupovat.
1285
1286 Pro přístup k zařízení je potřeba zavolat na soubor \texttt{/dev/comedi0} funkci \texttt{comedi\_open()}. Ta vrací ukazatel datového typu \texttt{comedi\_t}, reprezentující dané zařízení. K němu je možné přistupovat pomocí funkcí: \texttt{comedi\_data\_read()}, \texttt{comedi\_data\_write()}, \texttt{comedi\_dio\_read()}, \texttt{comedi\_dio\_write()} a jiných.
1287
1288 První dvě slouží pro zápis/čtení A/D a D/A převodníků, zatímco poslední dvě slouží pro přístup k digitálním vstupům/výstupům.
1289 Prvním parametrem všech funkcí je ukazatel na \texttt{comedi\_t} odpovídající danému zařízení. Druhým je číslo \textit{podzařízení}. Třetí parametr určuje kanál (tj. např. který z osmi A/D převodníků má být čten). Posledním parametrem je ukazatel na proměnnou, kam mají být zapsána přečtena data nebo hodnota, která má být zapsána.
1290
1291 Ukázka jednoduchého userspace programu:
1292 \begin{verbatim}
1293  1 |  #include <stdio.h>
1294  2 |  #include <comedilib.h>
1295  3 |  #define MF614_DO_SUBDEV      1 /* Je potřeba vědět, jak je 
1296  4 |                                    implementováno v ovladači */
1297  5 |  
1298  6 |  int main(int argc, char* argv[])
1299  7 |  {
1300  8 |      comedi_t* comedi_dev;
1301  9 |  
1302 10 |      comedi_dev = comedi_open("/dev/comedi0");
1303 11 |      if (comedi_dev == NULL) {
1304 12 |          comedi_perror("comedi_open");
1305 13 |          return 1;
1306 14 |      }
1307 15 |
1308 16 |      /* Zápis 1 na 0. kanál digitálního výstupu */  
1309 17 |      comedi_dio_write(comedi_dev, MF614_DO_SUBDEV, 0, 1);
1310 18 |      sleep(1);
1311 19 |      comedi_dio_write(comedi_dev, MF614_DO_SUBDEV, 0, 0);
1312 20 |      sleep(1);
1313 21 |      comedi_dio_write(comedi_dev, MF614_DO_SUBDEV, 0, 1);
1314 22 |      
1315 23 |      return 0;
1316 24 |  }
1317 \end{verbatim}
1318
1319 Při kompilaci je potřeba použít parametry \texttt{-lcomedi -lm}.
1320
1321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1322 \chapter{Implementace karty Humusoft MF624 v Qemu}\label{qemu}
1323 Měřící karta Humusoft MF624 je hardware vhodný pro výklad principů implementace ovladačů PCI zařízení. Nevýhodou může být její cena. 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. Takto modifikovaná verze qemu může pří implementaci základního ovladače plně nahradit původní kartu.
1324
1325 Kromě částečné implementace karty MF624 do Qemu je součástí tohoto \textit{virtuálního hardware} grafická aplikace, která má na starosti nastavování vstupních hodnot a zobrazování výstupních hodnot do/z karty (obr. \ref{qemu_diagram}).
1326
1327
1328 \begin{figure}[h!]
1329         \begin{center}
1330         \includegraphics[width=100mm]{img/qemu.pdf}
1331         \caption{Diagram znázorňující princip funkce implementované karty MF624 v Qemu}
1332         \label{qemu_diagram}
1333         \end{center}
1334 \end{figure}
1335
1336 \section{Qemu}
1337 Qemu je emulátor různých procesorových architektur. Od klasických virtualizačních nás\-tro\-jů se odlišuje tím, že podporuje kromě IA-32 architektury také např. ARM, SPARC, PowerPC, MIPS, m68k. Qemu umožňuje kromě \textit{plné emulace} (kdy je spuštěn celý operační systém) tzv. \textit{uživatelskou emulaci}, kdy je v uživatelském prostoru spuštěn program zkompilovaný pro jinou architekturu. Uživatelská emulace je možná pouze pro operační systém GNU/Linux.
1338
1339 \subsection{Kompilace, instalace}
1340 Po stažení a rozbalení zdrojových kódů některé ze stabilních verzí emulátoru Qemu je potřeba spustit příkaz (pro emulaci architektury IA-32):
1341 \begin{verbatim}
1342   $ ./configure --enable-system --target-list=i386-softmmu
1343 \end{verbatim}
1344
1345 Neohlásí-li spuštěný skript žádné chybějící knihovny, je možné spustit kompilaci:
1346 \begin{verbatim}
1347   $ make
1348 \end{verbatim}
1349
1350 \subsection{Kompilace virtuální karty Humusoft MF624}
1351 V případě, že je potřeba zkompilovat virtuální kartu MF624, je nejprve potřeba překopíro\-vat zdrojový soubor implementující zařízení do složky \texttt{/hw} a do souboru \texttt{Makefile.objs} (nachází se v kořenovém adresáři se zdrojovými kódy) přidat řádek:
1352
1353 \begin{verbatim}
1354   hw-obj-$(CONFIG_PCI) += mf624.o
1355 \end{verbatim}
1356 Poté je již možné spustit příkaz:
1357 \begin{verbatim}
1358   $ make
1359 \end{verbatim}
1360
1361
1362 \subsection{Použití}
1363 Zkompilovaný binární soubor se nachází v adresáři \texttt{i386-softmmu}. Nejnutnější parametr při spuštění je \texttt{-hda}, který uvádí cestu k souboru reprezentujícím \textit{obraz} spouštěného systému.
1364
1365 V případě správně zkompilované virtuální karty MF624, je možné ji spustit zadáním parametru \texttt{-device mf624}. Po spuštění je v příkazové řádce vypsáno číslo TCP/IP portu, na kterém virtuální karta MF624 naslouchá. Tento port slouží k připojení klientského programu, který má na starosti vykreslování výstupních a nastavování vstupních hodnot karty (možná implementace je popsána v kapitole \ref{qt_gui_ch}). V případě neexistence klientského software je možné se k virtuální kartě připojit pomocí programu \texttt{telnet}.
1366
1367 Příklad spuštění:
1368 \begin{verbatim}
1369   $ ./qemu -device mf624 -hda ../os_images/debian.qcow --boot c 
1370   MF624 Loaded.
1371   Waiting on port 55555 for MF624 client to connect
1372   Client connected
1373 \end{verbatim}
1374
1375 Příklad ovládání vstupů a zobrazování výstupů karty pomocí aplikace \texttt{telnet}:
1376 \begin{verbatim}
1377   $ telnet localhost 55555
1378   Trying ::1...
1379   Trying 127.0.0.1...
1380   Connected to localhost.
1381   Escape character is '^]'.
1382   DA1=9.998779
1383   DOUT=255.000000
1384   DOUT=0.000000
1385   DA1=5.000000
1386   ^]
1387   telnet> Connection closed.
1388 \end{verbatim}
1389
1390 \section{Qt grafiké rozhraní}\label{qt_gui_ch}
1391 Pro komunikaci s virtuální kartou MF624 bylo implementováno jednoduché grafické roz\-hraní, které má na starosti vykreslování hodnot výstupů karty (nastavovaných ovladačem běžícím v operačním systému virtualizovaném Qemu) a posílání nastavovaných vstupních hodnot zpět virtuální kartě.
1392
1393 Komunikace mezi virtuální kartou a grafickou aplikací probíhá pomocí TCP/IP protokolu. Přenášené informace jsou textového charakteru, ve formátu \texttt{REGISTR=HODNOTA}.
1394
1395 Na obrázku \ref{qt_gui} je snímek obrazovky implementované grafické aplikace.
1396
1397 \subsection{Kompilace, použití}
1398 Grafická aplikace je vytvořena za pomoci knihovny Qt. V případě, že je v~systému nainstalována vývojářská verze Qt knihovny, včetně potřebných vývojářských nástrojů, stačí pro kompilaci spustit:
1399 \begin{verbatim}
1400   $ qmake
1401   $ make
1402 \end{verbatim}
1403
1404 Jako parametr při spuštění je nutné zadat číslo portu, na kterém naslouchá virtuální karta MF624. Použití aplikace by mělo být intuitivní. Položky, u kterých není možné měnit jejich hodnotu, jsou záměrně pouze pro čtení (zobrazují výstupní hodnoty).
1405
1406
1407 \begin{figure}[h!]
1408         \begin{center}
1409         \includegraphics[width=100mm]{img/qt_gui.png}
1410         \caption{Vzhled grafické aplikace pro ovládání vstupů a výstupů virtuální karty MF624}
1411         \label{qt_gui}
1412         \end{center}
1413 \end{figure}
1414
1415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1416 \chapter{Testování}
1417 \section{UIO ovladač, Comedi ovladač}
1418 Jednotlivé ovladače jsou tvořeny samostatnými jadernými moduly, které pouze využívají funkce jednotlivých subsystémů -- neexportují žádné \textit{symboly} ani nemění globální proměnné. V tomto případě nebylo nutné provádět regresní testování.
1419
1420 Testování správnosti funkce ovladačů probíhala přímo na hardware, za pomoci \textit{univerzální svorkovnice TB620} (obrázek \ref{svorkovnice}).
1421
1422 \begin{figure}[h!]
1423         \begin{center}
1424         \includegraphics[width=120mm]{img/svorkovnice.jpg}
1425         \caption{Svorkovnice TB620}
1426         \label{svorkovnice}
1427         \end{center}
1428 \end{figure}
1429
1430 \vspace{1cm}
1431 Základní propojení na svorkovnici, které se osvědčilo, bylo:
1432 \begin{itemize}
1433 \item 2 $\times$ LED pro nejnižší a nejvyšší bit DOUT
1434 \item 2 $\times$ 1k$\Omega$ rezistory mezi 5 V a nejnižším a nejvyšším bitem DIN
1435 \item 2. bit DIN dynamicky spojován s GND nebo pomocí 1k$\Omega$ rezistoru s 5 V
1436 \item Měření multimetrem výstupní hodnoty z DAC (většinou DAC0 nebo DAC1)
1437 \item ADC0 spojen s GND, ADC1 spojen pomocí 1k$\Omega$ rezistoru s DAC0
1438 \end{itemize}
1439
1440 ~\\
1441
1442 Konzistence jádra byla testována opětovným načítáním a uvolňováním jednotlivých ovladačů.
1443
1444 \section{Qemu virtuální hardware, Qt grafické rozhraní}
1445 Správnost implementace virtuálního hardware byla testována spouštěním ovladačů (testovaných na skutečném hardware) v systému virtualizovaném v Qemu. Zároveň byla ověřena funkčnost grafického rozhraní, reprezentujícího vstupy a výstupy do/z virtuální karty. 
1446
1447
1448 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1449 \chapter{Závěr}
1450 V této práci se mi podařilo vysvětlit základní aspekty psaní ovladačů PCI zařízení pro operační systém GNU/Linux -- jak na obecné úrovni, tak u konkrétních ovladačů typu UIO a Comedi.
1451
1452 Součástí práce jsou základní (pokrývající pouze A/D, D/A převodníky a digitální vstupy/výstupy) ovladače pro karty Humusoft MF624 a Humusoft MF614. V budoucnu by tyto ovladače mohly být rozšířeny tak, aby pokrývaly všechny funkce těchto karet.
1453
1454 Pro potřeby výuky byly implementovány základní funkce karty Humusoft MF614 do emulátoru Qemu. Tato implementace by mohla být v budoucnu rozšířena, případně by mohla posloužit jako příklad pro tvorbu jiných jednoduchých PCI zařízení v Qemu, sloužících pro výuku implementace PCI ovladačů. I když tak nebylo původně zamýšleno, mohla by částečná implementace karty MF614 do Qemu posloužit i při výuce psaní ovladačů pro jiné operační systémy, jako například systémy rodiny Microsoft Windows.
1455
1456
1457 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1458 \appendix
1459 \chapter{Obsah přiloženého CD}
1460
1461 \begin{verbatim}
1462 .
1463 |-- doc
1464 |   |-- diploma_thesis  Text diplomové práce
1465 |   `-- hw              Informace k použitým kartám MF614 a MF624
1466 `-- src
1467     |-- comedi          Zdrojové kódy Comedi ovladačů pro karty MF614 a MF624
1468     |-- qemu            Implementace funkcí karty MF624 do Qemu
1469     |-- qemu_qt_gui     Grafické rozhraní pro virtuální kartu MF624 v Qemu
1470     `-- uio             Zdrojové kódy UIO ovladačů karet MF614 a MF624
1471 \end{verbatim}
1472
1473
1474 %\chapter{Hudaqlib}
1475