Funkcje driveru informuja dysk o akcji do wykonania przy pomocy funkcji
Funkcje driveru moga pobierac poprzez odpowiedni port stan dysku
funkcja
Dla dyskow oblugiwanych przez driver hd.c mamy zdefiniowana nastepujaca
strukture gendisk :
Informacje o partycji dyskowej przechowywane sa w
srtukturze
outb_p(komenda, HD_CMMAND), gdzie Czesciej uzywane komendy dla dysku :
Przy skladaniu polecenia rozrozniane jest dla ktorego dysku ono bedzie.
inb_p(HD_STATUS) gdzie HD_STATUS jest numerem portu
Czesciej spotykane stany dysku :
Dzieki temu funkcja driveru moze ustalic kiedy dochodzi do sytuacji
nieprawidlowych. W przypadku wykrycia sytuacji blednej dysk jest
recalibrowany (omowienie rekalibrowania w funkcji driveru
do_special_op)
lub resetowany ( omowienie resetowania w funkcji driveru
hd_reset,
z grubsza polega to na odnowieniu danych zwiazanych z
dyskami w systemie i recalibrowaniu wszystkich dyskow).
Bledy dysku mozna sprawdzac funkcja
inb(HD_ERROR) gdzie HD_ERROR jest
numerem portu.
Czesciej spotykane bledy zwracane przez dysk:
Algorytm obslugi zadan do dysku
Schemat dzialania driveru dysku w systemie

Schemat pobierania zadan do dysku
Funkcja strategii zapewnia komunikacje miedzy kolejka
zadan a driverem urzadzenia. Ogolnie rzecz biorac
funkcja strategii
pobiera pierwszwe zadanie z kolejki i inicjuje jego realizacje.
Funkcja strategii wywolywana jest zawsze po nadejsciu zadania
do pustej kolejki.

schemat dzialania funkcji driveru hd.c
opis oznaczen na rysunku
Bloki oznaczaja funkcje driveru,
wychodzace z nich strzalki pokazuja, ktore funkcje sa wywolywane
numery przy strzalkach pokazuja kolejnosc wywolywania funkcji
wytluszczone numery ozanczaja funkcje ktore sa wywolywane zawsze
, chude numery ozanczaja funkcje wywolywane opcjonalnie
Funkcje driveru :

wejscie :
- drive - fizyczny numer dysku twardego
- nsect - ile sektorow nalezy wczytac/zapisac
- sect, head, cyl - adres na dysku od ktorego nalewzy rozpoczac
realizacje zadania
- cmd - komenda dla dysku ( czytanie, pisanie ... )
- intr_addr - funkcja ktora zostanie wywolana w najblizszym przerwaniu
od dysku i wymieni informacje z dyskiem.
Funkcja hd_out informuje dysk o zadaniu do wykonania i ustawia funkcje
, ktora zostanie wywolana w najblizszym przerwaniu. Dysk jest urzadzeniem
wolnym ustawienie glowicy nad poczatkowym sektorem zadania zajmuje
troche czasu.
Dlatego dysk informuje driver o gotowasci do transmisji danych
przysylajac przerwanie, ktore uruchomi odpowiednia funkcje obslugi.
W ten sposob czas nie jest tracony
Algorytm :
1. czeka (aktywnie) az kontroler dysku bedzie gotowy
jesli sie nie doczeka to
nastapil jakis blad nalezy resetowc kontroler dysku
(reset=1)
wpp
a) nalezy ustawic funkcje do wywolania przy nastepnym
przerwaniu (DEVICE_INTR=intr_addr )
UWAGA: w tym miejscu jesli przerwania nie sa ignorowane
moze sie zdarzyc ze przyjdzie przerwanie od dysku
i wykona sie funkcja intr_addr podczas gdy nie
przekazano danych dla dysku.
b) zapisac informacje o zadaniu dla dysku
outb_p(nsect,++port);
outb_p(sect,++port);
outb_p(cyl,++port);
outb_p(cyl>>8,++port);
outb_p(0xA0|(drive<<4)|HEAD,++PORT); OUTB_P(CMD,++PORT);
funkcja ta jest wywolywana przez
funkcje driveru uruchamiane w przerwaniach
w przypadku gdy dysk znajduje sie w nieprawidlowym stanie.
Funkcja
void bad_rw_intr(void)
bad_rw_intr sprawdza i reaguje na bledy dysku.
Algorytm :
0. zwiekszyc ilosc prob realizacji bierzacego zadania (++CURRENT->errors )
1. jesli ilosc bledow realizacji zadania wynosi MAX_ERRORS
(CURRENT->errors >= MAX_ERRORS, MAX_ERRORS==16)
lub proba transmisji danych z/do blednego setctora to
usunac zadanie z kolejki (end_request(0)) i ustawic
recalibrowanie dysku (special_op[dev] = 1 i rodzaj operacji
recalibrate[dev] = 1)
wpp jesli ilosc bledow (CURRENT->errors%RESET_FREQ==0, RESET_FREQ= 8)
od ostatniego resetowania rowna jest RESET_FREQ lub wystapil
blad odczytu sciezki zero to
nalezy ustawic resetowanie kontrolera (reset = 1)
wpp jesli ilosc bledow od ostatniego recalibrowania jest wieksza
niz RECAL_FREQ (CURRENT->errors%RECAL_FREQ==0,
RECAL_FREQ==4) to
ustawic wykonanie specjalnych operacji
(special_op[dev]=1 i rodzaj operacji
recalibrate[dev]=1)
int do_special_op (unsigned int dev)
wejscie :
- dev - identyfikuje fizyczny numer dysku
wyjsci :
wartosc zmiennej reset
Funkcja ta jest wywolywana przez funkcje strategii
hd_request jesli wczesniej zostalo
ustawione wywolanie operacji specjalnych (special_op[dev]=1).
Funkcja do_special_op przy pomocy
hd_out rejestruje wykonanie specjalnej
fukcji i przekazuje komende dla dysku.
Algorytm :
1. jesli recalibrate [dev] to
hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr)
/*rejestrowana funkcja recal_intr sprawdza status dysku (po wykonaniu
przez dysk komendy WIN_RESTORE) jesli jest on nie prawidlowy
to wywolywana jest funkcja bad_rw_intr
ktora sprobuje cos zaradzic : usuwa zadanie ktorego nie mozna
zbyt dlugo zrealizowac i ustawia recalibrowanie,
ustawia samo recalibrowanie lub resetowanie.
WIN_RESTORE - komenda dla dysku
hd_info[dev].sect - ilosc sectorow na sciezce
dev - fizyczny numer dysku */
zwracana jest wartodc zmiennej reset ktora mogla sie zmienic w funkcji
hd_out
2. jesli nie ma danych o dysku (identified[dev]=0) to
hd_out(dev,0,0,0,0,WIN_IDENTIFY,&identify_intr);
/*rejestrowana funkcje identify_intr wczyta dane o dysku :
ilosc sektorow, glowic, cylindow , max ilosc sektorow do czytania
przy jednym zadaniu
(identyfi_intr jest wywolywana do przy pierwszej probie realizacji
pierwszego zadania)
WIN_IDENTIFY - komenda dla dysku by przekazal dane o sobie
dev - fizyczny numer urzadzenia*/
zwracana jest wartodc zmiennej reset ktora mogla sie zmienic w funkcji
hd_out
3. jesli (mult_req[dev] != mult_count[dev])
hd_out(dev,mult_req[dev],0,0,0,WIN_SETMULT,&set_multmode_intr);
/*mult_req[dev] - nowa liczba transmitowanych sektorow przy jednej
operacji czytania/pisania z/do dysku (wartosc
mult_req[] mozna zmieniac przy pomocy
funkcji hd_ioctl)
mult_count[dev] - akualna liczba transmitowanych sektorow przy
jednej operacji czytania/pisania z/do dysku
rejestrowana funkcja set_multmode_intr ustawi
mult_count[dev]=mult_req[dev] o ile dysk przyjal wiadomosc o nowej
liczbie transmitowanych sectorow przy jednej operacji
czytania/pisania z/do dysku
WIN_SETMULT - komenda dla dysku by ustawil sobie nowa liczbe
transmitowanych sectorow*/
zwracana jest wartodc zmiennej reset ktora mogla sie zmienic w funkcji
hd_out
4. sprawdzane jest czy dysk ma wiecej niz 16 glowic jesli tak to
aktualne zadanie jest usuwane ( end_request(0) ) poniewaz takie dyski
nie sa obslugiwane.
5. po wykonaniu wszystkich specjalnych operacji (punkty 1, 2, 3, 4)
zaznaczmy ten fakt special_op[dev]=0 i zwracamy 1.
Funkcja ta restartuje kontroler dyskow. Jest wywolywana przez funkcje
strategii
void reset_hd(void)
hd_request
jesli wartosc globalnej zmiennej reset == 1 .
Wartosc zmiennej reset moze ulec zmianie w funkcji
bad_rw_intr
lub
hd_out
w przypadku blednych stanow dysku .
Algorytm :
1. jesli reset==1 to
reset=0
reset_controller()
i=-1
/*funkcja reset_controller() przez port HD_CMD zawiadamia dyski
o resetowaniu
i - zmienna statyczna wskazuje fizyczny numer dysku 0 lub 1*/
wpp a) jesli status dysku jest bledny to wywolywana jest funkcja
bad_rw_intr, ktora spobuje cos zaradzic
(w tym wypadku moze tylko zmienic wartosc zmiennej rest)
b) jesli reset == 1 to
wykonujemy funkcje reset_hd od poczatku
2. jesli (++i hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1,
hd_info[i].cyl,WIN_SPECIFY,&reset_hd)
/*hd_info[i].sect - ilosc sectorow na sciezce
hd_info[i].head - ilosc glowic dysku
hd_info[i].cyl - ilosc cylindrow
WIN_SPECIFY - komenda dla dysku
reset_hd - funkcja ktora uruchomi sie w najblizszym
przerwaniu(po wykonaniu przez dysk komendy
WIN_SPECIFY).Wykona operacje z punktu 2 dla
nastepnego dysku (i) lub jesli natrafi na
bledny stan dysku proces resetowania zacznie
sie od poczatku*/
d) /*funkcja hd_out mogla zmienic wartosc zmiennej reset na 1*/
jesli reset==1 to
wykonac funkcje reset_hd od poczatku
wpp po zakonczeniu resetowania wywolac funkcje strategii hd_request
ktora przygotuje realizacje nastepnego zadania w kolejce do dysku
fumkcja strategi dysku
Funkcja ta pobiera kolejne zadania dla dysku i zawiadamia dysk o zadaniu
(funkcja
void hd_request(void)
hd_out).
hd_request wywolywana jest gdy przyjdzie zadanie
do pustej kolejki. Dopoki kolejka zadan nie bedzie pusta
funkcje konczace realizacje zadania
(funkcje wywolywane w przerwaniach)
beda wywolywac funkcje strategii
Algorytm :
0. sprwdza czy zadanie (globalna zmienna CURRENT) jest wlasciwa
(numer urzadzenia w zadaniu i blok do/z nastapi trnsmisja danych)
1. wyzerowanie zegara dla przerwan (zobacz zegar dla przerwan)
2. sprawdzane jest czy nalezy zresetowc dysk ( globalna zmienna reset)
jesli tak (to znaczy ze w czasie ralizacji ostaniego zadania dysk
spowodowal jakies bledy) to blokowane sa przerawania i wykonuje
sie funkcja
reset_hd.
3. jesli nalezy wykonac operacje specjalne (special_op[dev]==1) to
wykonywana jest funkcja do_special_op
4. z zadania pobiearny jest numer sektora do czytania/pisania i ilosc
sectorow do obsluzenia w tym zadaniu
block = CURRENT->sector - numer sektora na dysku od ktorego nalezy
rozpoczac realizacje zadania
nsect = CURRENT->nr_sectors - ilosc sektorow do obsluzenia
nastepnie numer sektora (block) jest zwiekszany o numer poczatku
partycji ( hd[dev].start_sect )
nastepnie obliczany jest adres dyskowy :
sec = block mod ilosc sektorow na sciezce
track = block div ilosc sektorow na sciezce
head = track mod ilosc sciezek w cylindrze
cyl = track div ilosc sciezek wcylindrze
5. blokowane sa przerwania (cli) sprawdzana jest komenda w biezacym
zadaniu ( CURRENT->cmd == READ lub CURRENT->cmd == WRITE )
i wykonywana jest funkcja ktora przekazuje zadanie do dysku
i ustawia funkcje do wykonania w najblizszym przerwaniu.
np. zadanie czytania hd_out(dev,nsect,sec,head,cyl,cmd,&read_intr)
(najpierw dysk odbierze komende np.WIN_READ nastepnie gdy bedzie gotowy
do transmisji danych wysle przerwanie. Przerwanie uruchomi funkcje
read_intr, ktora wczyta dane z dysku)
Funkcje wywolywane przez przerwania dysku
Funkcja ktora ma byc wykonana w najblizszym przerwaniu pamietana jest
na zmiennej DEVICE_INTR. Kiedy przychodzi przerwanie od dysku
wykonuje sie funkcja hd_interrupt
static void hd_interrupt() {
void (*handler)(void) = DEVICE_INTR; /*pobranie funkcji do wykonania*/
DEVICE_INTR = NULL /*wyczyszczenie zmiennej*/
timer_active &= ~(1*HD_TIMER) /* zaznaczenie faktu, ze przyszlo
przerwanie.
zobacz zegar dla przerwan */
if (!handler)
handler = unexpected_hd_interrupt; /*funkcja ktora obsluguje
nieoczekiwane przerwania */
handler()
sti() /*przywrocenie obslugi przerwan ktora
zostala zablokowana
przy wykonuwaniu handlera*/
}
Funkcje ktore moga zostac wywolane przez przerwanie :
Ogolny algorytm dzialania funkcji wywolywanych w przerwaniach :
read_intr ()
write_intr ()
read_intr ()
write_intr lecz moze przekazac max tyle
sectorow przy jednym wywolaniu ile jest ustawionych dla
urzadzenia dysku (mult_count[dysk]) wartosc te mozne
zmieniac przy pomocy funkcji
hd_ioctl
recal_intr()
recal_intr
sprawdza stan dysku jesli jest on nie prawidlowy to wywolywna
jest funkcja bad_rw_intr ktora probuje cos zaradzic
opis uzycia recal_intrw funkcji
do_special_op
set_multimode_intr()
do_special_op
indetify_intr()
do_special_op
I. funkcje realizujace zadania czytania, pisania.
Algorytm :
1. czekaj (aktywnie) az dysk bedzie gotowy do transmisji danych
(stan dysku DRQ_STAT)
2. jesli dysk jest gotowy do transmisji danych to
przekazuj dane miedzy buforem zadania (CURRENT->buffer)
a dyskiem
(
outsw(int port, char *buf, int ile_bajtow)-wysyla do dysku
insw( int port, char *buf, int ile_bjatow)-pobiera z dysku)
wpp jesli dysk nie jest gotowy do transmisji danych to
(cos nie poszlo) nalezy wywolac funkcje bad_rw_intr do
obslugi bledow dyskowych.
3. jesli sa jeszcze zadania do dysku to
wywolac funkcje strategii hd_request, ktora
zajmie sie realizacja zadania lub wykona operacj specjalne
ustanowione prze wczesniej wywolana funkcje bad_rw_intr
II. pozostale funkcje
Algorytm :
1. sprawdzaja czy komenda wyslana do dysku (przez wczesniej
wywolana funkcje hd_out) zostala wykonana
(pobierajac stan dysku funkcja inb_p(HD_STATUS))
2. jesli stan dysku jest prawidlowy to
wykonuja operacje, ktore maja wykonac
wpp nic nie rob, dysk nie wykonal komendy wyslanej przez hd_out
3. jesli sa zadania w kolejce do dysku to
wywolac funkcje strategii hd_request
Struktury danych pisujacych dysk i funkcje Inicjujace
struktury danych dyskow uzywanych przez driver hd.c
Struktura do przechwywania najwazniejszych informacji o dysku.
Tablice
struct hd_i_struct {
unsigned int head, - liczba glowic
sect, - liczba sektorow na sciezce
cyl, - liczba cylindrow
wpcom,
lzone,
ctl;
};
struct hd_i_struct hd_info[],
struct hd_i_struct bios_info[]
przechowuja informacje o dysku sa incjowane w funkcji
hd_geninit
, ktora wczytuje dane z BIOS-u
struct hd_driveid
zawiera mase informacji o dysku miedzy innymi posiada te same
pola co struktura hd_i_struct. Struktura hd_driveid rozni sie tym od
struktury hd_i_struct ze jest wczytywana z dysku.
Tablica
struct hd_driveid *hd_ident_info[MAX_HD]
(MAX_HD - maksymalna liczba dyskow obslugiwanych przez driver hd.c MAX_HD=2)
przechowuje rozszerzone informacje o dyskach.
Inicjowanie tablicy hd_ident_info w funkcji
identify_intr
ktora jest wywolywana dla kazdego dysku przed realizacja pierwszego
zadania.
Kazde zadanie do dysku ma liste buforow z/do ktorych nastapi wczytywanie
danych z/do dysku. Wielkosci buforow w zadaniach dla kazdej partycji
sa przechowywane w tablicy
int hd_blocksizes[MAX_HD<<6]
(MAX<<6==128) hd_blocksize[] jest inicjowana w funkcji
hd_geninit.
Dla kazdej partycji wielkosc bufora w zadaniu dla niej wynosi 1024 bajty.
Struktura hd_struct opisuje partycje dyskowa
Informacje o partycjach dyskowych przechowywane sa w tablicy
struct hd_struct {
long start_sect - sektor poczatkowy partycji
long nr_sects - liczba sektow w partycji
};
struct hd_struct hd[MAX_HD<<6]
gdzie MAX_HD<<6 ="128." hd[] poprzez
numer drugorzedny urzadzenia. Przypominam, ze 6 najmlodszych bitow w
numerze drugorzednym to numer partycji, 7-my bit to fizyczny numer dysku
(8-my bit jest nie wykorzystywany). Dzieki takiej organizacji numeru
drugorzednego tablica hd[0..63] zawiera partycje dysku pierwszego,
hd[64..127] zawiera partycje dysku drugiego. Tablica hd[] uzywana jest
w funkcji strategii
hd_request przy tworzeniu adresu
dyskowego.
Tablica hd[] inicjowana jest w funkcji
check_partition i
extended_partition.
Proces wczytywania partycji dyskowych jest omowiony dalej.
Dane o typie dysku przechowywane sa w specjalnej strukturze zdefiniownej
w pliku genhd.h
Dla wszystkich typow dyskow w systemie tworzona jest kolejka
struct gendisk {
int major; - numer glowny typu dysku
char *major_name; - identyfikator typu dysku
int minor_shift; - liczba bitow jakie nalezy obciac w numerze
drugorzednym aby otrzymac fizyczny numer
dysku
int max_p; - maxymalna ilosc partycji na jednym dysku
int max_nr; - maxymalna liczba dyskow obslugiwanych
przez driver tego typu dysku
void (*init)(void) - funkcja inicjujaca dane dysku
struct hd_struct *part - tablica partycji dyskow obslugiwanych
przez driver
int *sizes; - rozmiary partycji
int nr_real - rzeczywista liczba dyskow w systemie
void *real_devices; - wskaznik do tablicy z dnymi o dyskach
struct gendisk *next; - wskaznik do nastepnej struktury gendisk
}
gendisk_head struktur gendisk
static struct gendisk hd_gendisk {
MAJOR_NR, numer glowny MAJOR_NR==3
"hd", nazwa
6, nalezy obciac 6 najmlodszych bitow w numerze
drugorzednym by uzyskac fizyczny numer dysku
1 << 2 MAX MAX_HD, DYSKOW MOZE 6, 64 ZAWIERAC HREF="#HD_GENINIT" DYSK LICZBA PARTYCJE JEDEN hd_geninit, funkcja inicjujaca dysk.
hd wskaznik do tablicy partycji dyskow
hd_sizes, tablica rozmiarow poszczegolnych partycji
0, ilosc urzadzen wykrytych w systemie zostanie
ustalona w funkcji inicjujacej
hd_geninit
(void *)bios_info informacje o dyskach (ile sectorow na sciezke itp.)
NULL nastepny geninit dla innych dyskow
zostanie ustalony przy rejestracji urzadzenie
};
Funkcje inicjujaca dane dysku
Funkcja inicjujaca podstawowe dane dysku
void hd_geninit(void)
Algorytm :
0. sprawdzic ile dyskow znajduje sie w systemie i zapisac w
hd_gendisk.nr_real
1. pobrac dane z BIOS-u o dyskach i wczytac do tablic
Rejetracja dysku w tablicy urzadzen blokowychhd_info[], bios_info[]
2. ustawic pierwsza partycje dla kazdego dysku.
Pierwsza partycja obejumeje caly dysk.
3. ustawic funkcje ktora ma sie wywolac gdy przyjdzie
przerwanie dyskowe HD_IRQ
request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd")
4. zarezerwowac porty do komunikacji
request_region(HD_DATA, 8, "hd") - zwykle porty
request_region(HD_CMD, 1, "hd(cmd)") - port uzywany do resetowania
5. ustawic rozmiar bufora w zadaniu do partycji dysku
(tablica hd_blocksizes[]).
Dla kazdej partycji (1024 byte)
unsigned long hd_init
(unsigned long mem_start, unsigned long mem_end)
Parametry wejsciowe mem_start i mem_end nie sa w zaden sposob
wykorzystywane. Funkcja zwraca mem_start.
Alogorytm :
1. zarejestrowac typ dysku w tablicy urzadzen blokowych
register_blkdev(MAJOR_NR,"hd",&hd_fops)
(MAJOR_NR - dla omawianych dyskow wynisi 3
hd_fops - wskaznik do struktury file_operation dysku twardego)
2. ustawic funkcje strategii dla dysku
blk_dev[MAJOR_NR].request_fn = hd_request
(blk_dev[MAJOR_NR] jest struktura blk_dev_struct, ktora
przachowyje kolejke zadan do urzedzen blokowych i
funkcje strategii realizujaca zadania)
3. wstawic strukture hd_gendisk do kolejki gendisk_head danych o dyskach
4. ustawic funkcje hd_times_out by byla wywolywana w przypadku
gdy dysk zbyt dlugo (0.6 sek) nie przysyla przerwan.
Wczytywanie partycji dyskowych
Wstep
Kiedy system startuje najpierw wywolywana jest funkcja rejestrujaca
hd_init
(wywolanie w pliku main.c)
nastepnie dla kazdego typu dysku (kazdej sruktury gendisk z kolejki
gendisk_head)
wywolywana jest funkcja
setup_dev, ktora inicjuje dane dysku
i wczytuje partycje z dysku.
partition.
Dla kazdego dysku pierwsza partycja zawiera caly dysk.
W bloku zerowym pierwszej partycji zapisane sa 4-ry struktury
partition opisujace partycje glowne. Kazda partycja glowna typu extended
dzieli sie na partycje logiczne, ktore nie maga sie juz dzielic.
W bloku zero partycji extened zapisane sa dwie struktury partition.
Pierwsza opisuje pierwsza partycje logiczna druga zawiera informacje
(wskaznik) umozliwiajacy wczytanie bloku z danymi dla partycji drugiej i
wskaznikiem umozliwiajacym wczytanie bloku z danymi parycji trzeciej itd...
struct partition {
unsigned char head; /* poczatkowa glowica */
unsigned char sector; /* poczatkowy sector */
unsigned char cyl; /* poczatkowy cylinder */
unsigned char sys_ind; /* typ partycji */
unsigned char end_head; /* koncowa glowica */
unsigned char end_sector; /* koncowy sector */
unsigned char end_cyl; /* koncowy cylinder */
unsigned int start_sect; /* sector poczatkowy partycji */
unsigned int nr_sects; /* liczba sektorow w partycji */
};
Algorytm wczytywania partycji
void setup_dev
(struct gendisk *dev)
Algorytm:
1. wywolywana jest funkcja dev->init() w przypadku omawianego
dysku jest to funkcja
hd_geninit
(hd_init zaklada pierwsza partycje obejmujaca caly dysk)
2. dla kazdego dysku inicjowana jest tablica parycji funkcja
check_partition
void check_partition ()
(struct gendisk *hd, unsigned int dev)
wejscie :
hd - struktura gendisk opisujaca typ dysku
dev - numer glowny i numer drugorzedny urzadzenia
(numer drugorzedny wskazyje fizyczny numer dysku i
pierwsza partycje na tym dysku, pierwsza partycja obejmuje
caly dysk)
Funkcja check_partition wczytuje cztery glowne partycje
i dla kazdej glownej partycji typu extended (partycje ktore zawieraja
w sobie inne partycje) wczytywane sa partycje w niej zawarte
Algorytm :
1. z urzadzenia o numerze (glownym i drugorzednym) dev
wczytac blok(1kB) zerowy (funkcja
bread)
w bloku tym znajduja sie struktury partition
opisujace partycje glowne
2. z wczytanego bloku pobrac informacje o 4 glownych partycjach
Informacje o kazdej partycji wpisac do tablicy hd[]
Dla kazdej glownej partycji typu extended wczytac partycje
w niej zawarte funkcja extended_partition
void extended_partition ()
(struct gendisk *hd, int dev)
wejscie :
hd - struktura gendisk opisujaca typ dysku
dev - numer glowny i numer drugorzedny urzadzenia
(numer drugorzedny wskazyje fizyczny numer dysku i
glowna partycje typu extened, dla ktorej nastapi wczytanie
partycji logicznych w niej zawartych)
Funkcja extened_partition wczytuje parycje logiczne zawarte w partycji
glownej. Numer partycji glownej i dysku zakodowany jest w numerze
urzadzenia dev.
Algorytm :
while (sa jeszcze partycje logiczne) {
1. wczytac blok zerowy partycji o numerze dev
2. z wczytanego bloku pobrac strukture
partition
3. ze struktury partition wczytac dane o partycji do tablicy
partycji hd[]
4. pobrac nastepna strukture partition z wczytanego bloku
bedzie ona wskazywac na nastepna partycje.
5. jesli pobrana struktura patition wskazuje na nastepna partycje to
a) ustawic tymczasowy poczatkowy sektor nastepnej partycji,
(na podstawie wczytanej struktury partition),
posluzy on do wczytania bloku zero z nastepnej
partycji z wlasciwymi informacjami o tej partycji
b) zwiekszy wartosc dev by wskazywala nastepna partycje
wpp koniec petli
}
Struktura file_operation dla dysku twardego i jej funkcje
Funkcja
ioctl dla dysku twardego
wjscie :
inode - wskaznik do i-wezla
file - wskaznik do tablicy plikow
cmd - komenda
arg - przakazuje/pobiera parametry pracy dysku
wyjscie :
0 w przpadku sukcesu wpp kod bledu
Komendy (cmd) i ich znaczenie :
hd_ioctl zostala wywolana.
block_write , block_read)
hd_ioclt
hd_ioclt
struct hd_driveid hd_ident_info[dysk]
Funkcja otwierajaca partycje dysku twardego
int hd_open
struct inode * inode, struct file * filp)
wejscie :
- inode - wskaznik do i-wezla
- filp - wskaznik do tablicy plikow
wyjscie :
0 w przpadku sukcesu wpp kod bledu (proba otwierania partycji
na nie istniejacym dysku)
Alorytm :
1. sprawdzic czy dysk nie jest zajety wczytywaniem parycji
jesli jest zajety to czekac gdy parycje zostana wczytane
wykonywanie funkcji zostanie wznowione
2. zwiekszyc ilosc partycji otwartych na dysku.
Funkcja zamykajaca partycje dysku twardego
void hd_release
(struct inode * inode, struct file * file)
wejscie :
- inode - wskaznik do i-wezla
- filp - wskaznik do tablicy plikow
Alorytm :
1. zapisac synchronicznie :
bloki, i-wezly, i super_blok partycji
2. zminiejszyc ilosc parycji otwartych na dysku
Struktura file_operation dla dysku twardego obslugiwanego
przez driver hd.c
static struct file_operations hd_fops = {
NULL, /* lseek */
block_read, /*ogolna funkcja do czytania z urzadzen blokowych*/
block_write, /*ogolna funkcja do pisania na urzadzenich blokowych*/
NULL, /* readdir - bad */
NULL, /* select */
hd_ioctl, /*ioctl*/
NULL, /*mmap*/
hd_open, /* open */
hd_release, /* close*/
block_fsync /*ogolna funkcja zapisujaca synchronicznie
bloki urzadzenia blokowego*/
};
Zegar dla przerwan
Dysk jest urzadzeniem pracujacym w przerwaniach. Zatem jesli
cos sie zepsuje w przesylaniu przerwan bedziemy czekac na przerwanie, ktore
nigdy nie przyjdzie. System radzi sobie w ten sposob ze ma zapisane
w specjalnej strukturze ile czasu uplynelo od wyslania polecenia do
dysku, po jakim czasie ma zareagowac i funkcje ktora ma byc wywolana
w zwiazku z nie przychodzacym przerawaniem.
Czas wyslania polecenia do dysku jest zerowany w funkcji strategii
(tuz przed wyslaniem polecenia do dysku)
hd_request
i zerowany jest po przyjsciu przerwania w funkcji
hd_interrupt
void hd_times_out(void)
Funkcja wywolywana w zwiazku z nie przychodzacym przerwaniem
Algorytm :
1. zablokowac przerwania
2. ustawic resetowanie (reset=1)
3. wywolac funkcje strategii hd_request
, ktora sprobuje odnowic wspolprace z dyskiem
Bibliografia
autor : Mariusz Rokicki