Do tematu: Podsystem wejścia-wyjścia
Do tematu: Struktury danych
Struktura tty_driver

Struktura tty_driver opisuje sterownik urządzenia terminalowego. Inicjalizowana jest podczas rozpoczęcia pracy systemu operacyjnego i w przeciwieństwie do struktury tty_struct istnieje statycznie. Struktura ta jest związana nie z pojedynczym urządzeniem, ale z typem (podtypem) urządzenia. Do obsługi takich samych urządzeń, nawet jeśli jest ich kilkadziesiąt, służy tylko jedna struktura tty_driverJeśli jakieś urządzenie terminalowe jest zarejestrowane w tablicy urządzeń znakowych chrdevs, to opisująca sterownik tego urządzenia struktura tty_driver znajduje się na dwukierunkowej liście tty_drivers.
 
typ nazwa pola opis
int magic Liczba magiczna
const char* name Nazwa urządzenia. 

Przykładowe wartości tego pola to: "tty", "console", "pty", "ttyp". Jeśli np. sterownik opisywany przez strukturę tty_driver jest sterownikiem części podrzędnej pseudoterminala, to pole name jest równe "ttyp".

int name_base Wartością pola name_base jest liczba definiująca przesunięcie wykorzystywane przy określaniu nazwy urządzenia. Zazwyczaj w systemie Linux może być obsługiwanych jednocześnie wiele urządzeń o tym samym numerze głównym. Wówczas pole name nie wystarcza do określenia jednoznacznej nazwy urządzenia. Dlatego napis, zapamiętany w polu name, jest konkatenowany z liczbą, która jest wyliczana w następujący sposób: 

numer drugorzędny urządzenia - minor_start + name_base

W wyniku powyższych działań powstają takie nazwy jak tty4, tty24, itp. Przeważnie wartością pola name_base jest zero. Wyjątek stanowią konsole. Dla konsol pole name_base jest równe jeden. Jest to związane z faktem, że konsola o numerze drugorzędnym zero oznacza bieżącą konsolę. Zatem nazwy konsol zaczynają się od tty1, a nie tty0

short major Numer główny urządzenia 
short minor_start Najmniejszy numer drugorzędny urządzenia o numerze głównym major. Od tego numeru rozpoczynają się numery drugorzędne urządzenia danego typu. Obecnie przyjmuje następujące wartości: 

1 dla konsol 

64 dla terminali 

128 dla pseudoterminali nadrzędnych 

192 dla pseudoterminali podrzędnych 

short num Liczba urządzeń danego typu, które mogą być jednocześnie obsługiwane przez system operacyjny Linux. Dla konsol i pseudoterminali pole to przyjmuje następujące wartości: 

MAX_NR_CONSOLES 63 

NR_PTYS 256 

Obecnie jednak, wartość NR_PTYS jest przepisywana (zmieniana na 64) . System może obsługiwać 64 pseudoterminale nadrzędne i 64 pseudoterminale podrzędne. 

short type Typ sterownika
short subtype Podtyp sterownika
struct termios init_termios Początkowe ustawienia parametrów pracy urządzenia terminalowego.
int  flags Flagi
int* refcount Licznik wskaźników w tablicy table, które są różne od NULL. 

Zmienne typu tty_struct, opisujące urządzenia terminalowe, są tworzone i niszczone dynamicznie. Początkową wartością wszystkich wskaźników w tablicy table jest NULL. Podczas inicjalizacji urządzenia przydzielana jest pamięć na zmienną typu tty_struct. Wskaźnik do tej zmiennej jest m.in. umieszczany w tablicy table. Wówczas zwiększany jest licznik *refcount. Gdy urządzenie jest zwalniane, licznik *refcount jest zmniejszany, a w tablicy table odpowiedni wskaźnik przyjmuje wartość NULL. 

Licznik *refcount jest potrzebny, ponieważ jeden sterownik może obsługiwać wiele urządzeń. Jeśli wartość licznika *refcount jest równa zero, to sterownik nie obsługuje żadnych urządzeń i można go np. wyrejestrować z tablicy chrdevs[]. Dokładniej: z tablicy chrdevs[] wyrejestrowywane jest urządzenie o numerze głównym równym polu major.

struct tty_driver* other Jeśli struktura tty_driver opisuje sterownik części podrzędnej (nadrzędnej) pseudoterminala, to other jest wskaźnikiem na strukturę opisującą sterownik części nadrzędnej (podrzędnej) tego pseudoterminala. 
struct tty_struct** table Tablica wskaźników do struktur tty_struct, które opisują aktualnie otwarte urządzenia terminalowe, obsługiwane przez dany sterownik. Rozmiarem tablicy table jest liczba numerów drugorzędnych zdefiniowanych dla urządzenia. Urządzeniu o logicznym numerze drugorzędnym i, odpowiada struktura *table[i]. Logicznym numerem drugorzędnym urządzenia jest liczba: 

drugorzędny numer urządzenia - minor_start

struct termios** termios Tablica wskaźników do struktur termios. Jej rozmiar jest taki jak rozmiar tablicy table. Jeśli urządzenie terminalowe, o logicznym numerze drugorzędnym i, jest otwarte, to table[i]->termios = termios[i]
struct termios** termios_locked Tablica wskaźników do struktur termios. Jej rozmiar jest taki jak rozmiar tablicy table. Jeśli urządzenie terminalowe, o logicznym numerze drugorzędnym i, jest otwarte, to table[i]->termios_locked = termios_locked[i].
int (*open)(struct tty_struct * tty, struct file * filp) Funkcja open jest wołana, gdy urządzenie terminalowe, obsługiwane przez dany sterownik, jest otwierane. Jeśli nie jest zdefiniowana, próba otwarcia kończy się błędem ENODEV (ang. error no device).
void (*close)(struct tty_struct * tty, struct file * filp) Funkcja close jest wołana, gdy urządzenie jest zamykane.
int  (*write)(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) Funkcja write musi być zdefiniowana, tzn. dla każdego sterownika write jest różne od NULL. Wołana jest przez jądro, aby zapisać sekwencję znaków do urządzenia. Znaki mogą pochodzić z przestrzeni adresowej użytkownika lub jądra. Funkcja zwraca liczbę zapisanych znaków.
void  (*put_char)(struct tty_struct *tty, unsigned char ch) Funkcja put_char jest wołana przez jądro, aby zapisać pojedynczy znak do urządzenia terminalowego. Znak ten nie jest jednak fizycznie przesyłany do urządzenia, ale tylko umieszczany w kolejce wyjściowej sterownika. Jeśli w kolejce tej nie ma miejsca, znak jest ignorowany.
void (*flush_chars)(struct tty_struct *tty) Funkcja flush_chars jest wołana przez jądro po zapisaniu znaków do urządzenia terminalowego za pomocą funkcji put_char. Zazwyczaj funkcja ta zapisuje dane do portów.
int  (*write_room)(struct tty_struct *tty) Funkcja write_room zwraca liczbę znaków, które sterownik może w danym momencie przyjąć do kolejki wyjściowej.
int  (*chars_in_buffer)(struct tty_struct *tty) Funkcja chars_in_buffer zwraca liczbę znaków, znajdujących się w kolejce wyjściowej sterownika.
int  (*ioctl)(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) Przy pomocy funkcji ioctl procesy mogą sterować pracą urządzenia. Wiele sterowników definiuje komendy, specyficzne dla urządzenia, które obsługują. Jeśli komenda (cmd) nie została przez sterownik rozpoznana, zwracany jest błąd ENOIOCTLCMD (ang. error no ioctl command).
void (*set_termios)(struct tty_struct *tty, struct termios * old) Funkcja set_termios jest wołana, aby poinformować sterownik o zmianie ustawień w strukturze termios. Struktura ta definiuje parametry pracy urządzenia obsługiwanego przez ten sterownik.
void (*throttle)(struct tty_struct * tty) Funkcja throttle jest wołana, gdy wejściowa kolejka znaków dyscypliny linii jest bliska przepełnienia. Funkcja ta jest związana z flagą TTY_THROTTLED.
void  (*unthrottle)(struct tty_struct * tty) Funkcja unthrottle jest wołana, aby powiadomić sterownik, że dyscyplina linii może już przyjmować kolejne znaki. Funkcja ta również jest związana z flagą TTY_THROTTLED.
void (*stop)(struct tty_struct *tty) Funkcja stop powiadamia sterownik, że powinien przestać wysyłać znaki do obsługiwanego urządzenia.
void (*start)(struct tty_struct *tty) Funkcja start powiadamia sterownik, że powinien wznowić wysyłanie znaków do urządzenia.
void (*hangup)(struct tty_struct *tty) Funkcja hangup informuje sterownik o tym, że obsługiwane przez niego urządzenie powinno zostać zawieszone. 
void (*flush_buffer)(struct tty_struct *tty) Funkcja flush_buffer usuwa znaki z bufora wyjściowego sterownika. W przeciwieństwie do funkcji flush_chars, nie zapisuje niczego do portów. Stąd wniosek, że słowo flush użyte jest tutaj w znaczeniu discard (pozbyć się, odrzucić).
void (*set_ldisc)(struct tty_struct *tty) Funkcja set_ldisc powiadamia sterownik o zmianie parametrów pracy urządzenia. Jest wołana, jeśli urządzeniu została przydzielona nowa dyscyplina linii. 
struct tty_driver * next Wskaźnik do następnej struktury tty_driver na liście tty_drivers. 
struct tty_driver * prev Wskaźnik do poprzedniej struktury tty_driver na liście tty_drivers. 

Typy
 
flaga kod opis
TTY_DRIVER_TYPE_SYSTEM 0x0001 Obecnie nieużywany
TTY_DRIVER_TYPE_CONSOLE 0x0002 Sterownik konsoli
TTY_DRIVER_TYPE_SERIAL 0x0003 Sterownik łącza szeregowego
TTY_DRIVER_TYPE_PTY 0x0004 Sterownik pseudoterminala
TTY_DRIVER_TYPE_SCC 0x0005 Sterownik urządzeń SCC
Podtypy
 
flaga kod opis
SYSTEM_TYPE_TTY 0x0001 Obecnie nieużywany
SYSTEM_TYPE_CONSOLE 0x0002 Obecnie nieużywany
PTY_TYPE_MASTER 0x0001 Sterownik pseudoterminala nadrzędnego
PTY_TYPE_SLAVE 0x0002 Sterownik pseudoterminala podrzędnego
W podprogramach obsługi urządzeń mogą być zdefiniowane dodatkowe podtypy, ściśle związane z rodzajem urządzenia.
Flagi
 
flaga kod opis
TTY_DRIVER_INSTALLED 0x0001 Ustawiona oznacza, że sterownik jest zarejestrowany, tzn. struktura tty_driver opisująca ten sterownik znajduje się na liście tty_drivers oraz w tablicy chrdevs[] jest zarejestrowane urządzenie o numerze głównym równym numerowi głównemu urządzenia obsługiwanego przez ten sterownik. Obecnie flaga ta używana jest wyłącznie w funkcji tty_register_driver() znajdującej się w pliku /drivers/char/tty_io.c.
TTY_DRIVER_RESET_TERMIOS 0x0002 Ustawienie flagi tej oznacza, że podczas odłączania terminala (funkcja do_tty_hangup() w pliku tty_io.c) zostanie nadana inicjalna wartość polu termios w strukturze tty_struct. Ponadto, przy zamykaniu terminala (funkcja release_dev() w pliku tty_io.c) przez ostatni podłączony do niego proces, flaga ta, ustawiona, spowoduje zwolnienie pamięci zajmowanej przez strukturę termios tego terminala.
TTY_DRIVER_REAL_RAW 0x0004 Ustawienie flagi tej oznacza, że urządzenie pracuje w trybie surowym oraz dodatkowo: pomijane lub akceptowane są znaki, które spowodowały błąd kontroli parzystości, a także nie jest sygnalizowane nadejście znaku przerywającego (VINTR).

Autor: Maciej Kaczmarek