]> rtime.felk.cvut.cz Git - mf6xx.git/blob - doc/diploma_thesis/text/dip_text.tex
Diploma thesis text.
[mf6xx.git] / doc / diploma_thesis / text / dip_text.tex
1 %FIXME
2 % vlna
3 % \caption{} bez tečky na konci
4 % \item[] a \item s tečkou na konci
5 % odsazování zdrojáků
6 % parametry funkce. Většinou nejsou, ale u prvních výskytů by se hodily
7
8 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9 \chapter{Úvod}
10 \section{Motivace, cíl}
11 Zadání této práce vzešlo z akademického prostředí a reaguje na nedostatek studijních materiálů v českém jazyce pro začátečníky, popisujících vývoj ovladačů (v tomto případě PCI zařízení) pro operační systém GNU/Linux.
12
13 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. Text obsahuje pouze nezbytné množství teorie, která je podložená četnými příklady pro snadnější pochopení čtenářem. Pro čtenáře neznalého psaní programů těsně svázaných s hardwarem se snažím názorně vysvětlit základní principy a úskalí tohoto druhu programování. V případě dalšího zájmu o problematiku může čtenář sáhnout po knize \cite{devicedriver}.
14
15 Kromě samotného popisu vývoje PCI ovladačů je cílem práce částečně implementovat funkce karty Humusoft MF624 do emulačního programu Qemu tak, aby si případný zájemce mohl vše vyzkoušet, aniž by fyzicky vlastnil hardware.
16
17 \section{Dostupné materiály}
18 V českém jazyce dosud vyšla pouze jedna tištěná kniha, která se zabývá problematikou vývoje pro jádro Linux. Jedná se o knihu \cite{jadrosystemu} od Lukáše Jelínka. Je dělena do 3 základních částí:
19 \begin{itemize}
20 \item \textit{Vnější rozhraní jádra}
21 \item \textit{Vývoj ovladačů}
22 \item \textit{Pohled dovnitř jádra}
23 \end{itemize}
24
25 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 studenta nižšího ročníku, neznalého vývoje jaderných ovladačů zařízení nemá příliš velký přínos.
26
27 Za nejpřínosnější knihu, zabývající se psaním ovladačů pro Linux, považuji anglicky psanou knihu \cite{devicedriver} od autorů Jonathan Corbet, Alessandro Rubini a Greg Kroah-Hartman. Knihu je možné stáhnout zdarma ve formátu PDF\footnote{\url{http://lwn.net/Kernel/LDD3/}}.
28
29 \begin{figure}[h!]
30         \begin{center}
31         \begin{minipage}[b]{0.4\linewidth}
32                 \includegraphics[width=50mm]{img/jadro-systemu-linux.jpg}
33         \end{minipage}
34         \begin{minipage}[b]{0.4\linewidth}
35                 \includegraphics[width=50mm]{img/lddrivers.jpg}
36         \end{minipage}
37         \caption{\textit{Vlevo}: Kniha Lukáše Jelínka (v českém jazyce). 
38                 \textit{Vpravo}: kniha od autorů Jonathan Corbet, Alessandro Rubini a Greg Kroah-Hartman (v anglickém jazyce)}
39         \label{knihy}
40         \end{center}
41 \end{figure}
42
43
44
45 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
46 \chapter{Hardware}
47 \section{Základní principy komunikace s hardwarem}
48 Jak je možné ovládat hardwarové periferie pomocí programu (software) je nejsnazší ukázat na příkladu jednočipového počítače.
49
50 \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. 
51 \begin{description}
52 \item[GPIO piny (General Purpose Input/Output)] -- u těchto pinů je možné nastavit, zda má být jejich hodnota čtena (slouží jako vstupní piny -- skrze ně vstupuje informace) nebo zda chceme jejich hodnotu nastavovat (tj. výstupní piny).%
53 %\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.
54 %\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).
55 \end{description}%
56 }
57
58 Prvním způsobem, jak změnit stav 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 pevně daná a liší mezi jednotlivými architekturami mikrokontrolérů), tato adresa odpovídá \textbf{registru}\footnote{Registr může být pro zjednodušení považován za malou paměťovou buňku. Změna její hodnoty přímo ovlivňuje stav hardware. V dokumentaci ke konkrétnímu mikrokontroléru/\-mikroprocesoru/\-programovatelnému integrovanému obvodu je uvedeno, jakou funkci mají jednotlivé bity registru.} GPIO pinu. Vnitřní uspořádání mikrokontroléru, dle adresy na kterou bylo zapisováno, rozpozná, že provedená operace zápisu nebyla určena pro změnu hodnoty vnitřní paměti, ale je určena pro změnu hodnoty registru a z toho plynoucí změny stavu určité části hardwaru. Zapsaná hodnota se tedy projeví změnou 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 prostoru}.\footnote{Také označováno jako MMIO -- \textit{Memory-mapped input/output}}
59
60 \begin{figure}[h!]
61         \begin{center}
62         \includegraphics[width=130mm]{img/gpio.pdf}
63         \caption{Registr odpovídající GPIO pinům. Změnou tohoto registru je možné měnit chování GPIO pinů}
64         \label{gpio_pins}
65         \end{center}
66 \end{figure}
67
68
69 Jiným způsobem změny stavu registru je použití 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 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 prostoru spolu nijak nesouvisí. 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. 
70
71 \ibox{V případě architektury IA-32 (označované také jako x86) máme k dispozici paměťový a vstupně-výstupní adresní prostor. Vstupně výstupní adresní prostor je pouze 16bitový, zatímco paměťový je (\textit{pro zjednodušení nebereme 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}.)}
72
73 Hlavní rozdíly mezi chováním paměťové buňky a registru zařízení jsou:
74 \begin{itemize}
75 \item Změnou hodnoty registru je možné měnit stav zařízení/periferie odpovídající danému registru.
76 \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.
77 \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. 
78 \item Při zápisu a čtení do/z registru si je nutné přesně rozlišovat, kolika-bitové operace zápisu/čtení smějí být použity (8-, 16-, 32bitové).
79 \end{itemize}
80
81 \begin{figure}[h!]
82         \begin{center}
83         \includegraphics[width=100mm]{img/mmio.pdf}
84         \caption{Paměťový a vstupně-výstupní prostor u architektury IA-32}
85         \label{mmio}
86         \end{center}
87 \end{figure}
88
89 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
90 \clearpage
91 %\newpage
92 \section{PCI sběrnice}\label{pcich}
93 %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í.
94
95 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{Příklad: FIXME}
96
97 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.
98
99 \subsection{Historie}
100 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 PC XT a PowerPC.
101
102 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.
103 \subsection{Konektory}
104 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 klíčovací zářezy -- tyto zářezy znemožňují zasunutí \textit{napěťově} nekompatibilní karty do slotu. Jsou však karty, které mají tyto zářezy oba, díky čemuž může být karta použita v libovolném slotu (Obr. \ref{pci}).
105
106 \begin{figure}[h!]
107         \begin{center}
108         \begin{minipage}[b]{0.4\linewidth}
109                 \includegraphics[width=57mm]{img/pci_schema2.png}
110         \end{minipage}
111         \begin{minipage}[b]{0.4\linewidth}
112                 \includegraphics[width=50mm]{img/pci2.jpg}
113         \end{minipage}
114         \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ů}
115         \label{pci}
116         \end{center}
117 \end{figure}
118
119
120 \subsection{Dynamická konfigurace a konfigurační adresní prostor}\label{pci_conf}
121 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 si každá karta pevně určila, 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é postará PCI most.
122
123 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{FIXME Ve skutečnosti funguje vyčtení požadované velikosti z registru karty PCI mostem takovým způsobem, že se PCI most snaží do každého BAR registru zapsat 0xFF a poté zapsanou hodnotu přečíst -- do BAR registru je možné zapsat pouze .... bla bla}. Poté co se PCI mostu podaří tuto hodnotu přečíst a požadovanou paměť alokovat, zapíše zpět do daného registru adresu, 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.
124
125
126 Kromě výše zmíněných 6 BAR registrů, obsahují PCI zařízení i následující registry:
127 \begin{description}
128 \item[Vendor ID]~\\Obsahuje unikátní 16bitové číslo identifikující výrobce zařízení. Za poplatek je udělová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}}
129 \item[Device ID]~\\Obsahuje 16bitové číslo identifikující model zařízení. Hodnotu tohoto identifikátoru si volí sám výrobce zařízení.
130 \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.
131 \item[Subsystem Vendor ID] -- Podobá se \texttt{Vendor ID}. V případě, že karta využívá PCI řadič třetí strany, jako \texttt{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.
132 \item[Subsystem ID]~\\Opět se jedná o údaj podobný \texttt{Device ID} sloužící k rozlišení karet postavených na univerzálním řadiči.
133 \end{description}
134
135 Registry \texttt{Vendor ID}, \texttt{Device ID} (příp. ještě \texttt{Subsystem Vendor ID} a \texttt{Subsystem ID}) slouží operačnímu systému k jednoznačné identifikaci zařízení, při volbě správného ovladače.
136
137
138 \begin{figure}[h!]
139         \begin{center}
140         \includegraphics[width=80mm]{img/pci-config-space2.pdf}
141         \caption{Obsah 256 bajtů konfiguračního prostoru PCI karty (zvýrazněny jsou nejdůležitější registry)}
142         \label{sa1}
143         \end{center}
144 \end{figure}
145
146 Výše popsané registry (spolu s ostatními, které zde nebyly popsány) se nacházejí v 256bitovém tzv. \textbf{konfiguračním adresním prostoru} karty\footnote{Po paměťovém a vstupně-výstupním adresním prostoru je zde třetí -- konfigurační -- adresní prostor.}. Přístup do konfiguračního adresního prostoru je na architektuře IA-32 možný pomocí zapsání adresy (\textit{kam chceme v konfiguračním prostoru zapisovat}) a dat (\textit{která chceme do konfiguračního prostoru zapsat}) do dvou speciálních I/O portů, které jsou pro tuto operaci vyhrazeny.
147
148
149 \subsection{Přerušení}
150 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í přerušení jsou úrovňově spouštěná (oproti hranovému spouštění nedochází k promeškání přerušení).
151
152 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žadavak směruje dále k procesoru.
153
154 \subsection{Budoucnost}
155 V posledních letech je na poli osobních počítačů PCI sběrnice nahrazována její nástupkyní -- sběrnicí PCIe (PCI Express). Ta je na rozdíl od PCI sériová a dosahuje rychlostí až 16 GB/s. I přesto je sběrnice PCI stále využívána mnohými zařízeními -- převážně v průmyslu.
156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
157 \section{Humusoft MF624}
158 \begin{figure}[h!]
159         \begin{center}
160         \includegraphics[width=150mm]{img/mf624.jpg}
161         \caption{Měřící karta Humusoft MF624}
162         \label{mf624}
163         \end{center}
164 \end{figure}
165
166 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:
167 \begin{itemize}
168 \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).
169 \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.
170 \end{itemize}
171
172 Karta MF624 najde své uplatnění hlavně v laboratorním prostředí -- v případech, když je potřeba vytvořit styk mezi počítačem a senzorem/jiným zařízením, které poskytuje analogový, resp. digitální signál (v tom případě jsou použity A/D převodníky, resp. digitální vstupy). Kartu je možné použít pro řízení akčního členu/zařízení -- k dispozici jsou D/A převodníky a digitální výstupy.
173
174 Karta disponuje následujícícmi funkcemi (v popisu implementace ovladačů se omezím pouze na A/D, D/A převodníky a digitální vstupy/výstupy):
175 \begin{itemize}
176 \item 8 digitálních vstupů (TTL kompatibilní logické úrovně)
177 \item 8 digitálních výstupů (TTL kompatibilní logické úrovně)
178 \item 8 14bitových A/D převodníků (rozsah $\pm$10 V)
179 \item 8 14bitových D/A převodníků (rozsah $\pm$10 V)
180 \item 4 časovače/čítače
181 \item 4 vstupy inkrementálních snímačů
182 \end{itemize}
183
184 \subsection{Komunikace s kartou}\label{hum_komunikace}
185 Komunikace s kartou není nijak složitá -- zjednodušeně by se dala popsat následovně:
186 \begin{itemize}
187 \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.
188 \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.
189 \end{itemize}
190
191 Které registry karta obsahuje, jakou mají funkci a kde jsou umístěny je možné zjistit z manuálu ke kartě -- ten je možné stáhnout z oficiálních internetových stránek výrobce: \url{http://www2.humusoft.cz/www/datacq/manuals/mf624um.pdf}.
192
193 Na straně 11 je k vidění první důležitá tabulka (zde tab. \ref{tab_bar}):
194
195 \begin{table}[h!]
196         \begin{center}
197         \begin{tabular}{|p{2cm}|p{4cm}|c|c|}
198         \hline \textbf{Region} & \textbf{Function} & \textbf{Size (bytes)} & \textbf{Width (bytes)} \\ 
199         \hline BADR0 (memory mapped) & PCI chipset, interrupts, status bits, special functions & 32 & 32 \\ 
200         \hline BADR1 (memory mapped) & A/D, D/A, digital I/O & 128 & 16/32 \\ 
201         \hline BADR2 (memory mapped) & Counter/timer chip & 128 & 32 \\ 
202         \hline 
203         \end{tabular} 
204         \caption{Paměťové regiony, které využívá karta MF624}
205         \label{tab_bar}
206         \end{center}
207 \end{table}
208
209 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 procesorem 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ý. Na tuto skutečnost se musí při implementaci ovladače brát zřetel.} mapované do paměťového adresního prostoru -- o velikostech 32, 128 a 128 bajtů. Pro čtení/zápis z/do nich je potřeba používat 32-, 16-, 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 rád vyhnul. Částečná implementace karty MF624 do emulátoru Qemu (Popsaná v příloze \ref{qemu}) umožňuje \textbf{pouze} 16bitový přístup do BAR1 paměťového regionu.}
210
211 \subsection{Digitální vstupy a výstupy}
212 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 (v oficiálním manuálu na straně 12) -- tomu odpovídá tabulka (s menšími úpravami) \ref{tab_bar1}.
213
214 \begin{table}[h!]
215         \begin{center}
216         \begin{tabular}{|p{17mm}|c|c|}
217         \hline \textbf{Address (BADR1 offset)} & \textbf{Read} & \textbf{Write} \\ 
218         \hline 0x00 & \textbf{ADDATA} -- A/D data & ADCTRL -- A/D control \\ 
219         \hline 0x02 & \textbf{ADDATA} -- A/D data mirror &  \\ 
220         \hline 0x04 & \textbf{ADDATA} -- A/D data mirror &  \\ 
221         \hline 0x06 & \textbf{ADDATA} -- A/D data mirror &  \\ 
222         \hline 0x08 & \textbf{ADDATA} -- A/D data mirror &  \\ 
223         \hline 0x0A & \textbf{ADDATA} -- A/D data mirror &  \\ 
224         \hline 0x0C & \textbf{ADDATA} -- A/D data mirror &  \\ 
225         \hline 0x0E & \textbf{ADDATA} -- A/D data mirror &  \\ 
226         \hline 0x10 & \textbf{DIN} -- Digital input & \textbf{DOUT} -- Digital output \\ 
227         \hline 0x20 & \textbf{ADSTART} -- A/D SW trigger & \textbf{DA0} -- D/A 0 data \\ 
228         \hline 0x22 &  & \textbf{DA1} -- D/A 1 data \\ 
229         \hline 0x24 &  & \textbf{DA2} -- D/A 2 data \\ 
230         \hline 0x26 &  & \textbf{DA3} -- D/A 3 data \\ 
231         \hline 0x28 &  & \textbf{DA4} -- D/A 4 data \\ 
232         \hline 0x2A &  & \textbf{DA5} -- D/A 5 data \\ 
233         \hline 0x2C &  & \textbf{DA6} -- D/A 6 data \\ 
234         \hline 0x2E &  & \textbf{DA7} -- D/A 7 data \\ 
235         \hline 
236         \end{tabular} 
237         \caption{Registry karty obsažené v regionu BAR1}
238         \label{tab_bar1}
239         \end{center}
240 \end{table}
241
242 Na devátém řádku jsou zmíněny \texttt{DIN} (Digital input) a \texttt{DOUT} (Digital output) registry. Z této tabulky je patrná pozice těchto registrů v paměťovém prostoru (t.j. offset v bytech vůči adrese BAR1).
243
244 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}). 
245 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.
246
247 \begin{table}[h!]
248         \begin{center}
249         \begin{tabular}{|c|c|c|}
250         \hline \textbf{Bit} & \textbf{Description} & \textbf{Default} \\ 
251         \hline 7:0 & \textbf{Digital input 7:0.} Reads digital input port. & 1 \\ 
252         \hline 15:8 & Reserved & N/A \\ 
253         \hline 
254         \end{tabular} 
255         \caption{DIN -- Digital Input Register Format}
256         \label{tab_din}
257         \end{center}
258 \end{table}
259
260 \begin{table}[h!]
261         \begin{center}
262         \begin{tabular}{|c|c|c|}
263         \hline \textbf{Bit} & \textbf{Description} & \textbf{Default} \\ 
264         \hline 7:0 & \textbf{Digital output 7:0.} Writes to digital output port. & 0 \\ 
265         \hline 15:8 & Reserved & N/A \\ 
266         \hline 
267         \end{tabular} 
268         \caption{DOUT -- Digital Output Register Format}
269         \label{tab_dout}
270         \end{center}
271 \end{table}
272
273
274 \subsection{A/D převodníky}
275 Karta MF624 obsahuje osm 14bitových A/D převodníků s pevně stanoveným rozsahem $\pm$10 V. Jejich vyčtení může probíhat následujícím způsobem:
276
277 \begin{itemize}
278 \item Nejprve se v registru ADCTRL zvolí, které A/D převodníky mají být čteny. 
279 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.
280 \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á.
281 \item V případě, že se 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).
282 \item Výslednou hodnotu je možné přečíst z registru ADDATA, který je typu FIFO. To znamená, že opětovným čtením jednoho registru jsou vyčítány jednotlivé naměřené hodnoty z měřených A/D převodníků v pořadí od 0 do 7.
283
284 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.
285 \end{itemize}
286
287 Hodnota vyčtená z A/D převodníků je ve formátu dvojkového doplňku -- příklad konkrétních hodnot je v tabulce \ref{tab_adval}.
288
289
290 \begin{table}[h!]
291         \begin{center}
292         \begin{tabular}{|c|c|}
293         \hline \textbf{Digitální hodnota} & \textbf{Analogová hodnota} \\ 
294         \hline 0x3FFF & -0.0012 V \\ 
295         \hline 0x2000 & -10.0000 V \\ 
296         \hline 0x1FFF &  9.9988 V \\ 
297         \hline 0x0000 &  0.0000 V \\ 
298         \hline 
299         \end{tabular} 
300         \caption{Kódování vstupních hodnot A/D převodníku}
301         \label{tab_adval}
302         \end{center}
303 \end{table}
304
305 \subsection{D/A převodníky}
306 Karta MF624 obsahuje také osm 14bitových D/A převodníků s rozsahem $\pm$10 V.
307
308 Nastavení výstupních hodnot D/A převodníků může probíhat následujícím způsobem:
309
310 \begin{itemize}
311 \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.
312 \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}.
313 \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).
314 \end{itemize}
315
316
317 \begin{table}[h!]
318         \begin{center}
319         \begin{tabular}{|c|c|}
320         \hline \textbf{Digitální hodnota} & \textbf{Analogová hodnota} \\ 
321         \hline 0x3FFF &  9.9988 V \\ 
322         \hline 0x2000 &  0.0000 V \\ 
323         \hline 0x1FFF & -0.0012 V \\ 
324         \hline 0x0000 & -10.0000 V \\ 
325         \hline 
326         \end{tabular} 
327         \caption{Kódování vstupních hodnot D/A převodníku}
328         \label{tab_daval}
329         \end{center}
330 \end{table}
331
332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
333 \newpage
334 \section{Humusoft MF614}
335 \begin{figure}[h!]
336         \begin{center}
337         \includegraphics[width=150mm]{img/mf614.jpg}
338         \caption{Měřící karta Humusoft MF614}
339         \label{mf614}
340         \end{center}
341 \end{figure}
342
343 Karta Humusoft MF614 má podobné funkce a využití jako karta MF624. Ve skutečnosti se jedná o její předchůdkyni. 
344
345 Karta disponuje následujícími funkcemi:
346
347 \begin{itemize}
348 \item 8 digitálních vstupů (TTL kompatibilní logické úrovně)
349 \item 8 digitálních výstupů (TTL kompatibilní logické úrovně)
350 \item 8 12bitových A/D převodníků (volitelné rozsahy $\pm$10 V, $\pm$5 V, 0--5 V, 0--10 V)
351 \item 4 12bitových D/A převodníků (rozsah $\pm$10 V)
352 \item 4 časovače/čítače
353 \item 4 vstupy inkrementálních snímačů
354 \end{itemize}
355
356 \subsection{Komunikace s kartou}
357 Způsob komunikace s kartou MF614 se mírně liší od MF624.
358
359 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ýstupní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. 
360
361 \begin{table}[h!]
362         \begin{center}
363         \begin{tabular}{|c|c|c|}
364         \hline \textbf{Region}          & \textbf{Function}                                             & \textbf{Size (bytes)} \\ 
365         \hline BADR0 (I/O mapped)       & Board programming registers                           & 32 \\ 
366         \hline BADR1 (I/O mapped)       & Reserved                                                                      & 4 \\ 
367         \hline BADR2 (I/O mapped)       & OX9162 local configuration registers          & 32 \\ 
368         \hline BADR3 (memory mapped) & OX9162 local configuration registers     & 4096 \\ 
369         \hline BADR4 (memory mapped) & Board programming registers                              & 4096 \\ 
370         \hline 
371         \end{tabular} 
372         \caption{Paměťové a vstupně-výstupní regiony, které využívá karta MF614}
373         \label{tab_mf614_bars}
374         \end{center}
375 \end{table}
376
377
378 \begin{table}[h!]
379         \begin{center}
380         \begin{tabular}{|c|c|c|}
381         \hline \textbf{Address} & \textbf{Read} & \textbf{Write} \\ 
382         \hline BADR0 + 0x0 & \textbf{ADLO} -- A/D data low                      & \textbf{ADCTRL} -- A/D control \\ 
383         \hline BADR0 + 0x1 & \textbf{ADHI} -- A/D data high                     &  \\ 
384         \hline BADR0 + 0x2 & \textbf{9513A} -- Data read                                & \textbf{9513A} -- Data write \\ 
385         \hline BADR0 + 0x3 & \textbf{9513A} -- Command read                     & \textbf{9513A} -- Command write \\ 
386         \hline BADR0 + 0x4 &  &  \\ 
387         \hline BADR0 + 0x5 &  &  \\ 
388         \hline BADR0 + 0x6 & \textbf{DIN} -- Digital input                      & \textbf{DOUT} -- Digital output \\ 
389         \hline BADR0 + 0x7 &  &  \\ 
390         \hline BADR0 + 0x8 & \textbf{DALE} -- D/A latch enable          & \textbf{DA0LO} -- D/A 0 data low byte \\ 
391         \hline BADR0 + 0x9 &                                                                            & \textbf{DA0HI} -- D/A 0 data high byte \\ 
392         \hline BADR0 + 0xA &                                                                            & \textbf{DA1LO} -- D/A 1 data low byte \\ 
393         \hline BADR0 + 0xB &                                                                            & \textbf{DA1HI} -- D/A 1 data high byte \\ 
394         \hline BADR0 + 0xC &                                                                            & \textbf{DA2LO} -- D/A 2 data low byte \\ 
395         \hline BADR0 + 0xD &                                                                            & \textbf{DA2HI} -- D/A 2 data high byte \\ 
396         \hline BADR0 + 0xE &                                                                            & \textbf{DA3LO} -- D/A 3 data low byte \\ 
397         \hline BADR0 + 0xF &                                                                            & \textbf{DA3HI} -- D/A 3 data high byte \\ 
398         \hline \ldots & \ldots & \ldots \\      
399         \hline BADR2 + 0x10 & \textbf{STATUS} -- Status register & \\   
400         \hline 
401         \end{tabular} 
402         \caption{Registry karty MF614 náležící digitálním vstupům/výstupům a analogovým vstupům/výstupům}
403         \label{tab_mf614_regs}
404         \end{center}
405 \end{table}
406
407 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:
408 \begin{verbatim}
409    u8 regAHI, regALO;
410    u16 regA;
411    
412    regA = regALO | (regAHI << 8);
413 \end{verbatim}
414
415 \subsection{Digitální vstupy a výstupy}
416 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 registr DIN.
417
418 \subsection{A/D převodníky}
419 Č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. 
420
421 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 (t.j. $0_{10} = 000_{2}$, $1_{10} = 001_{2}$, $2_{10} = 010_{2}$, $3_{10} = 011_{2}$, $4_{10} = 100_{2}$, \ldots). 
422
423 Bity 3 a 4 slouží k nastavení použitého rozsahu (způsob nastavení viz tabulka \ref{tab_mf614_rng}).
424
425 Bity 5, 6 a 7 nemají žádnou funkci a musí bát nastaveny na 0, 1, 0.
426
427 \begin{table}[h!]
428         \begin{center}
429         \begin{tabular}{|c|c|c|}
430         \hline \textbf{Bit} & \textbf{Jméno} & \textbf{Popis} \\ 
431         \hline  7                       &                               & Musí být nastaveno na 0 \\ 
432         \hline  6                       &                               & Musí být nastaveno na 1 \\ 
433         \hline  5                       &                               & Musí být nastaveno na 0 \\ 
434         \hline  4                       & RNG                   & Nastavení měřeného rozsahu A/D převodníku (tab. \ref{tab_mf614_rng}) \\ 
435         \hline  3                       & BIP                   & Nastavení, zda bude měřený rozsah \textit{bipolární} (tab. \ref{tab_mf614_rng}) \\ 
436         \hline  2, 1, 0         & A2, A1, A0    & Výběr A/D převodníku pro příští měření \\ 
437         \hline 
438         \end{tabular} 
439         \caption{Funkce jednotlivých bitů registru ADCTRL}
440         \label{tab_mf614_adctrl}
441         \end{center}
442 \end{table}
443
444 \begin{table}[h!]
445         \begin{center}
446         \begin{tabular}{|c|c|c|}
447         \hline \textbf{RNG} & \textbf{BIP} & \textbf{Vstupní rozsah [V]} \\ 
448         \hline  0                       &       0                       & 0--5 V \\ 
449         \hline  1                       &       0                       & 0--10 V \\ 
450         \hline  0                       &       1                       & -5--5 V \\ 
451         \hline  1                       &       1                       & -10--10 V \\ 
452         \hline 
453         \end{tabular} 
454         \caption{Volba rozsahu A/D převodníku}
455         \label{tab_mf614_rng}
456         \end{center}
457 \end{table}
458
459 Vyčtení hodnoty A/D převodníku může probíhat následujícím způsobem:
460
461 \begin{itemize}
462 \item Nejprve se v registru ADCRTL zvolí, který A/D převodník bude čten a který měřící rozsah bude použit.
463 \item Zápis do registru ADCTRL automaticky spouští převod.
464 \item Je-li CC bit (2. bit) registru STAT nastaven na 0, převod již byl ukončen.
465 \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í (t.j. 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.
466 \end{itemize}
467
468 \subsection{D/A převodníky}
469 Karta MF614 obsahuje 4 D/A převodníky. Ty mají pevně nastavený výstupní rozsah -10--10 V a nevyžadují žádnou konfiguraci.
470
471 Nastavení výstupu D/A převodníků může probíhat následujícím způsobem:
472 \begin{itemize}
473 \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 jsou zapsány do DA$x$HI na 4 nejnižší bity, nepoužité 4 MSB registru DA$x$HI jsou vyplněny nulami.
474
475 Hodnota je zapsána v aditivním kódu (tab. \ref{tab_mf614_dac}).
476
477 \item Čtením registru DALE se spustí převod všech D/A převodníků.
478 \end{itemize}
479
480 \begin{table}[h!]
481         \begin{center}
482         \begin{tabular}{|c|c|}
483         \hline \textbf{Digitální hodnota} & \textbf{Analogová hodnota} \\ 
484         \hline 0xFFF & 9.9951 V \\ 
485         \hline 0x800 & 0.0000 V \\ 
486         \hline 0x7FF & -0.0049 V \\ 
487         \hline 0x000 & -10.0000 V \\ 
488         \hline 
489         \end{tabular} 
490         \caption{Kódování vstupních hodnot D/A převodníku}
491         \label{tab_mf614_dac}
492         \end{center}
493 \end{table}
494
495 \ibox{
496 \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.
497 \\~\\
498 \textbf{LSB} (Least Significant Bit) je bit s nejnižší hodnotou. Jde o bit nejvíce vpravo.
499
500 \begin{center}
501 \texttt{1 0 1 0 1 0 1 0}\\
502 \texttt{MSB\hspace{2.6cm}LSB}
503 \end{center}}
504
505 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
506 \chapter{Implementace ovladačů}
507 \section{Operační systém GNU/Linux}
508 Jako cílový operační systém, na kterém bude vysvětlena implementace základních ovladačů, 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 dostupnost zdrojových kódů, velké množství kvalitní dokumentace, rozšířenost a vysoká kvalita. 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.
509
510 \subsection{Práce s PCI zařízeními z uživatelského prostoru}
511 Pro výpis všech zařízení v systému připojených pomocí sběrnice PCI slouží program \texttt{lspci}.
512 Po jeho spuštění bez udání parametrů bude vypsán základní seznam PCI zařízení. 
513
514 Mezi důležité parametry, použitelné při spuštění programu, patří:
515 \begin{description}
516 \item[\texttt{-t}] Zobrazí diagram znázorňující jednotlivé PCI sběrnice a mosty.
517 \item[\texttt{-v}, \texttt{-vv}, \texttt{-vvv}]
518  Umožňuje vypisování podrobných informací o zařízeních. (Postupně od \textit{střední podrobnosti} k \textit{vysoké podrobnosti}).
519 \item[\texttt{-nn}] Zobrazí Vendor ID a Device ID v číselné a zároveň i textové podobě
520 \item[\texttt{-d [<vendor>]:[<device>]}] Zobrazí informace pouze o zařízeních odpovídajících Vendor ID, případně i Device ID
521 \end{description}
522
523 Příklad, jak takový výpis může vypadat:
524 \begin{verbatim}
525 $ lspci -nn -d 186c:0624 -vvv
526 01:0b.0 Signal processing controller [1180]: Humusoft, s.r.o. MF624 
527              Multifunction I/O Card [186c:0624]
528         Subsystem: Humusoft, s.r.o. MF624 Multifunction I/O Card [186c:0624]
529         Control: I/O+ Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- 
530              Stepping- SERR- FastB2B- DisINTx-
531         Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- 
532              <MAbort- >SERR- <PERR- INTx-
533         Interrupt: pin A routed to IRQ 22
534         Region 0: Memory at d2dffc00 (32-bit, non-prefetchable) [size=128]
535         Region 1: I/O ports at b800 [size=128]
536         Region 2: Memory at d2dff800 (32-bit, non-prefetchable) [size=128]
537         Region 4: Memory at d2dff400 (32-bit, non-prefetchable) [size=128]
538         Kernel driver in use: mf624
539 \end{verbatim}
540
541
542 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.
543
544 \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.}
545
546 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ří:
547
548 \begin{description}
549 \item[\texttt{vendor}] -- Obsahuje Vendor ID zařízení.
550 \item[\texttt{device}] -- Obsahuje Device ID zařízení.
551 \item[\texttt{class}] -- Obsahuje 24bitový identifikátor třídy zařízení.
552 \item[\texttt{subsystem\_vendor}] -- Obsahuje Subsystem Vendor ID.
553 \item[\texttt{subsystem\_device}] -- Obsahuje Subsystem ID.
554 \item[\texttt{resource}] -- Soubor obsahuje popis jednotlivých regionů (reprezentovaných BAR registry) využívaných zařízením.
555 \end{description}
556
557 Struktura souboru \texttt{resource} může vypadat následovně:
558 \begin{verbatim}
559 0x00000000d2dffc00 0x00000000d2dffc7f 0x0000000000020200
560 0x000000000000b800 0x000000000000b87f 0x0000000000020101
561 0x00000000d2dff800 0x00000000d2dff87f 0x0000000000020200
562 0x0000000000000000 0x0000000000000000 0x0000000000000000
563 0x00000000d2dff400 0x00000000d2dff47f 0x0000000000020200
564 0x0000000000000000 0x0000000000000000 0x0000000000000000
565 \end{verbatim}
566
567 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). 
568
569
570
571
572 \subsection{Základní jaderný modul}
573 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ří jeho snadná implementace. Aby běžící jádro nemuselo obsahovat veškeré dostupné ovladače zařízení (nebo abychom v případě potřeby přidat do jádra ovladač pro nový hardware nemuseli celé jádro znovu kompilovat), existuje mechanismus načítání jaderných modulů za běhu, tzv. LKM -- 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.
574
575 Jak se takový jaderný modul může vypadat, je nejlepší si ukázat na příkladu:
576 \begin{verbatim}
577  1 |  #include <linux/init.h>
578  2 |  #include <linux/module.h>
579  3 | 
580  4 |  static int hello_init(void)
581  5 |  {
582  6 |      printk("Hello, world!\n");
583  7 |      return 0;
584  8 |  }
585  9 | 
586 10 |  static void hello_exit(void)
587 11 |  {
588 12 |      printk("Goodbye, cruel world!\n");
589 13 |  }
590 14 | 
591 15 |  module_init(hello_init);
592 16 |  module_exit(hello_exit);
593 17 |  
594 18 |  MODULE_LICENSE("Dual BSD/GPL");
595 \end{verbatim}
596
597 Z příkladu je patrné, že je modul napsán v programovacím jazyce C. To platí pro většinu všech jaderných modulů (stejně jako zdrojových kódů jádra samotného). Ve skutečnosti se jedná o mírně modifikovaný standard C90.
598 \begin{description}
599 \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.
600 \item[Na řádcích 4--8] je funkce, která bude spuštěna ihned po zavedení našeho modulu do jádra. Ta obsahuje pouze volání funkce \texttt{printk()}.
601
602 Pro jednoduchost můžeme s funkcí \texttt{printk()} pracovat jako s, pro čtenáře známou, funkcí \texttt{printf()} -- 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}.\\Jak se zařídí, že se tato funkce vykoná ihned po zavedení modulu do jádra? O to se postará příkaz na $\rightarrow$
603 \item[řádku 15] -- ten obsahuje makro \texttt{module\_init()}, kterému řekneme právě to, která funkce se má po načtení spustit.
604 \item[Řádek 16] obsahuje naopak makro, které udává, která funkce se má zavolat v případě, že se bude modul uvolňovat z jádra. V našem případě je to funkce na $\rightarrow$
605 \item[řádcích 10--13.] Tato funkce nemá na starost nic jiného než výpis krátkého textu do logu jádra.
606 \end{description}
607
608 \subsection{Kompilace modulu}
609 Dále je potřeba jaderný modul přeložit\footnote{Před samotným překladem jádra je potřeba mít k dispozici zdrojové kódy jádra. Ty je možné stáhnout z \texttt{kernel.org} nebo v distribuci Debian nainstalovat pomocí příkazu \texttt{apt-get install linux-source}}. K tomu poslouží následující \texttt{Makefile}:
610 \begin{verbatim}
611 1 |  KERNEL_VER=`uname -r`
612 2 |  obj-m += hello.o
613 3 |
614 4 |  all:
615 5 |      make -C /lib/modules/$(KERNEL_VER)/build M=$(PWD) modules
616 6 |  clean:
617 7 |      make -C /lib/modules/$(KERNEL_VER)/build M=$(PWD) clean
618 \end{verbatim}
619 Linux využívá při kompilaci systému \texttt{KBUILD}. Ten je tvořen množstvím Makefile souborů a jeho smyslem je umožnit uživateli snadnou konfiguraci před kompilací -- určující, které čáasti se do jádra zakompilují a které nikoliv. Popis toho systému je mimo rozsah této práce. Stručný popis výše zmíněného Makefile souboru:
620
621 \begin{description}
622 \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í)
623 \item[Druhý řádek] říká, že modul bude vytvářen ze zdrojového souboru \texttt{hello.c} (pod tímto názvem jsme uložili náš ukázkový modul)
624 \item[Na pátém řádku] (uvozeném tabelátorem) se volá (pomocí přepínače \texttt{-C}) Makefile ze systému \texttt{KBUILD}, který se nachází v adresáři spolu se zdrojovými kódy jádra. Parametrem \texttt{M} říkáme, které moduly si přejeme vytvořit -- v tomto případě jsou to ty, jejichž zdrojové soubory jsou v aktuálním adresáři (tj. \texttt{PWD}).
625 \end{description}
626
627 V případě, že 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:
628 \begin{verbatim}
629 $ make
630 make -C /lib/modules/`uname -r`/build M=/tmp/kernel_module_example modules
631 make[1]: Entering directory `/usr/src/linux-headers-2.6.35-28-generic'
632   CC [M]  /tmp/kernel_module_example/hello.o
633   Building modules, stage 2.
634   MODPOST 1 modules
635   CC      /tmp/hello.mod.o
636   LD [M]  /tmp/hello.ko
637 make[1]: Leaving directory `/usr/src/linux-headers-2.6.35-28-generic'
638 \end{verbatim}
639 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} -- t.j. zkompilovaný jaderný modul připravený na zavedení do jádra.
640
641 \begin{verbatim}
642 $ ls
643 hello.c  hello.ko  hello.mod.c  hello.mod.o  hello.o  
644 Makefile  modules.order  Module.symvers
645 \end{verbatim}
646
647 \subsection{Zavedení modulu}
648 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:
649 \begin{verbatim}
650 $ sudo insmod ./hello.ko 
651 \end{verbatim}
652
653 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:
654 \begin{verbatim}
655 $ dmesg | tail -1
656 [ 9245.757491] Hello, world!
657 \end{verbatim}
658 A skutečně je posledním řádkem v logu text vypsaný zavedeným modulem.
659
660 Pro plné otestování funkčnosti ukázkového modulu, je potřeba ho z jádra uvolnit. K tomu slouží program \texttt{rmmod} (opět je potřeba spouštět se superuživatelskými privilegii).
661 \begin{verbatim}
662 $ sudo rmmod hello 
663
664 $ dmesg | tail -1
665 [ 9612.256929] Goodbye, cruel world!
666 \end{verbatim}
667 V logu je opět nachází text vypisovaný modulem při uvolňování z jádra.
668
669
670 \ibox{V případě, že se chystáme do jádra zavést modul, jehož jsme autoři a nejsme si jisti jeho funkčností, doporučuji si veškerou důležitou práci uložit 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.}
671
672 \subsection{Na co si dávat pozor}
673 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ří:
674
675 \begin{description}
676 \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 nebo ho na to alespoň upozornil.
677 \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.
678 \item[Přímý přístup k hardwaru]~\\Základní jaderný modul psaný například nezkušeným studentem má zcela stejné možnosti 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}}.
679 \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.
680
681 V případě ukončení funkce ovladače musí být tato paměť uvolněna.
682 \end{description}
683
684 \subsection{Příkaz GOTO}
685 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í.
686
687 Příklad pro lepší názornost:
688 \begin{verbatim}
689  1 |  int mf614_attach(...)
690  2 |  {
691  3 |      if(pci_enable_device(devpriv->pci_dev))
692  4 |          goto out_exit;
693  5 |  
694  6 |      if(pci_request_regions(devpriv->pci_dev, "mf614"))
695  7 |          goto out_disable;
696  8 |  
697  9 |      if (!pci_iomap(devpriv->pci_dev, 0, 0))
698 10 |          goto out_release;
699 11 |    
700 12 |  out_release:
701 13 |      pci_release_regions(devpriv->pci_dev);
702 14 |  out_disable:
703 15 |      pci_disable_device(devpriv->pci_dev);
704 16 |  out_exit:
705 17 |      return -ENODEV;
706 18 |  }
707 \end{verbatim}
708
709 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í.
710
711 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 jak funkce \texttt{pci\_disable\_device()}, tak funkce \texttt{pci\_release\_regions()} -- to způsobuje duplikaci kódu, která vede k nepřehlednosti a může způsobovat chyby (v případě, že se omylem změní volání funkce pouze na jednom místě).
712
713 Za pomoci volání \texttt{goto} je výše popsaný problém elegantně vyřešen.
714
715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
716 \section{Základní funkce v prostředí jádra Linux}
717 \subsection{Funkce \texttt{printk()}}
718 FIXME
719 \subsection{Funkce \texttt{kalloc()}}
720 \subsection{Funkce \texttt{kfree()}}
721
722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723 \section{Ovladače PCI zařízení}\label{pci_driv}
724 \ibox{Jako nejlepší reference jednotlivých funkcí slouží zdrojové kódy jádra. Pro prohlížení zdrojových kódů jádra mohu doporučit online \textit{The Linux Cross Reference} -- \\
725 \url{http://lxr.linux.no/linux/}.}
726
727 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}). Druhá varianta se týká všech ovladačů standardně zkompilovaných s jádrem.
728
729 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}), o tomto zařízení. Hotplug subsystém (v uživatelském prostoru) poté na základě informací od jádra, jako je Vendor ID a Device ID , rozhodne, který ovladač má být pro dané zařízení načten. Seznam, dle kterého se rozhodne, který ovladač bude načten je v souboru \texttt{/lib/modules/\$(uname -r)/modules.pcimap}.
730
731 Každý ovladač by měl tedy obsahovat informaci o tom, pro které zařízení je určen. To je uvedeno ve struktuře \texttt{struct pci\_device\_id}.
732
733 \subsection{Struktura \texttt{struct pci\_device\_id}}\label{pci_dev_id}
734 Struktura \texttt{struct pci\_device\_id} slouží k identifikaci, pro která zařízení je ovladač určen. Mezi hlavní položky struktury patří \texttt{vendor}, \texttt{device}, \texttt{subvendor}, \texttt{subdevice} (typu \texttt{\_\_u32}) -- jejichž hodnota odpovídá stejnojmenným registrům v konfiguračním prostoru PCI zařízení. Jelikož může být ovladač napsán pro více zařízení, je tato struktura inicializována jako prvek pole, které je zakončeno prvkem prázdným. Různé způsoby inicializace mohou vypadat následovně:
735
736 \begin{verbatim}
737  1 |  #define PCI_VENDOR_ID_HUMUSOFT          0x186c
738  2 |  #define PCI_DEVICE_ID_MF624             0x0624
739  3 |  #define PCI_DEVICE_ID_MF614             0x0614
740  4 |  #define PCI_SUBVENDOR_ID_HUMUSOFT       0x186c
741  5 |  #define PCI_SUBDEVICE_MF624             0x0624
742  6 |  
743  7 |  static struct pci_device_id mf624_pci_id[] = {
744  8 |      {
745  9 |          .vendor = PCI_VENDOR_ID_HUMUSOFT,
746 10 |          .device = PCI_DEVICE_ID_MF624,
747 11 |          .subvendor = PCI_SUBVENDOR_ID_HUMUSOFT,
748 12 |          .subdevice = PCI_SUBDEVICE_MF624,
749 13 |      },
750 14 |
751 15 |      { PCI_VENDOR_ID_HUMUSOFT, PCI_DEVICE_ID_MF614, 
752 16 |          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
753 17 |
754 18 |      { 0, } /* seznam je vždy zakončen prázdným prvkem */
755 19 |  };
756 \end{verbatim}
757
758 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í 
759 i pro Subdevice ID).
760
761 \ibox{\texttt{MODULE\_DEVICE\_TABLE(type, struct pci\_device\_id* name);}}
762
763 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}.
764
765 \subsection{Struktura \texttt{struct pci\_driver}}\label{pci_reg}
766 Pro to, aby mohl se mohl ovladač PCI zařízení stát součástí jaderného PCI subsystému, je potřeba ho do 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}. 
767
768 Tato struktura obsahuje základní informace o ovladači -- základní proměnné a ukazatele na funkce. Mezi hlavní položky patří:
769 \begin{description}
770 \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.
771 \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}).
772 \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.
773 \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.
774 \end{description}
775
776 Příklad, jak může být struktura \texttt{pci\_driver} inicializována a následně zaregistrována:
777 \begin{verbatim}
778  1 |  static struct pci_driver mf624_pci_driver = {
779  2 |      .name = "mf624",
780  3 |      .id_table = mf624_pci_id,
781  4 |      .probe = mf624_pci_probe, 
782  5 |      .remove = mf624_pci_remove,
783  6 |  };
784  7 |  pci_register_driver(&mf624_pci_driver);
785 \end{verbatim}
786
787
788 \subsection{Funkce \texttt{probe()}}\label{pci_init}
789 \ibox{\texttt{int probe(struct pci\_dev *dev, const struct pci\_device\_id *id);}}
790
791 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í.
792
793 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}).
794
795 \ibox{\texttt{pci\_enable\_device(struct pci\_dev *dev);}}
796
797 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í.
798
799 \subsection{Přístup ke zdrojům karty}
800 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}. 
801
802 \ibox{\texttt{int pci\_request\_regions(struct pci\_dev *pdev, const char *res\_name);}}
803
804 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.
805
806 \ibox{\texttt{unsigned long pci\_resource\_start(struct pci\_dev *dev, int bar);}}
807
808 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). 
809 %Volání této funkce má pouze informativní charakter
810
811 \ibox{\texttt{unsigned long pci\_resource\_len(struct pci\_dev *dev, int bar);}}
812
813 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()}.
814
815 \ibox{\texttt{void \_\_iomem *pci\_ioremap\_bar(struct pci\_dev *pdev, int bar);}}
816
817 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()}.
818
819 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.
820
821 \subsection{Funkce \texttt{remove()}}
822
823 \ibox{\texttt{void remove(struct pci\_dev *dev);}}
824
825 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.
826
827 Tato funkce by se měla postarat o úklid všech naalokovaných prostředků. Měla by obsahovat volání:
828 \begin{description}
829 \item[\texttt{iounmap()}]~\\Uvolnění virtuální paměti namapované voláním \texttt{pci\_ioremap\_bar()}.
830 \item[\texttt{pci\_release\_regions()}]~\\Uvolnění zdrojů karty, které byly zarezervovány voláním \texttt{pci\_request\_regions()}.
831 \item[\texttt{pci\_disable\_device()}]~\\Opak k volání \texttt{pci\_enable\_device()}.
832 \end{description}
833
834 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
835 \section{Přístup k paměti zařízení}\label{iofce}
836 Poté co se ovladači podařilo získat přístup ke zdrojům zařízení, je nutné využít speciálních volání pro zápis/čtení do/z těchto zdrojů.
837
838 \subsection{Vstupně-výstupní adresní prostor}
839 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í:
840
841 \ibox{\texttt{unsigned inb(unsigned port);}}
842
843 \ibox{\texttt{unsigned inw(unsigned port);}}
844
845 \ibox{\texttt{unsigned inl(unsigned port);}}
846
847 Třetí písmeno značí o \textit{kolika-bitové} čtení se jedná: b = 8 b, w = 16 b, l = 32 b.
848
849 Pro zápis je možné využít volání:
850 \ibox{\texttt{void outb(unsigned char byte, unsigned port);}}
851
852 \ibox{\texttt{void outw(unsigned char byte, unsigned port);}}
853
854 \ibox{\texttt{void outl(unsigned char byte, unsigned port);}}
855
856
857 Třetí písmeno, stejně jako u funkcí pro čtení, značí o kolika-bitový přístup se jedná.
858
859 Funkce se stejným \textit{prototypem} jsou k dispozici i v uživatelském prostoru (potřebný hlavičkový soubor je \texttt{<sys/io.h>}).
860
861 \subsection{Paměťový adresní prostor}
862 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 k 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.
863
864 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 bude lišit od toho, jak to bylo v programu zamýšleno.
865
866 Těmto optimalizacím lze nejsnáze zabránit použitím volání pro čtení:
867
868 \ibox{\texttt{unsigned int ioread8(void *addr);}}
869
870 \ibox{\texttt{unsigned int ioread16(void *addr);}}
871
872 \ibox{\texttt{unsigned int ioread32(void *addr);}}
873
874 a pro zápis:
875
876 \ibox{\texttt{void iowrite8(u8 value, void *addr);}}
877
878 \ibox{\texttt{void iowrite16(u16 value, void *addr);}}
879
880 \ibox{\texttt{void iowrite32(u32 value, void *addr);}}
881
882 Číslo na konci funkce označuje o kolika-bitový přístup se jedná.
883
884 V případě, že se na paměť ve vstupně-výstupním adresním prostoru zavolá funkce 
885 \ibox{\texttt{void *ioport\_map(unsigned long port, unsigned int count);}} 
886 nebo v případě PCI zařízení funkce
887 \ibox{\texttt{void *pci\_iomap(struct pci\_dev *dev, int bar, unsigned long maxlen);}}
888
889 se paměť chová jakoby byla v paměťovém adresním prostoru a je nutné pro přístup k ní používat volání popsaná v této kapitole.
890
891
892 Pro přístup k paměti zařízení z uživatelského prostoru bohužel žádná sada funkcí není. Je potřeba nadefinovat funkce vlastní, které přistupují k paměti skrze ukazatel, který je ale označen jako \texttt{volatile}. To opět zabrání překladači v optimalizaci kódu manipulujícího s ukazatelem.
893
894 Příklad jak takové funkce mohou vypadat:
895
896 \begin{verbatim}
897   1 | static inline void mf624_write32(uint32_t val, uint32_t *ptr)
898   2 | {
899   3 |     *(volatile uint32_t*) ptr = val;
900   4 | }
901   5 | static inline int32_t mf624_read32(uint32_t *ptr)
902   6 | {
903   7 |     return (volatile uint32_t) *ptr;
904   8 | }
905 \end{verbatim}
906
907 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
908 \section{UIO ovladač}
909 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 zvukovou kartu. Tato volba určí, kterou sadu pomocných funkcí bude moci ovladač používat a jakým způsobem bude zpřístupněno zařízení do uživatelského prostoru.
910
911 V případě, že jde o PCI zařízení, které nelze snadno zařadit do žádné kategorie (jedná-li se například o neobvyklou průmyslovou 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živatelském prostoru. 
912
913 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 (její implementace je poměrně snadná). Druhou částí je aplikace v uživatelské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.
914
915 \subsection{Jaderný modul}
916 Jaderný modul UIO ovladače PCI zařízení by měl obsahovat:
917 \begin{itemize}
918 \item Funkci volanou PCI subsystémem při registraci ovladače
919 \item Volání funkcí pro namapování regionů zařízení
920 \item Inicializaci struktury \texttt{struct uio\_info} a registraci do UIO subsystému
921 \item Funkce pro \textit{úklid} a uvolnění regionů karty
922 \end{itemize}
923
924 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}.
925
926 \ibox{\texttt{int uio\_register\_device(struct device *parent, struct uio\_info *info);}}
927
928 Registrace UIO ovladače se provede zavoláním funkce \texttt{uio\_register\_device()}, které se jako první parametr předá ukazatel na \textit{rodiče} struktury \texttt{struct pci\_dev} -- tj. ukazatel na její položku \texttt{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.
929 Druhý parametr předá ukazatel na strukturu \texttt{struct uio\_info}.
930
931 \subsubsection{Struktura \texttt{struct uio\_info}}
932
933 Jedná se o strukturu vyplněnou informacemi o zařízení, která je předána při registraci UIO subsystému.
934 Mezi její hlavní položky patří:
935 \begin{description}
936 \item[\texttt{const char *name}]~\\Název ovladače. Většinou se shoduje s názvem modulu.
937 \item[\texttt{const char *version}]~\\Verze ovladače v textové podobě.
938 \item[\texttt{struct uio\_mem mem[MAX\_UIO\_MAPS]}]~\\Pole struktur obsahujících informace o regionech PCI zařízení mapovaných do paměťového prostoru (bude podrobně vysvětleno dále).
939 \item[\texttt{struct uio\_port port[MAX\_UIO\_PORT\_REGIONS]}]~\\Pole struktur obsahujících informace o regionech PCI zařízení mapovaných do vstupně-výstupního prostoru (bude podrobně vysvětleno dále).
940 \end{description}
941
942 \subsubsection{Struktura \texttt{struct uio\_mem} a \texttt{struct uio\_port}}\label{uio_mem_port}
943 Tyto struktury obsahují informace o regionech zařízení. Které (a kolik) z těchto dvou struktur budou inicializovány záleží na tom, zda karta mapuje regiony do paměťového nebo vstupně-výstupního prostoru.
944
945 Struktura \texttt{struct uio\_mem} obsahuje položky:
946 \begin{description}
947 \item[\texttt{const char *name}]~\\Textový popis daného regionu (viditelný z uživatelského prostoru).
948 \item[\texttt{unsigned long addr}]~\\Fyzická adresa regionu získaná voláním \texttt{pci\_resource\_start()}.
949 \item[\texttt{unsigned long size}]~\\Délka regionu. Nejsnáze získaná voláním \texttt{pci\_resource\_len()}.
950 \item[\texttt{int memtype}]~\\Typ paměti. Pro fyzickou paměť na zařízení se použije \texttt{UIO\_MEM\_PHYS}.
951 \item[\texttt{void \_\_iomem *internal\_addr}]~\\Virtuální adresa získaná voláním \texttt{pci\_ioremap\_bar()}.
952 \end{description}
953
954 Struktura \texttt{struct uio\_port} obsahuje položky:
955 \begin{description}
956 \item[\texttt{const char *name}]~\\Textový popis daného regionu (viditelný z uživatelského prostoru).
957 \item[\texttt{unsigned long start}]~\\Fyzická adresa regionu získaná voláním \texttt{pci\_resource\_start()}.
958 \item[\texttt{unsigned long size}]~\\Délka regionu. Nejsnáze získaná voláním \texttt{pci\_resource\_len()}.
959 \item[\texttt{int porttype}]~\\Typ portu. Pro porty na architektuře IA-32 se použije \texttt{UIO\_PORT\_X86}.
960 \end{description}
961
962 ~\\
963
964 Příklad, jak taková jednoduchá inicializace struktury \texttt{struct uio\_info} včetně registrace může vypadat (bez ošetření chybových stavů):
965 \begin{verbatim}
966  1 |  /* struct pci_dev *dev */
967  2 |  struct uio_info *info;
968  3 |  info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
969  4 |  
970  5 |  info->name = "mf624";
971  6 |  info->version = "0.0.1";
972  7 |  
973  8 |  info->mem[0].name = "PCI chipset, ...";
974  9 |  info->mem[0].addr = pci_resource_start(dev, 0);
975 10 |  info->mem[0].size = pci_resource_len(dev, 0);
976 11 |  info->mem[0].memtype = UIO_MEM_PHYS;
977 12 |  info->mem[0].internal_addr = pci_ioremap_bar(dev, 0);
978 13 |  
979 14 |  info->port[0].name = "Board programming registers";
980 15 |  info->port[0].porttype = UIO_PORT_X86;
981 16 |  info->port[0].start = pci_resource_start(dev, 1);
982 17 |  info->port[0].size = pci_resource_len(dev, 1);
983 18 |  
984 19 |  uio_register_device(&dev->dev, info);
985 20 |  pci_set_drvdata(dev, info);
986 \end{verbatim}
987
988 \ibox{\texttt{void pci\_set\_drvdata(struct pci\_dev *pdev, void *data)}}
989
990 Na posledním řádku je, dosud nepopsané, volání \texttt{pci\_set\_drvdata()}. To (v tomto případě) zajistí, že struktura \texttt{struct uio\_info} se stane součástí struktury reprezentující zařízení (\texttt{struct pci\_dev}) -- což umožní 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}.
991
992 \ibox{\texttt{static inline void *pci\_get\_drvdata(struct pci\_dev *pdev)}}
993
994 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()}.
995
996 Příklad použití:
997 \begin{verbatim}
998  1 |  static void mf624_pci_remove(struct pci_dev *dev)
999  2 |  {
1000  3 |      struct uio_info *info = pci_get_drvdata(dev);
1001  4 |      /* ... */
1002  5 |  }
1003 \end{verbatim}
1004
1005
1006 \subsection{Program v uživatelském prostoru}
1007 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:
1008 \begin{itemize}
1009 \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.}}.
1010 \item složkou \texttt{/sys/class/uio/uio0}, která obsahuje informace o regionech, které jsou zpřístupněny skrze UIO modul v jádře.
1011 \end{itemize}
1012
1013 \subsubsection{Obsah složky \texttt{/sys/class/uio/uio0}}
1014 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 PCI zařízení mapovaný do paměti (zpřístupněný jaderným ovladačem) složka obsahující soubory popisující tyto regiony (Soubor \texttt{addr} obsahuje fyzickou adresu regionu; \texttt{name} slovní pojmenování; \texttt{size} velikost regionu).
1015
1016 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}.
1017
1018 \subsubsection{Soubor \texttt{/dev/uio0}}
1019 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 karty. K souboru se přistupuje pomocí volání \texttt{mmap()}.
1020
1021 \ibox{\texttt{void *mmap(void *addr, size\_t length, int prot, int flags, int fd, off\_t offset);}}
1022
1023 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ěť.
1024  
1025 \begin{description}
1026 \item[Parametr \texttt{addr}]~\\V případě, že není nulový, určí na jakou adresu by měla být paměť mapována.
1027 \item[Parametr \texttt{length}]~\\ Udává velikost mapované paměti v násobcích velikosti paměťové stránky. 
1028 \item[Parametr \texttt{prot}]~\\ Obsahuje příznaky definující, zda bude mapovaná paměť pro čtení/zápis, apod.
1029 \item[Parametr \texttt{flags}]~\\ Pomocí příznaku 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}).
1030 \item[Parametr \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", ... );}).
1031 \item[Parametr \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.
1032 \end{description}
1033
1034 Příklad, jak takové volání může vypadat (bez ošetření chybových stavů):
1035 \begin{verbatim}
1036  1 |  #define BAR2_offset       (1 * sysconf(_SC_PAGESIZE))
1037  2 |  
1038  3 |  void* mf624_BAR2 = NULL;
1039  4 |  int device_fd = open("/dev/uio0", O_RDWR);
1040  5 |  
1041  6 |  mf624_BAR2 = mmap(0, 1 * sysconf(_SC_PAGESIZE), 
1042  7 |                    PROT_READ | PROT_WRITE, MAP_SHARED, 
1043  8 |                    device_fd, BAR2_offset);
1044 \end{verbatim}
1045
1046 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 PCI 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.
1047
1048 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):
1049 \begin{verbatim}
1050 mf624_BAR2 += (BAR2_phys_addr & (sysconf(_SC_PAGESIZE) - 1));
1051   |                \-- Fyzická adresa
1052    \-- Ukazatel vrácený voláním mmap()                 
1053 \end{verbatim}
1054
1055 \subsection{Přístup k paměti zařízení}
1056 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}.
1057
1058 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1059 \newpage
1060 \section{Comedi ovladač}
1061 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).
1062
1063 Pro ovladače měřících karet (které disponují základními funkcemi) existuje v Linuxu subsystém -- tzv. Comedi (Control and Measurement Device Interface).
1064
1065 Comedi se skládá ze tří částí:
1066
1067 \begin{description}
1068 \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.
1069 \item[Comedilib] -- je knihovnou v uživatelském prostoru, která poskytuje jednotné rozhraní pro ovládání jednotlivých zařízení. 
1070 \item[Kcomedilib] -- je jaderný modul, který poskytuje stejné rozhraní jako Comedilib v uživatelském prostoru. Používá v případě potřeby ovládat zařízení v reálném čase.
1071 \end{description}
1072
1073
1074 \subsection{Registrace ovladače}
1075 Pro správnou funkci je potřeba, aby byl ovladač ihned po načtení modulu (t.j. v \textit{init} funkci) zaregistrován, jak do PCI subsystému, tak do subsystému Comedi. Registrace mezi PCI zařízení je popsána v kapitole \ref{pci_reg}. Registrace mezi Comedi ovladače se provede voláním \texttt{comedi\_driver\_register(struct comedi\_driver *driver)}, kde jako parametr se předá ukazatel na strukturu \texttt{struct comedi\_driver}.
1076
1077 \subsection{Struktura \texttt{struct comedi\_driver}}
1078 Nejdůležitější položky, které tato struktura obsahuje jsou ukazatele na funkce volané při aktivaci Comedi ovladače.
1079
1080 Položky struktury jsou:
1081 \begin{description}
1082 \item[\texttt{const char *driver\_name;}]~\\Obsahuje textový název ovladače.
1083 \item[\texttt{struct module *module;}]~\\Ukazatel na modul, kterému tato struktura náleží. Inicializuje se makrem \texttt{THIS\_MODULE}.
1084 \item[\texttt{int (*attach) (struct comedi\_device *, struct comedi\_devconfig *);}]~\\Ukazatel na funkci, která má být zavolána při aktivaci ovladače.
1085 \item[\texttt{int (*detach) (struct comedi\_device *);}]~\\Ukazatel na funkci, která má být zavolána při deaktivaci ovladače.
1086 \end{description}
1087
1088 Narozdí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.
1089
1090 \subsection{Funkce \texttt{attach}}
1091 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.
1092
1093 \begin{description}
1094 \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).
1095 \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.
1096 \end{description}
1097
1098 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}.
1099
1100 \subsection{Struktura \texttt{struct comedi\_subdevice}}
1101 Každé podporované funcki zařízení/karty by měla odpovídat jedna struktura \texttt{struct comedi\_subdevice}. Hlavní položky, které struktura obsahuje:
1102
1103 \begin{description}
1104 \item[\texttt{int type}]~\\ Označuje druh \textit{podzařízení}. Na výběr jsou např. možnosti: 
1105 \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).
1106
1107 \item[\texttt{int subdev\_flags}]~\\ Označuje základní vlastnost podzařízení. Nejpoužívanější hodnoty: \texttt{SDF\_READABLE} (z podzařízení může být čteno), \texttt{SDF\_WRITABLE} (do podzařízení může být zapisováno).
1108
1109 \item[\texttt{int n\_chan}]~\\ Počet kanálů podzařízení (např. pro 8 digitálních vstupů bude tato hodnota 8).
1110
1111 \item[\texttt{unsigned int maxdata}]~\\ Maximální hodnota, která může být do podzařízení zapsána/čtena.
1112 \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 jejich ukazatel):\\
1113 \texttt{range\_digital},\\ \texttt{range\_bipolar10},\\ \texttt{range\_bipolar5},\\ \texttt{range\_unipolar10},\\ \texttt{range\_unipolar5}.\\ Jejich názvy jsou samovysvětlující.
1114
1115 \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).
1116 \item[\texttt{int (*insn\_write) ( ... );}]~\\Ukazatel na funkci, která má na starosti zápis do zařízení (většinou se používá pro A/D převodníky).
1117 \item[\texttt{int (*insn\_bits) ( ... );}]~\\Ukazatel na funkci použitou pro zápis a čtení digitálních výstupů a vstupů,
1118 \item[\texttt{int (*insn\_config) ( ... );}]~\\Ukazatel na funkci, která má na starosti konfiguraci podazařízení.
1119
1120 Poslední čtyři funkce mají parametry: \\ \texttt{(struct comedi\_device *, struct comedi\_subdevice *, struct comedi\_insn *, unsigned int *);}. První z nich je ukazatel na strukturu popisující Comedi 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.
1121  
1122 \end{description}
1123
1124 \ibox{\texttt{int alloc\_subdevices(struct comedi\_device *dev, unsigned int num\_subdevices)}}
1125
1126 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}. 
1127
1128 V případě dealokace zdrojů ovladače není potřeba tuto paměť dealokovat -- o uvolnění paměti se postará Comedi subsystém. 
1129
1130 \subsection{Funkce pro čtení a zápis z/do podzařízení}
1131
1132 \subsection{Funkce \texttt{detach}}
1133
1134 \subsection{Přístup z uživatelského prostoru}
1135 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}).
1136
1137 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í -- 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.
1138
1139 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ího dané zařízení. K němu je možné přistupovat pomocí funkcí\\
1140 \texttt{comedi\_data\_read()},\\
1141 \texttt{comedi\_data\_write()},\\
1142 \texttt{comedi\_dio\_read()},\\
1143 \texttt{comedi\_dio\_write()}.
1144
1145 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.
1146 Prvním parametrem všech funkcí je ukazatel na \texttt{comedi\_t}. Druhým je číslo \textit{podzařízení}. Třetí parametr určuje kanál (t.j. 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.
1147
1148 Ukázka jednoduchého userspace programu:
1149 \begin{verbatim}
1150   1 |  #include <stdio.h>
1151   2 |  #include <comedilib.h>
1152   3 |  #define MF614_DO_SUBDEV      1 /* Je potřeba vědět, jak je 
1153   4 |                                    implementováno v ovladači */
1154   5 |  
1155   6 |  int main(int argc, char* argv[])
1156   7 |  {
1157   8 |      comedi_t* comedi_dev;
1158   9 |  
1159  10 |      comedi_dev = comedi_open("/dev/comedi0");
1160  11 |      if (comedi_dev == NULL) {
1161  12 |          comedi_perror("comedi_open");
1162  13 |          return 1;
1163  14 |      }
1164  15 |
1165  16 |      /* Zápis 1 na 0. kanál digitálního výstupu */  
1166  17 |      comedi_dio_write(comedi_dev, MF614_DO_SUBDEV, 0, 1);
1167  18 |      sleep(1);
1168  19 |      comedi_dio_write(comedi_dev, MF614_DO_SUBDEV, 0, 0);
1169  20 |      sleep(1);
1170  21 |      comedi_dio_write(comedi_dev, MF614_DO_SUBDEV, 0, 1);
1171  22 |      
1172  23 |      return 0;
1173  24 |  }
1174 \end{verbatim}
1175
1176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1177 \chapter{Implementace Humusoft MF624 v Qemu}\label{qemu}
1178 Měřící karta Humusoft MF624 je hardware vhodný pro výklad principů implementace ovladače -- je ale poměrně drahý. Pro účely výuky proto byly do emulačního software Qemu implementovány základní funkce této měřící karty -- konkrétně se jedná o A/D převodníky, D/A převodníky a digitální vstupy a výstupy. Takto modifikovaná verze qemu může pří implementaci základního ovladače plně nahradit původní kartu.
1179
1180 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.
1181
1182
1183 \section{Qemu}
1184 \subsection{Kompilace, instalace}
1185 Nejprve je potřeba řádně zkompilovat některé ze stabilních vydání emulátoru Qemu.
1186
1187 \subsection{Použití}
1188 Komunikace mezi virtuální kartou implementovanou v Qemu a grafickým programem probíhá pomocí TCP/IP protokolu.
1189
1190 \section{Qt grafiké rozhraní}
1191 Na obrázku \ref{qt_gui} je 
1192
1193 Aplikaci je nutné spouštět až po spuštění Qemu ....
1194
1195 \begin{figure}[h!]
1196         \begin{center}
1197         \includegraphics[width=70mm]{img/qt_gui.png}
1198         \caption{(FIXME aktualni verzi). Vzhled grafikcé aplikace pro ovládání vstupů virtuální karty MF624}
1199         \label{qt_gui}
1200         \end{center}
1201 \end{figure}
1202
1203 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1204 \chapter{Testování}
1205 \section{UIO ovladač, Comedi ovladač}
1206 Jednotlivé ovladače jsou tvořeny samostatnými jadernými moduly, které pouze využívají volání 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í.
1207
1208 Testování správnosti funkce ovladačů probíhala přímo na hardware, za pomoci \textit{univerzální svorkovnice TB620} (obrázek \ref{svorkovnice}).
1209
1210 \begin{figure}[h!]
1211         \begin{center}
1212         \includegraphics[width=120mm]{img/svorkovnice.jpg}
1213         \caption{Svorkovnice TB620}
1214         \label{svorkovnice}
1215         \end{center}
1216 \end{figure}
1217
1218 \vspace{1cm}
1219 Základní propojení na svorkovnici, které se osvědčilo, bylo:
1220 \begin{itemize}
1221 \item 2 $\times$ LED pro nejnižší a nejvyšší bit DOUT
1222 \item 2 $\times$ 1k$\Omega$ rezistory mezi 5 V a nejnižším a nejvyšším bitem DIN
1223 \item 2. bit DIN dynamicky spojován s GND nebo pomocí 1k$\Omega$ rezistoru s 5 V
1224 \item Měření multimetrem výstupní hodnoty z DAC (většinou DAC0 nebo DAC1)
1225 \item ADC0 spojen s GND, ADC1 spojen pomocí 1k$\Omega$ rezistoru s DAC0
1226 \end{itemize}
1227
1228 ~\\
1229
1230 Konzistence jádra byla testována opětovným načítáním a uvolňováním jednotlivých ovladačů.
1231
1232 \section{Qemu virtuální hardware, Qt grafické rozhraní}
1233 Správnost implementace virtuálního hardware byla testována spouštěním implementovaných ovladačů v systému virtualizovaného v Qemu. Zároveň byla ověřena funkčnost grafického rozhraní, reprezentujícího vstupy a výstupy do/z virtuální karty. 
1234
1235
1236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1237 \chapter{Závěr}
1238 V této práci se mi podařilo vysvětlit základní aspekty psaní ovladačů PCI ovladačů -- jak na obecné úrovni, tak u konkrétních ovladačů typu UIO a Comedi.
1239
1240 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 614. V budoucnu by tyto ovladače mohly být rozšířeny tak, aby pokrývaly všechny funkce těchto karet.
1241
1242 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 implementaci jiných jednoduchých PCI zařízení 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.
1243
1244
1245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1246 %\appendix
1247 %\chapter{Hudaqlib}
1248
1249 %\chapter{Obsah přiloženého CD}