% Impala Operating System
%
% Copyright (C) 2009 University of Wroclaw. Department of Computer Science
%    http://www.ii.uni.wroc.pl/
% Copyright (C) 2009 Mateusz Kocielski, Artur Koninski, Pawel Wieczorek
%    http://bitbucket.org/wieczyk/impala/
% All rights reserved.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions
% are met:
% 1. Redistributions of source code must retain the above copyright
%  notice, this list of conditions and the following disclaimer.
% 2. Redistributions in binary form must reproduce the above copyright
%  notice, this list of conditions and the following disclaimer in the
%  documentation and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
% ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
% FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
% DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
% OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
% HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
% LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
% SUCH DAMAGE.
%
% $Id$

\section{Sterowniki urządzeń.}
\label{DEV}

Większość sterowników urządzeń w~systemach UNIXowych tworzy tak zwane
pliki urządzeń, przez które można obsługiwać dane urządzenie.
W naszym
systemie zarządzaniem takimi plikami zajmuje się specjalny system plików
\texttt{devfs}, zamontowany w~katalogu \texttt{/dev}. Sterowniki plików
urządzeń dzielą się na~trzy kategorie:

\begin{itemize}
 \item urządzenia blokowe - sterowniki obsługujące takie
urządzenia jak
stacje dyskietek, dyski twarde itp.
 \item urządzenia znakowe - sterowniki obsługujące
urządzenie, widziane jako strumień bajtów.
 \item terminale - specjalny rodzaj urządzeń znakowych.
\end{itemize}

Każdy sterownik dostarcza systemowi tak zwaną deskę rozdzielczą
(\texttt{devsw\_t} - \emph{device switch}), która zawiera implementację
procedur obsługi pliku urządzenia. Deska rozdzielcza zawiera następujące pola:
\begin{itemize}
 \item \texttt{d\_open} -
obsługa otwarcia pliku urządzenia.

 \item \texttt{d\_close} -
obsługa zamknięcia pliku urządzenia.

 \item \texttt{d\_ioctl} -
obsługa poleceń kontrolnych dla~sterownika.

 \item \texttt{d\_write} -
obsługa zlecenia wyjścia ze strumienia znakowego, może blokować klienta
na~czas wykonywania operacji.

 \item \texttt{d\_read} -
obsługa zlecenia wejścia ze strumienia znakowego, może blokować klienta
na~czas wykonywania operacji.

 \item \texttt{d\_strategy} -
obsługa zleceń operacji wejścia-wyjścia na~urządzeniach blokowych, działa
asynchronicznie, tzn nie blokuje klienta na~czas wykonywania operacji.

 \item \texttt{type} -
informacja o kategorii, do jakiej urządzenie należy
\begin{itemize}
 \item \texttt{DEV\_BDEV} - dla urządzeń blokowych.
 \item \texttt{DEV\_CDEV} - dla urządzeń znakowych.
 \item \texttt{DEV\_TTY} - dla terminali.
\end{itemize}
\end{itemize}

Podział na urządzenia znakowe i~blokowe oraz rozróżnienie procedur
obsługujących zlecenia wejścia-wyjścia jest koniecznie ze względu na~wydajność
oraz obsługę tych urządzeń. Na~urządzeniach znakowych użytkownik może
wykonywać te same operacje jak na plikach, ponieważ pliki są również widziane
jako strumienie znakowe. Dozwolone są takie operacje jak przeczytanie jednego
bajtu, dwóch kilobajtów czy pięciu megabajtów.

Urządzenia blokowe jak dyski twarde cechuje inna metodą dostępu, fizycznie
są one podzielone na bloki danych (sektory). Stąd wszelkie transfery danych
między pamięcią RAM a~urządzeniem nie są tak elastyczne pod~względem wielkości
jak strumienie znaków.

Z~powodu tych różnic jednolita obsługa wejścia-wyjścia dla~tych dwóch rodzajów
urządzeń musiałaby emulować urządzenia blokowe jako znakowe, co nie byłoby
wydajne. Dzięki wyodrębnieniu oddzielnej procedury sterownik zawsze dostaje
zlecenia, których długość jest wielokrotnością długości sektoru oraz może sam
zadecydować w~jakiej kolejności najlepiej je wykonać (co tłumaczy nazwę
procedury - \emph{strategia}). 
% -- nie robię na jutro physio, nie wyrobie się. -- wieczyk
%Możliwy jest również dostęp strumieniowy do~takich
%urządzeń, jest on emulowany za~pomocą procedury \texttt{physio}, która
%wykorzystuje \texttt{d\_strategy}. Należy zwrócić uwagę, że jest to~jedynie
%dodatkowa metoda dostępu, przydatna zwykle programom chcącym bezpośrednio
%modyfikować dane na~urządzeniu lub ingerować w~zapisany tam system plików
%(jak np programy sprawdzające powierzchnię dysku czy spójność systemu plików).
Zagadnienia wejścia-wyjścia urządzeń blokowych są omówione w~rozdziale
\ref{BIO}.

Operacje wejścia-wyjścia na~terminalach działają na~tej samej zasadzie
co urządzeń blokowych, z~tą różnicą że te~operacje przechodzą dodatkową
warstwę zwaną reżimem linii. Te zagadnienia są szerzej omówione w~rozdziale
\ref{TTY}.

W kodzie systemu większość sterowników, poza specjalnymi, jest wydzielona
do~oddzielnej biblioteki \texttt{libdev.a} (lokalizacja: \texttt{sys/dev/}).
System operacyjny nie zna bezpośrednio wszystkich
zaimplementowanych w~niej sterowników, pobiera natomiast
tablicę \texttt{devtab} zawierającą procedury inicjujące sterowniki.
Specjalnymi sterownikami nie wydzielonymi do~wymienionej biblioteki są
wirtualne terminale emulowane przez konsolę, która jest częścią jądra.

System z~plikami urządzeń wiąże deskryptor urządzenia {\texttt{devd\_t}},
który zawiera w~sobie takie informacje jak nazwa urządzenia, wskaźnik
na~prywatne dane sterownika oraz jego deskę rozdzielczą. Jeden sterownik może
stworzyć wiele deskryptorów urządzeń, w zależności od~tego ile wykryje urządzeń,
które może obsługiwać. Przykładowo, zaimplementowany kontroler stacji dyskietek,
jeżeli wykryje dwie stacje dyskietek w~komputerze, to tworzy odpowiednio dwa
pliki urządzeń: \texttt{/dev/fd0} dla stacji \texttt{A:} oraz \texttt{/dev/fd1}
dla stacji \texttt{B:}. System taką stację dyskietek widzi jako dwa różne
deskryptory, które współdzielą ze sobą deskę rozdzielczą.

Nie wszystkie urządzenia w~sprzęcie komputerowym są obsługiwane za~pomocą
tego modelu sterowników. Sterowniki niektórych urządzeń mogą być programowane,
jako moduły dostarczające pewną funkcjonalność, a nie jako ogólnie dostępne
pliki urządzeń. Ta uwaga dotyczy niskopoziomowych urządzeń, które są
wykorzystywane przez jądro do dostarczania pewnych usług lub do~implementacji
innych sterowników. Udostępnienie ich jako pliki widziane dla użytkownika
nie wnosiłoby żadnych korzyści, a dodało trudności implementacyjnych.
Na przykład, sterownik szyny ISA udostępnia zbiór procedur
\texttt{bus\_isa\_dma\_} wykorzystywanych w~ sterowniku kontrolera stacji
dyskietek. Sterownik zegara systemowego instaluje podprogram przerwania,
który przy każdym tyknięciu uruchamia ogólną obsługę zegara w~systemie.
Obsługa przerwań sprzętowych jest omówiona w~rozdziale \ref{INT}.


\subsection{Szyna ISA.}

Sterownik szyny ISA jest dostarczany przez obsługę architektury sprzętu,
jest on potrzebny w~naszym systemie ponieważ kontroler stacji dyskietek
znajduje się na~niej. Zadaniem sterownika jest dostarczyć procedury
obsługujące transfery DMA.

Za obsługę transferów DMA w komputerach domowych są odpowiedzialne dwa
kontrolery Intel 8237A. Każdy z~nich obsługuje cztery kanały, służące
do wykonywania transferów. Każde urządzenia ma przypisany swój kanał, a
przed rozpoczęciem transferu należy go odpowiednio zaprogramować.

Deskryptor kanału musi zostać przydzielony
za~pomocą procedury \texttt{bus\_isa\_dma\_alloc}, a programowanie kanałów
odbywa się przez \texttt{bus\_isa\_dma\_prepare}.
Ponieważ te kontrolery są starą technologią to obsługują jedynie transfery
do~fragmentów pamięci RAM których adres mieści się w~24 bitach.
Taką pamięć nie zawsze można przydzielić, w~szczególności po~dłuższej pracy
systemu, ten problem jest rozwiązany przez przydzielanie stałych buforów
kanałom przy starcie systemu w~adresach poniżej 1MB
(zobacz rysunek \ref{vm:mmap}). Po wykonaniu transferu należy wykonać procedurę
\texttt{bus\_isa\_dma\_finish}.

Para procedur \texttt{\_prepare} i \texttt{\_finish} kopiują odpowiednio
dane pomiędzy stałym buforem kanału, a~buforem danym przez klienta.

\subsection{Sterownik stacji dyskietek.}

Omówienie sterownika stacji dyskietek wymaga uprzedzenia kilku wiadomości
z~rozdziału \ref{BIO}. Jak wspomniano wcześniej procedura \texttt{d\_strategy}.
służąca do~zlecenia operacji wejścia-wyjścia, posługuje się nagłówkami buforów.
Nagłówki (\texttt{iobuf\_t}), zawierają w~sobie bufor operacji, logiczny
numer bloku na~urządzeniu, długość transferu oraz informację o kierunku
transferu \texttt{BIO\_READ} lub \texttt{BIO\_WRITE}\footnote{Wszystkie kierunki
odnoszą się do~podmiotu, a nie pamięci. Stąd ,,czytanie'' wszędzie oznacza
czytanie z~podmiotu (np. urządzenia, pliku) do~pamięci, a~nie czytanie z~pamięci
do~podmiotu.}. Sterownik informuje klientów o~zakończeniu operacji za~pomocą
procedur \texttt{bio\_done} oraz, w przypadku błędu, \texttt{bio\_error}.

Procedura inicjalizująca sterownik \texttt{fdc\_init} sprawdza w~pamięci
CMOS jakie są zainstalowane stacje dyskietek i odpowiednio
na~podstawie tych informacji tworzy pliki urządzeń \texttt{fd0} i \texttt{fd1}.
Pliki urządzeń nie są oddzielnymi instancjami sterownika, ponieważ zależą
od~tego samego kontrolera stacji dyskietek. Zatem procedury obsługi
pliku urządzeń są pomostem do~ogólniejszego sterownika FDC (\emph{floppy disk
controller}). W obecnej implementacji kolejka zleceń wejścia-wyjścia jest
wspólna dla~wszystkich stacji na~danym kontrolerze.

Żadna z~procedur sterownika kontrolera nie czeka na~zakończenie zleconej
przez siebie operacji. Kontroler po wykonaniu zadania informuje o~jego
zakończeniu zgłaszając przerwanie sprzętowe, a podprogram jego obsługi
uruchamia dalej odpowiednie procedury. Dzięki temu podejściu sterownik
działa w~pełni asynchronicznie w~stosunku do~swoich klientów (dzięki czemu
nie blokuje żadnego z nich).

Implementacja procedury \texttt{d\_strategy} kolejkuje nagłówek buforu
w~kolejce zadań oraz jeżeli kolejka była pusta to rozpoczyna obsługę zlecenia.
Jeżeli kolejka nie jest pusta to kontroler wykonuje jedno ze zleceń, po
wykonaniu którego sam zacznie obsługiwać następne.

Obsługa zlecenia jest implementowana przez procedurę \texttt{fdc\_work}, która
w~zależności od~obecnego położenia głowicy zleca sterownikowi przesunięcie
głowicy lub wykonanie transferu.

Zmiana położenia głowicy jest wykonywana przez procedurę \texttt{fdc\_seek},
która zleca to~zadanie bezpośrednio kontrolerowi. Po wykonaniu
zadania jest zgłaszane przerwanie, którego obsługa zleca wykonanie transferu.

Transfer jest wykonywany przez procedurę \texttt{fdc\_io}, która
przeprogramowuje kanał DMA i zleca rozpoczęcie transferu kontrolerowi.
Stacja dyskietek 1440kB może obsłużyć wszystkie sektory do końca ścieżki
w~jednym transferze. Jeżeli jednak zlecony transfer sterownika przekracza
granicę ścieżki to~musi zostać podzielony na~ mniejsze transfery częściowe.
Obsługa zgłoszonego przerwania, informującego o zakończeniu operacji,
informuje klienta sterownika o~zakończeniu operacji używając \texttt{bio\_done}
lub wykonuje kolejny transfer częściowy za pomocą wyżej wymienionej procedury.

Transfery stacji dyskietek często kończą się błędami, które przy ponownej
próbie nie występują. Sterownik obsługuje to~nadając każdemu transferowi
częściowemu licznik prób, który jeżeli zostanie przekroczony to~operacja
jest zakończona procedurą \texttt{bio\_error} z~numerem błędu \texttt{EIO}.
Przy konieczności powtórzenia transferu częściowego jego długość jest
obcinana do~jednego sektora, obcięte sektory będą rozpatrywane w~kolejnym
transferze częściowym.

\subsection{Sztuczne urządzenia.}

W~naszym systemie istnieją trzy sztuczne urządzenia:
\begin{itemize}
 \item \texttt{null} - puste urządzenie znakowe
 \item \texttt{zero} - nieskończony strumień zer
 \item \texttt{md} (\emph{memory disk}) - urządzenie blokowe działające
         w~pamięci RAM. Było przez nas używane we wczesnych pracach
         nad wirtualnym systemem plików.
\end{itemize}
