$f\yb侠bo1mݓTb4{wGCvP)^mhHЅmC+P8q {8GHτ-fzV ::$)}1ߞkS7,ЪDՄ^IZhLN{i@Roi&6';gcePk4?J3[oy#ئħqcib3uۼ`c K*!vWHu@li1PWq0HatjE%Edt%@7W H"ڎ]'5#]幪4ɹi[MZBx|?h}Ye3@j_E_-¡bLa$&s1zT GX蝸ĖU /WMN g]c79ZΔr/:{O`J c4 ֔]pD4lVG#Y(/ P\8ӛw)űu8#[Kw0@\ 0C$Io(uO=h^~Yamtp'+; Isג%F悡M~5:L5񘯹by _M;Tz`ֈC(3dRvF\AVA苤f[3r[ġ5hKLfCJy}"`5)4`>+.(c}bFt G?ءGZt1Do8X.8r`Z8 cGQEk#qo˪Cr&-Py0U1%0żFxǪ*t5Cnuh?} r#ZD7 D_絫v2+{Ðk&jAѢ֥j W@=#I'z!(L"|yCc61`x8mX .< xBzS s?'5VkG} {)#Wa!SMsљ6¨~" t?דxΈ<&I=e:'KJx`'C$fQH E| 9lpbOL*0L#:ŨD%˳֙vQMQ'@be_mQϬ>aTrO8X^ FE}՚^y=[ 9 n~do_@Fh huD}1ayђzp;-~ayqPjJ ;^5`[6qҪCtO2t JGx**БK%96L :Ҳ6/buzD򆷇p97Hlku.C=~FTN7XV72a׆o^=udkGonlm;7ȾfC=؅6U  DrETN3>qxc:Hl_9 &ҿ@q ܟU"CW5j3| 3X'gIr ғQKk\.0G]wƥ6a'JEj8j[󧾧/0Y]uY;}5}!o 1B{47`U4[jvbLrFމ?9QntF{[ErCav4xJ[Gj!$r!چ>–Q keNۥ"U%N%2F 5XQP.s9 '6Y{QsI;iR dy=9HF2[^RݓV}ytz @K[B@2@Ŵ3&y;vf"n-t:oR`gQ<_L ` -6GfC!b?Ѭ7%% z[2) ɨЁfLS#DRg T~Y՚n#H'&d'.kyև8W잜?^Yh fywn;]_#0p p(m V l=E]vzvP\3~fzlyvb19GscRW6h ]D(i( kΐd\:f3&do'sD|=N ":(`)`)2"^&=Ù^nEƩAz2vl6PAxX!>5j=Rf(9W@C .<{dP}<69Y;t8֭'PG{B9{[1Ht6WO=Ɛ YN5 km&2b1~ӿhfRcsɮ&`,g2Ct ',z,g1au ;> c}#wA5NAy2r]SsYſJ}FhK64V;-7xD!!c_y`& v8g0Ѱ|.DKTJ>|-w|?fͤo0p9w38BɂwKWE jbIhܟ'€";z˔5+FbVvJ/lJgېQ`=G2@RE 6k>c]hN{ L`\_RĞ05S{9@:*'.- V \?.q(1XM2 %!bAoN>c h9*燼hw?xfr&M L|"9CAC(ٯ|gz_;;f'mioZ$aH;!VwAt/<)}2$ga !?_TAH1j=n,t9YB[RctSv [JLzOY+cs4sAH=Bwpt%IKo׫]ewJfTe#MDC|!<#72ۧ,-fPP"Fxtq7Vm<6AA›AR0ƽ+BAVg-b>"CL;RLa_AY2pfx1kX=nrx̻]Y;[F{[0#@AL%aCX Û(M/kRˉ^3f#.K{L]]dRפkz:ki4H;{IVq> 2d&~KԥmHyGPfhW6&G鸲(]ϼK!={kqid333*a@ŕ|A+BLUvwlB;5Vs#΍k\lst;2Ѹz9$P ~r7ߚSz)aNdv XD5N2o"ĴkѓGb#A:$ GńX-T/&D5j1{mB}˰_ R%8WcڳpF΁x) Ct0DjJ_}kP oWNB9"6v}FW}dN6]! v?*$#-"1kq$[ڤ_\!t6+:ǡzO0^b_Ò ~Q2Yp/I-_*)h'GLl~ÃV'ٌKrH(d%[ZnȽVRBnqBK7G C:SFZTC#h ;&+B)cɈzO֕ɡlk}ee&ChA&f+O e;s9׋GzpeUݵj'6![/DpNQX3UtofіZtzSN§'QDt !!V՜y*p`gSH?q7{@}`it (DhkR67HqsIjKH p ~Bk> [˴3Yuxb;z&ٹu]rL ZBK΍Y!ފMLj1KP*Z-^z&:y&KF' mҐ1H*&w7ɓaz'+].ObaxWi$;;^M/gbOcN1UU_!tG>MMT"Tdͳ`pBf3 waYF֙$y\rrPC]6a]a{hwxSWU^G')B +2ǰ`~5ZF ~ť!I5uUtΙ,ǽsoܺ>` U^)T-+6>\DQ˫I^Ɲ6;qX~En}ro<[Al{+)Fe'/5s[~3)2tP/Et±9 +(T]FL793"u==q!+Ԧec %aHTd?^4atTrNr]\atnRD!Go ]Rl#/P">GsԻiGҥڊHFe-Q JDUZYC}6.Ec )WFh>uxqqY*?FȪҖRƐ(`Lis_O ?gҎ 㼪#rPҀx3z" ktuC+*bveDx;smAgۆVaHI1?%ZV>7"<6e3h癐,HEE߷0".hlAi\bF<Rﳑ ?(zTUVGSWQ85!vo4В!ܥrYr3r:|T_qA_f>`,A 1p =a܇I[zɺ}={ uU1A K"'XɁAױF;8nK-^FQ7U'J\%w^'"^ʚ'KgzZ y53333eYYYYIII999))),)))*)))))))%y +:łT$MM_~5^P|XM^P4XN6B RD(ONJ r21r228+CC2k$ۼWWi^{~~~qx-g 9 q1aۿѱf͛6|6lSX\ n( 3iM+RNMiU;7775Ob ?&,d8E &mLM}dDrZkMX]tZZH >CgD`oYKo}<tIǍTM4ٶL0̹Wa]pwlm 8لo?*"-5 KI]}8;Gq5W}LQ`|B}DY(j) :]IE}t(TRf x\a& $ZD$ =R)r<ɊM 2@W b!oUZ7-ǭdO7)W-ux[\Ple^i*?#X{VSijؽ6Z{n(vHq=|x.3Lhpr9{^.ֲ-vaσ^lZli+ ~Y* Tjs 74 % + oZ4MzBZuR)~~ۺL&Pά:\Jfm̽ԻZ‡2/`gݦk;@<TTD2D; ( խFI%fb_%;T؊,m@ +uZeZjXb%9=zjs~8dZĵ"\fujW^2."_%&m`j9G|5bcFlfpNMx_0U&k85le:=HH΍oi2Ӷ ;#3X0IVDAq P\x6c(7i(E0[l%= zc_yc@rC1jqߎ Qތ  D*48G ɴyDM* O4p~2+3^p-q3 n_hfXKSunqkjA@CD٧ CPq{'a(!ni'% {" NL=\եܡgpe!nh5⌦ ߩh}S `"۟#hf1O1J1"A0z4;w 2,B0Fd/F"~. {\nZVA=A <\!grLGri߻j7;3[.jŔi@N kL+ptcw<bX#Wfm GqǷgYc6XPͧP3X6qˊA@ am. sϟif>)ɧ[1U5mzuh= ytqzi<g('O˒U } /kl_ys_O NXm}aTc9kfd=å(*K ]Jc`zK)ÝxW}l;D. .&d8c@d7(4%i"d'ˇ )P4;7`uODPp2&8nNQd93fXPfqfbs]}59v1\[ ?]츥LۊB5L-fÀU:- gej8ZW0s"1 iӇ%rɍ3s{ ,t}Fm6 H-9#mj(fq7E*6B؛^gG@})ns6CBw Cl@U8iMb,)^ADCG`ݲJTQدk'kTNr&=>r ıp.UĿ1UG|55T*c>[ ru b "(aCwG3`xƒƾ%)|{36Gxl,4G#u|`PqJ$t%;hPtlsf sDM^.p~m>ve 9}5d+٪~c\xo `Zc?54:]TN-_Isft+SZRXO3t0GG%V6fg"VBNJ\U=Mv{%O;}zHƄІ_7ZA43輚L*es1w`%/7p(I]%4LuQ<jt]BJMgO$^jNPq.0 x6z֝j;*[yHHj5!/1TH-r 6w4;87Bv'Nm?v)˴d6 oThw UHIq"32f̭`Zx4k0=6ӥBj| vjKd̓4Y\zS<-DHOQt#b{\1.}l pYp蠞egD3YZFY AoF>| cQ%mR `UU0m_př^UNARJWpvAYA|WYsj3V2#]n^=/'{!ђ0L)t+?7n(5Ӵ)L<#ܙ:b*GXDn\x0{ɟO50xKL5S{ 'vK)h($L =4*yIl'UgT{1~{NruNu@^d +!|\+ {bLnw|O/_Gh#޳2=qpn}tFƎu|gG]s70b5l(@֒pt O@Z?Y-2 BŔfoi -OLl8L(} i]h̚DH!*q{ssbe;- ‡{|Ow|#G:ܭ+G="gN 'Wk4W%QKw_=2**MIX+amd1yhe/ʿVƾְo˰.LVaDB%%Pʂ)F"~j,`wrׅ$Pu[ ~r! ӃS i*K7y9ݘ{y@'y4ܩOrCi( ;$\^ Feg|Q!e "~HZ}ӴSHx>6y?rNUMY?~fZ&(>MzI_n:  8Kc6P-2b,8S:~#%(:/;y`sd]|zHΖcܣ!{ի!kWy$ }kVViE_e`|-H]z*ՈP;HiD"x-L@ ƽϥm`7T E>m:IGfIT؜@WD+<D/?*vRU'R!3mq;Ss:[ңHOPH_fBPC|:9~%/ ~KY1&v;}/N P@z?=Qd1py ŰVoUq#"u#U#]TX#t/|9G^ [KjkH!R iiqPTه;ҝhhf#]ȽFsO}Xݵ6HX2}IxT0zz#(A ~+Oac}UWZw4ޅI;|Y kC1p@bק5zƅц;#[MQ}'ZLha~%vzwD{LzK~#z;Ȉ\( iu#G}z*d(8 Bp3s'Y7n?8@=ޤ nfȫ9xZno 95%qKFf,.Ud/dHz2l0K0aB++9Y&E+[_څtIH_0htƫiluBxd+9D"1n&a/{9B ~BJB:%Zirt$?d@Y`6Έ9WSI@k^ƀmiBfF7֦L1AC,:"\E` 4?׎6ȈyIU 5\Y2:;|U)@"H|N!hT|*Փx8)b*O}hf6H[ ةCΞ2:ȁ ~-qNp*_`}((4+`J7RҌuM. A[7+;?z OkSmw^Hr{r5ܕoB7?0+V1};țmUN !,gU%Q^qpB=_T xM3b-]Wc tP_C3 d` P G}ԨvI؋.(WHYCRYCKp>#YczHC~FB>uxqq[cz99M!L&6}0c=ְЂ6Fx It$R64"KWGYĝ\~7E{U^|09 [z)xh7=m6KxM8Z.3\8)DQ!lAuPeK>UƧFV[h\44)HA$1sRASAw/k5 r0ќ,-Y/e&G8*ykFm :`61+^Z+ )8 ڵr<`0cA{t*5 Ve5\Exҭ=is/ WJ)il6`TCK8LjEd2*wo3Er3iwpT s5-~`2lmDJ25ۖ)v\Ͷ,v3k ũkrk̓v'eZ 9!Po0op^Y:ԡӗ2DCW%ZV>>͍"%7~5{?N PƼ1*(uӀjn"> void hd_request(void) Funkcja ta pobiera kolejne zadania dla dysku i zawiadamia dysk o zadaniu (funkcja 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 :
read_intr ()
wczytuje dane z dysku
write_intr ()
przekazuje dane do dysku do zapisu lecz tylko po jednym sektorze przy jednym wywolaniu funkcji
read_intr ()
podobnie jak 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()
funkcja ta jest uzywana przy recalibrowaniu dysku. Najpierw dysk wykonuje komende WIN_RESTORE nastepnie 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()
ustawia nowa liczbe sectorow transmitowanych przy jednej operacji czytania/pisania (read_intr,multwrite_intr) opis uzycia set_multimode_intr w funkcji do_special_op
indetify_intr()
pobiera dane o dysku z dysku jest wywolywana przed realizacja pierwszago zadania opis uzycia w funkcji do_special_op
Ogolny algorytm dzialania funkcji wywolywanych w przerwaniach :
   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.
struct hd_i_struct {
      unsigned int head, - liczba glowic
                   sect, - liczba sektorow na sciezce
                   cyl,  - liczba cylindrow
                   wpcom,
                   lzone,
                   ctl;
};
Tablice struct hd_i_struct hd_info[], struct hd_i_struct bios_info[] przechowuja informacje o dysku sa incjowane w funkcjiF+ h Z3ڒ{odUvkk۰y!+w.ߥ؝m;&>'"/f.]Ow9Sb.M! L C~we|&cluO.Ӌ¤J=T?ɋ3 Auo5hrB>*6yABˡ.?Ͷ?^lcWe$9><$*gIOCFR96mT(=8[`B|:'r}Xq]C욃V^l !GB>(82MF{v7zp*ϷRA/Il5?5F[WZQ{Bkƃ!6[ {IkЀO>H 8X#o0sB!d^,}4Oׂ*_x2Θ+y+SxscmHBD/i/qy?G){myz\PDlg"qBi?!MW9 jpQ#"AF{E7.2] رڢȪFd°D.h4Ky'߀؟u0*Ed6VsVS5nE鰩"̦va=km0x_ϭνjG"|r{,md˛"U4_."0JŒcHuB ¿; +EBA-bE3 K XԨ.1 M$^w\6ڤ5-!$1=%%X=73r<}xz23 4.ۡݩnB}]`nĝsS-8pVMVM)2u+лo~R&1C`@a[C5Eͷ9քEg܊lEm~:cl4/{+ Txire/;Qle>%a\OWBg}Ɓw \7z==l~^)p/se9愺XFZ\y7DfH-:k>pjt-d [*{UN9~N/UV֋'%fǻ뱜^sar7\D?sZx'f4.;LbdLlݝdVf&P>PRjutv&@v&)`*[@o>+Ww7HxGǃW {pdD,m -kFAtZH9PFmݟOse vsزʸorLfLd-'O![F3K. cہ B4$+تe5I$$1l%H,f:w4`A# ?uf Fž-KfVg*Ɋ X ֋MTՃiŊ;<*y7u~$60<uxZz^+Mְ',/nԉ7%[>8+Q\/J-Fчw<.j9/\ݶL! CE!; 8@albh-&{PCTsm ]w2]*o~(SU;~w\Az1tSԹv !ROц䝈$^ ^ - d$!'Z!AD KvڹrvRݼqjs'n7rDSìhWE xٺ4~F&KQ ,ړX$85k l 4(V_$<Ȇ[C-wϺnc[2?o)mP ]Z )γCg}Ul~2c*{p[T-|t(l1$ƣb)`5ۅJ*Q2A\݂ޢq;n%N& q Y"XPS&j락]oU3ap—XMT"Z5]p$kƒff+:lїC4SIsqehE{j<ƥQEQ𥳛#J*TR[R'$<1rvݿߧП?ܧN{MIT՜2dɕjիVZjիVZjիVZkׯ^zׯ^zիVZjիVnݻvlٳf͛6lٳfͻVZjիVZjիVZj*W.atӧN:t8pŇ5jyߢ* ,jJ[^;Y{덍@?fhж9l5ۖ- ҿhn1!(idsMU"8roX MRQAhHWo7tJKN[cpq'3xI:}_* So/5. Rl:_5m\sXrbqQ2kW0&jNƜtեb{`f8)6ci]RXSSیމōc1q󹜨 Uiʯs )-We~n^ɴY3Tkb]N-TW4f@'fmUblH3EX(O'MyI˦8$lUh%aGh{)f_UR&Eçқ|{l.mK. [+75=*: *xPx J8qsteSOUupsY]W:u%cYRΫQu\sUΫW:u\'J‡6oԫ:oPFН>tbJXĕd%98rV 3Y1a¦ug5\BH[\u=Fr[ w^Jg0KhRP,y>r*hʜS$\VA)1ZDGHHi3z %yJrzɝLlʵHSUP0Cbg [[K }Tיve˼x9.Rma3+wo ?eƆo~\OƯFZ"$_[;cѭql9G 7C.օ\^n5ʈʙcbiKT?Fbffn*rqlfj,Ll˗^2zU ZZ7ϜF82 *[33iL|ŅLwfSJwXY6#K\/P~[{E%/'}u9{AM{m qgckummQs@ȝ=*l-읮WSYnSezZ֜.OCB9Ƃ823& Y71e%F!c[ff̩[I7Z6+X_kIH'yUm9#ckIs;;yfe32oKQκ;:/;Fs='' 쌃U#e&D¾u%/_!Fc4Ν?^a}G[u)K^u |x`iީ(7 н3˯]Uj׬웞_%~[7FTdJOIYXcDTS0L<,ekHI\Z&gcOʯZ=U<܍W^oF'zwWw\3jɾk\5_{'6[*=i̫[~gS{W31Q|rgah2_ћN܋[2(8kHvvuΪ/=M " Z20VUu;Gec|ˊ(j(L,tU}w5VJ"O>l2 uU305ܿr0̐m} ۚ[W,L\SӻW4tjZh ee$+)&jG?+;54ڇ|4+xtZ=g&9?s ub!\Rj8f."O./=2~wI6^SHǿ<¹VZ: H x&?+ 93E_mue; Fplk*xXmmUܐͭG8أt_sݾةm]e']b8eP]=fXco vn]ԯfU[z_4عWJle&$PV=:3=Sޯ]pUA o-/PYg7v#cJDi\=vgI4~4zQ_/?#SsCvS+5ZUTOXU^UQlf$~[Cw"V˅ؑDHaVsT̿OȳZ{\·lc{z{|k/}]9YIi_ [Æwkjqoggkn+-[}ܽCuks_S[ڊhS ~&_לz/gnkNwT[Vm=\ es;Zdkfv~ntQTj rm͟歝ٶfT5S=[Y+YUvwQܮcswecZ+G;NlwjI{LV:!940,Xx'.oiylE]^ntbS ֯ngvm % %hY3L^på &rEAO@ĈܐC=ka?h^ IRbH ?hi|q;jb5d?dR>1*~wd*{Ÿ' [1it<Ɵs]V!Șqå,tq҇ lRg@h4ێF.IQ͜- ab]zy0=iK2yup ( xHةL+\+qِxz{NgGVT 0̃S"Iz9{>U9DZ[Ew$*'w̥g. ؑ7|V3vÇ:gK;4xVw?cp QR^R=Q.L X!K3HwdNkCquLZĦ;z 5@rV$<-9B(ou2ob Wkݹp SvkkkUoKp"sd|gUKb{Og[9e5 S `<gB%;C[M@5¶>QQG̅EX]#ٷJ! KᦡI=AF98{ [q/B˄'F#h–z\" v`;fD,6@{>UMS^g^ǺՋΜy5Pk(2R\,3D=יx, ^ïY=sV6fٚ4QŎ_Ĉ*0dM ޭj`N3[^kK._#^8u 0m$6>tG}We=*[Ei62F /D{v$tl6nMx˞fѷBC{\ic8U6G%ԛ]%v(VpPڧ\?έQkA[) V\Oy(.X; pP;P]wAs"ypWUG}j33ӁkGv J'fKoQ~e\ɑw7fm46P/3ky>z4>+/ve;ӎ(r ]71,^Rcji */ }; 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...


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

int hd_ioctl
(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg)
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 :
HDIO_GETGEO
pobiera geometrie dysku sectory , sciezki , glowice i poczatkowy sektor partycji dla ktorej funkcja hd_ioctl zostala wywolana.
BLKRASET
ustawienie ile sektorow pliku nalezy czytac z wyprzedzeniem (wykorzystywane jest to przez funkcje block_write , block_read)
BLKRAGET
sprawdzenie ile sectorow mozna czytac z wyprzedzeniem
BLKGETSIZE
przekazuje rozmiar partycji dla ktorej wywolana zostala funkcja hd_ioclt
BLKFLSBUF
synchroniczne zapisanie buforow partycji dla ktorej zostala wywolana funkcja hd_ioclt
BLKRRPART
ponowne wczytanie tablicy partycji (tej opcji uzywa sie gdy dysk zostal wymieniony w czasie pracy komputera)
HDIO_SET_UNMASKINTR
sprawia ze przerwania od dysky nie sa ingnorowane w czasie wykonywania funkcji driveru dysku. (moze to byc niebezpieczne)
HDIO_GET_UNMASKINTR
przekazuje informacje czy przerwania od dysku sa ignorowane
HDIO_GET_MULTCOUNT
przekazuje wartosc ile sectorow moze byc wczytanych/zapisanych przy jednej operacji czytania/pisania z/do dysku.
HDIO_SET_MULTCOUNT
ustawia ile sektorow moze byc wczytanych/zapisanych przy jednej operacji czytania/pisania z/do dysku
HDIO_GET_IDENTITY
pobiera pelne dane o dysku z tablicy struct hd_driveid hd_ident_info[dysk]
BLKROSET
ustawia partycje tylko do czytania
BLKROGET
sprawdza czy urzadzenie jest tylko do pisania

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

  1. Pliki zrodlowe linuxa
  2. artykuly o urzadzeniach blokowych z Kernel Hacker's Guide
  3. M.Bach "Budowa Systemy operacyjnego UNIX"


autor : Mariusz Rokicki