# Sterownik urządzenia HardDoom ## Budowanie, instalacja Potrzebujemy źródła Linuxa w katalogu `linux/` (można podsymlinkować). make insmod harddoom.ko Możliwe, że jeszcze będziemy chcieli móc pisać/czytać do urządzenia: chmod a+rw /dev/doom0 ## Opis plików w rozwiązaniu ### harddoom\_main.c Punkt wejściowy do modułu. Inicjalizuje sterowniki urządzenia znakowego i PCI. ### pci.c Definiujemy sterownik urządzenia PCI. W operacji `probe` włączymy urządzenie HardDoom i stworzymyy odpowiadające mu urządzenie znakowe `/dev/doomX`. Podczas inicjalizacji urządzenia również rejestrujemy handler przerwań, który pomoże nam w synchronizacji z urządzeniem. ### char.c Implementacja urządzenia znakowego. Rejestrujemy je w sysfs. Definiujemy ioctle dostępne na `/dev/doomX`. ### surface.c Implementacja buforów ramek, operacji które na nich wykonujemy, i pomocniczych struktur (buforów tekstur, etc.). ### harddoomdev.c Implementacja wrapperów na operacje, które możemy wykonywać na urządzeniu. Między innymi operacja `start_dev`, która uruchamia urządzenie, ładując mikrokod. ### private\_data.h Definicje struktur, które trzymamy jako dane prywatny sterowników lub inode'ów odpowiadających buforom. ### util.h Makra do obsługi błędów. ## Szczegóły implementacji Korzystamy z FIFO, nie bloku poleceń. ### Synchronizacja 1. Korzystamy z algorytmu ze wskazówek do znajdowania wolnego miejsca w FIFO. 2. Zakładamy lock na urządzenie gdy wysyłamy polecenia. Nie czekamy na ich zakończenie. 3. W operacji `read` na buforze ramki, czekamy na zakończenie rysowania poprzez `PING_SYNC`. Kładziemy się na semaforze, handler przerwania nas obudzi gdy przyjdzie `PONG_SYNC`. Aby zapewnić, że w locie jest tylko jeden `PING_SYNC`, przed wysłaniem bierzemy mutexa przeznaczonego do tego celu. ### Bezpieczeństwo, obsługa błędów 1. Staramy się zwracać sensowne kody błędów, na tyle na ile pozwala nam wybór kodów w jądrze. 2. Wszystkie dane, na które dostajemy wskaźnik z przestrzeni użytkownika kopiujemy do naszej pamięci operacją `copy_from_user`.