hA@M#AL# c`L#  cL#dL#>9iL# !"$lL#,-R.pL#./012346C rL#;<=tL#>?@ABC wL#DEFqxL#GgL#HIJKLMNP(L#cdefghik L#opqr"L#stuvw 6L#xyz{|}~oL# L#~!L# L#`!L#;L#/L#(L#-L#=L#dL#L# L#A0nM#!M#e#M# %M#(M#=*M#-M#/M# 3M#e 4M#  d7M#   ;M#" =M#5@M# CM#!"#$%WFM#&HM#'()*JM#+y MM#,-.NM#/TM#012345m UM#678!WM#9:;XM#< ZM#=>?]M#@ABCF_M#DEFaM#GHx dM#IJKtfM#L iM#MNOPkM#QRlM#SoM#TUVWX...kernelfs...at_wini.c.Zpc_makefileclock.c.Zconsole.c.Zdmp.c.Zfloppy.c.Z const.h main.c.Z memory.c.Z glo.h klib88.smy_wini.c.Zmakefileprinter.c.Zmpx88.sproc.c.Zps_wini.c.Zrs232.c.Zproc.hsystem.c.Ztable.c.Ztty.c.Zwini.c.Zxt_wini.c.Ztty.httymaps.htype.hat_makefile/T&fҰ)b7t¤qs0 2r)#ᛎt0L"I T@ܙ8F:># r\(!0 aHb1 %o)3G'ϝ 2l:R?9HQ9 CE1lތYc *2w  |3 ʞmCuN3TYuǸsL<ӷMbބQghXQNeVMd ,S'0ay0b_z:"V )'C8Đ'Uɔ$TS@xFd9Pv>7Hgc?5\M@P8]t }6Q R}@ 2s)I+9e缒=0dR_"\2PRw8@ HbZ}a3aN iM0W7ԆpekBG Sbh A4h1Qx?Ņ /O`0$u`MkH=1d=_NxŞŠx І:| ~$cGb?0K 0 2|纨MpO62_A@  ̆` q[Ȅ/ y."JS LB K`X^U$2W4dpIh=|(+8' \HU~gjB.94=p_:J)}A3Tt71Rth.!"#@A"½PQ b DƹP B*-k~c\K%8P@Av!F*SS4c&!9rRjLT,U7M]I:Qi#WY7ԯҨ.N(P  u_u WcUb}\: |Br(%͚<d u֏d* y^ ҹj !&8S$ZKR@Z4tCee0| /թ%&/ќפ4/w0,dͥvӞ64s+^}% CFtC(:ԩB(2XGK:\]8Q<XUO+S_  F`\1 } 76cdH2 _(B  b!7rHؘer/ǓT2op$nR3(GxdDxd$Q`F {,% #پ9g [x%z."H BvO2='MJ[Ҙδ10RT}ZV6VՔq^)Q^ R= xbNM>!/v98 ;y4#i^*/#a:?k9UoI\~p|, tcsaaS@vy휌P%qb ZD,c/ ؐ F~*HP* #4h&B5_5 1+P'dA3&hSQz"rKHavL_&4J A!PHPf@gMudS%4v݌FDl'CMe`|^mU!xl*q̓HAtp||f9- OvyՈT!>RRa2Ie P6 */,̄z? oHז8q{uwxz$Lv؀ty&8DUEdUtI_]9s@h'TSQ.aQ uG(Pyt}&'ut:N5y7?L؄=i`Q^(`WjL|P%>N6t5rvnELmh*E!Nz6| 4rQ`rp췍rtd&A'T'dqES1PNT8WNX/LGmVMVa;EdquP%:@vhب8sUQo +'A!Q6|#URՍȋq P{@Hv,Y8Ag~GI/P@Cp@ guL瘎 t@R eAuO`] ~IU\Z~\`ӗdzdV])e'锤 x H٘yzoM)XAa7as`N(_"TA[a! SR`Hi'o('vWqf  aݵIdqsdЈ*!rDLD$ r+PY,!RȉR"oUࢇm׍ `M :8/HrS(I4A:"'*!I{d;aTQ#d3o"AP)C,?~M႙]uїNO~'AfP~G?p0B1إ SsȢ6хZPRqqjjY2O}filY[0*XK7믔] `>F`:k4[*zUUA;00D[>80Hf69P< qCiE H t'&+vC$Kx:cW <̛VnFFʻk$yv'fȁ PaE|J!:0Z,SS{n!ij5sT(~a XW2,]ϲzە,L[11H)Lm ìs`EQK]~|џ1 *HA+bi Ж82){oq't0ufQ~d'3yn ZJG&/2@˥N1r7շWͬZկbM֌g֡|-RɡOA03pTP:TJё?z|b &bC<*(.neԁ*7L̬ii-nt਩̑ڸkeSڬ|؎1$<%cwQ| Qik)- 2[;[n*"Kl;aެIY}QS>Ĝ\ |h͍_c;&s}x+Ms[B @}ycs՛cm l>Qe_x Ko z~=SYAXܙ;;#M[/'J[f,u{ز+t4n8Aۃ6,>NN(En,΋K^M^ T.ˬGJ<*İ mtif.q޶a\/޶N8#CR.!>N(eADzȺ[뼻`+.)*>yh-.y=˰N۩&$|O"a-Z݊`5* ]hJ4D_Lz =l02@ aZȰ (CN!/Cd nB @ؐ hC aJ|q8CrEa`IVek0EB|a'WeDBF ;m ~k"C:5 &u h͙D~2Awj!0hoh[ L@3Eh@Au o# S_|1h;CBmQJQAc*Sw(emrWQI 9a IVo7_Û(-ȁ)%EHSb3D a.!-\g>N{,,S _D%R'c@H>'w 6#rą|2.\ @6\ȝVM!#O>Kgq@TC} 4Ԝ:8\hb%tYҀB^, x+x?v[JQxG.bdDI@v>:Ir˜cJ^!d뒐GPx[)`Հ/ݱB? XmrRyn^mQVh!κe7Z!.Eʷ=Բ $ V[Fӆ蝦 +qh7% */uG))P~•a .Ncd0BrQL':g2g2ȶ[6s^kҠ2"F;~>r]hL3CdK`M`,g%t,ԅxt|A7m2= " !$.}]27x¾Ҙ vޟe+ Klf*-Eu_TA,y"Yv}kS=糝]-]N{RgË䝔rHx eh@bS +: 琉l)gZj8򓇳oz Iz2;U?[VqYtUxwta={ÆH$q`/v!p՜hq eR.uמS}K3GÑ 5!ĝ|; *hskUE ,ɡ߂м sEPC8-4dg6s "RYLc xqKi?ȕ+2Ae"JE? W-1{}'rg"(OCLRx.WQwZ·132qxٷx`4D(xGl^N@SLPF@ه}p7Y9 z7$68>-@NqD)(D9ȣyUP0@胂Ѵ6Qn&Xr{d's-?(| d\Y73s+HsH;(ّ2(}))IhU5`Ytp[2aUW3+QԔR1F!wwKwd?Gxaxwe@WUOq}GxwyE-MPAeEQC`eI&U.zHaAqu s$R^_rE,rRJq)q8w6-i KT,BĔqZY'P,gwRbraRc*i]9?l5yWyP1 1Ad7WYP\A1zX? яa  z'qhןB2)A\j1nO ;PF͓>V g RI*ca#v  ryl ';hy!;D5siBvQp L$Q+ڛ X;%a[O$Iؒ*B:Q+jĔP۵.8vῤ2zhyRMb"BQ=!P13yB+j+\aD4a1O/wؘ+5x\Qx*px+jh,R z"TC,wZ> 甊)@M<FFL>M|{D\A5f:08`*"`&'<,LULKM`FS!?G50d4s1a7z tA- y PQgW"5͂)d<( HsTGQ9\HՒÁ2}yѵ(YP)6B Af[6}ymn(>p8<9EА? qe+AI}y^NUc4DEM`EEII9V!49.dSsai6ѹ#{ b7] $L{=͂ԁ z-I%qԈMs61/TLaܐA& 0 ̼I41捛9o$#'2r\PBi܌aS .\@G:.Јxsf̓8uNCaʤi3ΞaذqR(ѩGoڱ ԯFRijR"]b:L:Wi4gd 9@{Sroa2cp܎V묵J7hZV:LӶzABQ_!kWb C 3YqP76BLJPbQQF2*_PDE$@'wD G#k H DN/v@׆rT Qԑʌ1e 0E|qŝT 14*:r4GF_W:Mk(C nt5^7fAES$"͑1ꥣFlxA+ ~}6ig<)CCZ'ĠMh]^ B|S)^Q>1R<rAEpLliZ 85v!SlmG>u1E``;”С+A D]6YH$@* a D`'jEfa Ac r% TIxn$R)aq E Xx"L 1aaaRK!K(B@"K" X5!bxC\ ‡h@Kl"p0YB` $PC#@ řhT# 9'&O"P> i&ӸF=,lԙ I99 ϦK;[_Ztp]mh P"&!)7.A( $ڊP2=)3k}ʈ!+TM  (=D?0B()gKP%a$Ztaqa>eB%9*AbK `amh>ZCX P%4H0:ց4zbcz1~rp͘ql.8C,F1b(T Ť,wp3qz&rwpasB5%G$biP: Ӎx$Tؔt~`f@-b>#iȓ> 4 2'**E*Q6‘Hh&T1Մ,@fbF3{7 26# um6 'pEN(gYolIZw03T' 0`rO2#1nEEƩ~~Șg(! xK&P .)x5@ɝi Y8yΉL.c#GQN>#Q-5gr9(;8M pyOGqP=Q(2؉} At(#2t,"Z##ES\+cwI%,Mo] ;3< DO[L1}=e :Z1AW aM(1M$\bB#Q)ߔ^ @jahWJYwЍlp $}Gr3Iw:n '1ryJ6q#Rzk}*.-1ap(xޓH[>I]ޣ&6ro%Z={j9(`XHl @&24z;橫ʖXbXHp@Ȫ*?`I7cO#FiXZ)2:Ie2-TT4AdPeFIz)*nAѺxlyK'Jc1K*MڰLĄ'S,0j" g;.D)1i!XXf0Oc1kAbRrrPW+Z,O?IC:Z"Kbʮg(=ShQh uxpeqX en} `3.i(}؉"x5af5x12 ׉khk4Wm }6qk++P;*?J>t7#Q#Æ+V[Dg;)+|Ea1 ݸu!u Qb Ҡȃ=GsٹJ7s.j[ITz@_П8g&.D@2K[0+Ys+9s QQ%(jo #'131f(EP4ۘٯ Ih1 *w|T9P1" 0#*rrlBj\@Ya̛M. `[L/e EC1A^as@bD"6pyPM7t (4Ubkof0iaaar zkAUO9:qM%*sY gѝy-#yIW!x'Sp;=Fݙ0kr8"ѓi"9Nͮ1'UN06GcЙ̻e4 =ãKQ&3#}6#t. qQwP؀M,D=<|b0YDL1HgK,X f h>j[S6}XTxyb&I.yN]木ʌl,O[Ղ \хCPs#6)iO+p{ЌF L<9F0> M}ۮ! a|?98`w,҉ i` 3Lgΐ~[ޓj=6ZWm0o쀂=~!Xr>~̂KҖ-Qpî*0*MLAÅ` C.3|fN7 "QC<qR]3P֭ͮ͜9Y{49j8ǩ%:ܖA[*@<82&u:<|C<`t+r*6yZhɋiܹ[w 7Z@3(/R/+/b/E/kӡހ `3İ|jrjO~;55֐1Nx%1L^6ή1N &(/,/ ="$&\ '36٣3e7Ϯ9;n!1&2K|%DuOrp2O:S Al5O^A$ZeLOHJQ!oy2N%n%s!t b{LOR=fӈU`R5ؘfm 1`V]]:as *tD 1AK {Kg(*?\ٲ121Bň@S~=a4*5ۺINB61b2oLMƚOawxA'iYT8d!"d0,R[;ǐ{ys\I.Zíp|,2y'Ϥj;zF=:0!|Q; ^%R&I%hDL NI*<ӓuHIX#d}d|D)EctWb;gC .pH#xadXRcv9`Dc9R9$7ta L&"6IEEv,A [708O @i*]7 cYLܑ,)L0i"P?9J:wI`i'[dw Yjei?Lh'I% Љi1[ Ʉ8<ԍrxKR.3d6(ޥ AhsXci3nN %w$":r\5,"N0wEdx(܀P|ZB4?=AD IY Z8XS?Aܜ$nÈ@nDz ([樣,A-cu 􇚣1Da% DAڙ{%#7:pۅB`+*a%!]H #CYY1TxvI5',_zK}$<}랟3cϳ?f5E:mȷg#u+'I!]p On E?ۡ[ j[ˠan(^s64׏[ t_sK/F.t7Ъx-:1,%{^Ae1E #A((%9(n S+Ni^$ӽ)̙l I E)ioZ:$x5pUalP/XX  (%8B%65Z5PsrܓVD㒱H=8 07+mƎ +n+I*,r5=[߆WvMX[_lSV:noݭ9vKpqYf,n5Vbt/^te+{l uP`Z,me4g.i| XCIG%p~OJ`3 M,*#%&'()*+rRm4ZMbRwr$T&r/," 'kVr^g~EFNNK|OziDs,f} 8ⶕ F񌴌o 7C&Ly8Q:[M-fؾjU"f`Ku%Y\s@{0w5Pܙv1yK㾦U&bL#k1b"vL+}i'dG+tx=&ʉL5uɃa1IȂ8_ci&:^ R5Ay\U*V-- ~3?N3abS)PŐ+!ZIMd7 S~,`U@@ cLD3edZ~q]:k5"FL($RI&G1Fʶu 7աWXMTv*XcuJW +d<.1AF,sl0[A1e*Ujw::xbl)r5f7O}2K?gPdة@:Vp< 3wߙ>? (+PXiBcQ;CDfZcǣH7jO#TsUEPih=cCt J\Zt/Aՙ4(<-4zd$uӉ004s+hn"WHBu`9’r@ A6h$1kF-ZOTZG]:@:J"ڑNf`I닩\=P]WN[iH|iEV'5WQj@.'h56ܴF[3ĄIxu.?Z7S@"isxK&;D޽l;u4[Wk_t6?&'Mh%I` d;R{Wj]fZ[o &[rHk-;f So`) oA$;gJ(CL >кNNռʈb%ϖJ j!uTCm&m=#yj pt`q!0C=eXo:i?b``a-p( Ex#46ׂYuv䧞:29EuX 6paހ&?3zzWct2 k<^sMT7$6`)<"hs9a_|̛ _=4ݝ])l#o'cT0Ɍ;3Y)1D3y]LC *^eCjj 㐎q~]SÆߏ*A7y⿁GSe"pWD3ZCE/;[ٯԎC3؃iZ`kP ~J c5DߐCś(BS`"-" Œ;; U(CPauh)#MZ'Z_M'"euU[y*9s*y^N^8/fu8`M%.է88"OKk<@ׁ[d.վ87?<7g[4o=Wp[มDs.&<_&p?~ҌtɫVPSS^$PSŰ(W>`9]!crp9e(/ғ$0٢2[A0h4GR|*c kSctj9MgS uyp]p,(#AsG x`|K'DUA\p~hDx 2tn,*]3bѿzÛǵtAi8Y{IK\k Heet ^fR!]) DQuf|$ Mrm&Z)BL6UVY! ,Rd+(pjti1ŃrQV^grt\6Ȑ%I* 7dĂrdpJԅ2{OC6Lr%Wh (MpTC f-S7֠|~AZם꘰,Xafbd1£H|0a1ջ60@ 0Vч6+i~tl~6kG^"-Фpk7Вw= ?P+Ȝ@/&{8]ŰcNpxKqa D $X,Aܙ͕2)<:ćJX/01:>2* 41*VA#j%Yg#FTd!#p.Rpx)rF.'IN_ȅoOrE.?dVtø񡞓є<:DpFum"[sՐ_a#$c87$$rO `}]W#=f.hSf~hUd4c~ }@G3Uu!H/'2/Y[KĀ s ₜ+]<,,pKNJx9K`qF *0%r xg᯳9L,@CC\FȧKX,DtiElk_o (7#._B}?Yuma lPBTb|M"lMؕ0&~H/'2/j8c]j9)ggɉK=4dQerUD7upsNpVAzh40 n/E(P~^܈"CEDj~ }Cş[5<;K{5xi(-"+l5080s졖= ”q.aoa'>5O|j [*`촉`$!3 Ţ]'+:B @C+ h:i "n2aFuM%8E9 O_i:5@(wT[ Ս*r~/{304jղ%pޑOjYUJa{-}b10* #^fXG IP^t t H @0ɔ*b\p" `EH \@Ẁ-[@ L"6azp7 >!q# f ," f(1+8ld"5beD:Sa;a(2̗QbVdȦ.Ed pN #ؒJEC,P X*kr@vaȩ%]&ޒQ/T&fҰ)b7t¤qspΛ6 igrԡ3A3o SFL3g<#&aS%.\@!E:.ЈOBLҥ9Тaذq#*SN갍٬[%ZFNȲJjtҼpZmS?ϰyc-bpB1eB7 LI0Ag1yF$-N|"ɐ)]v$Λ4 #9#'Ln` 0*ݸ4c+bVgYOp7 ʩ30sDs?-)Ph& 6 Д QUk%ePˆ#  ,H_ )(A!}b,FpdS _uG| rވaGRiGrjbW FiAfB©Y&~tLiAld%gy7gi^ FaAzDF(D(XB ¦ps1lѢs$IjijgYvVaAr`*B ا}=,ʫʍEd! Sd1ALD dA& [viI)hWwdjY4"J*%ɚ0R<`dFmSjB #ޘ@f >_LT|aEC$QG%_B_,]Q_VZ̩Ҝl7è3n>`3K AA& q3C4@,u 1D̲2ukq 2D ݵ_=4 B D׊t;`s7~Yt]o %@4n߀;3マ( L4Νy<1.<0:}_l|qvIF0Y|qi&t>qcACJ #W6j} tPp-a P:!$mhWxc Z8YYx+%Nl $5$s u&l^jƌb }] UB/f$["$k X!(xk>[:#?1zg]Tbdaf&0w;+G88" Td$\1798QRWD%2Qj1@dOhAս@ yB@kJ0A'Cr @` ]#戈:caXMͨF7>:RFT/}ߚtF)R\\V,'RnHԂ~ EDjP^+CXCA ly;Ep&4/ͫ^5?T6,=,bS򲗪c!YN2e/YnH5jgVsZD48{UkFjYGjVnc71qwœ67Op\  baU6VsR.w7]׬sv݈$KMֲ~W-Ad*zTI *JԩFFRO:#BkQ%vPQuK2$"lvJ0[`Rܫ*%:?9 SbQj=(E 8! Ci?fY FGTYגkzAd+A}Y @^2" 3"*ٺLih͛_oR,2aIETI%*xЋ#\9Z}!,lPA1k fl㼁 k0a D ipB/8I"B]uf̚xpCЪhHuU's*Q'99$"u^ܘ&âܸbbPlc":ZkD*=1YyVUj9p ޢ`-pZj &D?Z~ee;В_\6g Lp9GNHkL+ۭD"uM]mH8ۼ- %L/T&fҰ)b7t¤qs0 2r)#ᛎyND 1!9o,!)@ԙ3 :h(!I! aFÂp\bƍ)A:wހ 1 4!L2 ,9fe7d CtHN1c3,6e s&2n-qbQ/iκ9sY:y~yrerژ},#4;:28a䄁WZ>B'ҧ)b%ɐ"١Hy2)Y>J'SPI DH)2e(hh%1_ Qi$6p4nt bANfQa QǽD ;c?|,^!|Uxaq!"NUȢ08c"d QB 9DBqoLD%#ua̱ 6ќutGPn0GsSgaV} wUQ pXcC8@IJƫ L1nkA_%Gpm 4z#L4uX./Y hKVwvƷ24!So Cm/*.G00.11c@@DR]"IS&JO012$sqFm$v C=C67APQ54 R (I<fhCZ4ѱSggԜ܊}t_vK5ĭ3'ٽ/+fYV veMM Nq/5*vcD__M0)a҂0*cHqQmOP4803ϙp@C׌ 00agQcH0uƋ\1!uPA J& Z {sC\*eFxBP!X跃a A!&0pt/92BufYYl7H1``Pr(!YI; B\ԽCْPtʀ]ŇiT 1$( dЄXίa}aE,]AM.b#:dEӆsq̓쒒z"qe{z'y9 9sb)Ry!pipgH/<󍛁 ɡ lXzV2 (*7 ] !9ljlNZ%kaR Xv`S`$4-tbNCL 6kc>-pӤk/R)A7-tAvn:ҴeCed'K+srv]ef-@c饂tvvvxf[zvYIIpJr"h01qvM`!wQo?FXDViyAg2+'V_Iwb}г"~),'!dwp~ u+XSX_Sp\T 1[Sx"uiM"'5w\xJ8}Hih+_.FDЅcthU.-qzߨzbrAVo`Xbw~mvkqHpPR@5uISΘ~0fQFW'qVisj#]H"u*#(  jّtp UDhXC8S':0#rHR_ Ja3(_0P:I[PgCc_2c"M 3!¡qY\$WgJUVYՔjnp#-FyIxx])R1ڣ,(m(9vaUIHxp 37Ba{YDf7U!rX)y3~tyuS+QR2[ъ5]"VmB1K&F#ٛHeDFFC`nnE@c12hɖɝXi!vF46Kɟ; + ٟrGw*tM ::}&hJۂ 9dL".%x,+ FEx)8g6 "ީeDb V@4~Ĝ Y\(ScB*AD&0i3Yʂ=d]=&?h7Ut vY_+LzT^B˃3lP(iF-ɢXd^,UC'm;!_d^j*ALtC6ud-bQC68 {ґ!f GkZ#*1g9 9 ivPᇶ ^"C̓QcI=cZٜU'Mtm.p`+l}VE,9EDFfwuj de5(p`Yp&))xvmѕkdU xAH8 g(.Fr!<8<"pw: 3Cxml7V4jGF|P!#T]9h[E@_=Tn& [_'@' bђ'sy#ʖTHjtlp9%t+e!ܪ7).x{.!é $Ɩ>/PAQ Ya\!pA0=hnln9/tvHtE4"ZJN'Vz`Uy|cwǖpqAN']ڱ8˘ߝ~yL֊z <9tXk=nmRT L_tUiX$jT)? ~mO!E~_Fu 2E}ݷV@doIE!^&B怀}(8R ICa$M V@z =p*ND^ExoG&,Ck-YGv䉵S&{.O<" $syH S&0x 'a?m*kkay9 ,4?@oXz c8a46WD]'rXg(?/͂ +_H( ?¥,HY fb2hͧEu5EgTpF+(T%bh"ptÅhKwaB8%'6NJYEy?H<@[s\ky%:+M aVXV @#S[k\̢Y8 *'vzA|eX k:ES`Sԡs}# #;83i/ nXN`T8ߢo"#CTv]g-D'&q2N8ZaxpeY"gpy [Tz`Ϯ; PL~ONU?ŤF3SN9@^{`|#dG4"@ qT}vJ@'h^3 *ؒ ;e;<Aϻ8&`pQ3 Q7ULr@3"4ef$ZeTU.ƵF͈:Nm̪ݼ;Y d vDxgV'30#i e ~)FU sj< ^@o o*d8d#S"/a QB!܂.kr5X,"!NX-_C6' AnW*\-s n[Qi%\*S.e d 7:4BPR5789:D2z 0HCsvJ 8OUctЫ DBp)(} '4UFӱ!(A-5ۯ3h0-&i-|TT3="m~CtIԬEz߽1I  !0MfصWj kUDuX Ijf$պh*rW yǢǧ;]9jArnSOa^CazpBICq1…T|kږPD a3ŽȒR"EtTL*]N<`*,E7H HMV`eadiϩQMi8m Sq-('LR`m'ֽF/j!]¤t%Bb,ބ{'k:|meE \at^]J FSTv[ gNvI0ΔaMi LC>`vòC/lk Rrwpee"M; "Gp~*`j%vfVvƔˢ 5nZ~8G 06L /3cN GB5d߅mJrEqs*AbPAiS2rV_32EQ+*=9LagO^|[mMB 0 ) ~w=XVgpV^mad`0I)*pfZ ˰Efy K`ZXn5.]ɱ{ꒆd 媁X›'rX0Hx6(4y@4ȑ19B LvF  ,đd@q7Zx.5""+:B(Q.u~`If W xobE Ugc-:fT{"C2`y"̻7. =o)~=)11$:Y I ! _%T{ nEѥƅFXN (ݵ[pSG ZZm EޜK{+3R\l|1Rj˶LCFex^DRzDѲ/0r (٫r)ƻZFfQ^ˈ*pT2!p~os(}G\BPu)᜽^POx-,֛n\+spT@$ڌsSg5*$0L:Y0b[ g]3G.c%LN3VDJ?b(Vh1εwLA *3:>Яi)t/B׽zu:Q;*sflX-؉2UƖ!1h-f9CNbE=0QXCvQfE90kʵEE,7&м$ @NqMi2ZJ `w M?RդdMdRh Ug@y ¹Z-+rES4En/Hqa5uGmu'ug^ez%Ũg PkTs* Nl3V4F 'BM6hCmLH!:4"̰S]t nFoKBCy[I㝾 7X {L]>igŲU@(Z\ m5)^@9q(A99 00C;9047LX4G׹w1n,sj{.tF[]q-lt:@gLFf0{FQ|0I>Y" 'NѦث![&DR*H?L!h䆼 _^f1}l^ QQ,aFLwuN߸3*!Gƥ DH5"Ect[̥_BDrlam եu"[>G=@vτ0!;H[ Vp:o4ȂxY gܾJF4}pI fit7O5Rә]8?ԣ7dK++A2D;t Sm87z\1;57F_֝~nRzVf"[E9lisgA -g\ %MGbENP:T^plҳQǚQ'}wDgЈ:mlmJ ;l[&O)_x 0,9K86yA#SWVcK<~{Q@&;I LT~w+1LC7F݀/X^3\Teh O0Ðu 7>L\AK8p@)nZfh~KSmٶk0 dvƼT5`DV4RLfec$3z7Q4\SGu.eLGZސ}Rb÷cąʒO\:*Rd!oyc^/^AЈnBPry;A Vķji}Q]eCemB J' "srC3Ŝ(#CJ\h*YnrnC V-#r'^'R 1 2kA5wXBv + ɽ=`E4Q7b}l" $ I:Z/ pw3jߢ5~-Xy8sj2.z_親DeBƘ7z =%DK|~izLb˪ ooЈ +mcb%ᵮZ)/n\f/Q A\486~\r%kھDϳBe!yIMC1Y6o::򹳌S6Cvժ2o`AEݣٳ 21qyll-U)qAE=kXGqmюXߋLjumVhS c?j=aKmzU{NݯgHr5\s*M<1ƳMN. jX2o0q?.ȥ[8&scv)ɺ}`5PZ+ȳV-Hk^l:[b]0^3-暣9WѹչXIjAN:2F(Kx"6 JZ@e~Ȕco浶}(ݡNS0jEgzt t~sfF vj {XG,Ьː϶l׋˓^ֽ6APjF%ˍ+ ܷ fk\+q\ihv4vZrbnn(s@F ެ|P Զra "~AY(17]2߂ P=p׽*R>wW0>r-a n395VpNR/|/* General constants used by the kernel. */ #ifdef i8088 /* p_reg contains: ax, bx, cx, dx, si, di, bp, es, ds, cs, ss in that order. */ #define NR_REGS 11 /* number of general regs in each proc slot */ #define INIT_PSW 0x0200 /* initial psw */ #define INIT_SP (int*)0x0010 /* initial sp: 3 words pushed by kernel */ /* The following values are used in the assembly code. Do not change the * values of 'ES_REG', 'DS_REG', 'CS_REG', or 'SS_REG' without making the * corresponding changes in the assembly code. */ #define ES_REG 7 /* proc[i].p_reg[ESREG] is saved es */ #define DS_REG 8 /* proc[i].p_reg[DSREG] is saved ds */ #define CS_REG 9 /* proc[i].p_reg[CSREG] is saved cs */ #define SS_REG 10 /* proc[i].p_reg[SSREG] is saved ss */ #define VECTOR_BYTES 284 /* bytes of interrupt vectors to save */ #define MEM_BYTES 655360L /* memory size for /dev/mem */ /* Interrupt vectors */ #define DIVIDE_VECTOR 0 /* divide interrupt vector */ #define CLOCK_VECTOR 8 /* clock interrupt vector */ #define KEYBOARD_VECTOR 9 /* keyboard interrupt vector */ #define ETHER_VECTOR 11 /* ethernet interrupt vector */ #define SECONDARY_VECTOR 11 /* RS232 interrupt vector for port 2 */ #define RS232_VECTOR 12 /* RS232 interrupt vector for port 1 */ #define XT_WINI_VECTOR 13 /* xt winchester interrupt vector */ #define FLOPPY_VECTOR 14 /* floppy disk interrupt vector */ #define PRINTER_VECTOR 15 /* line printer interrupt vector */ #define SYS_VECTOR 32 /* system calls are made with int SYSVEC */ #define AT_WINI_VECTOR 118 /* at winchester interrupt vector */ #define PS_KEYB_VECTOR 0x71 /* keyboard interrupt vector for PS/2 */ /* The 8259A interrupt controller has to be re-enabled after each interrupt. */ #define INT_CTL 0x20 /* I/O port for interrupt controller */ #define INT_CTLMASK 0x21 /* setting bits in this port disables ints */ #define INT2_CTL 0xA0 /* I/O port for second interrupt controller */ #define INT2_MASK 0xA1 /* setting bits in this port disables ints */ #define ENABLE 0x20 /* code used to re-enable after an interrupt */ #define PCR 0x65 /* Planar Control Register */ #endif #define K_STACK_BYTES 512 /* how many bytes for the kernel stack */ #define RET_REG 0 /* system call return codes go in this reg */ #define IDLE -999 /* 'cur_proc' = IDLE means nobody is running */ /* The following items pertain to the 3 scheduling queues. */ #define NQ 3 /* # of scheduling queues */ #define TASK_Q 0 /* ready tasks are scheduled via queue 0 */ #define SERVER_Q 1 /* ready servers are scheduled via queue 1 */ #define USER_Q 2 /* ready users are scheduled via queue 2 */ #define printf printk /* the kernel really uses printk, not printf */ /T&fҰ)b7t¤qsm$GΛ3r´ &I$ <֡3F)81 0l)S|oهN.qTcUJ 0QVy$G\/(Fd0$ . QD h0c7Ž=HGi$n؈<$Vn!U&e@ƗTZ$Z8H^d?ΑngrdR{Q K|9c AAQYd @@IuD$4Gf%E5eo% x͑ 1@iM XQY|!DG 9 ^_bXu⭅xk]VvNkALQP 6*Pd!Qqѿ'DbTSjK &Q)CS$ES *;T!A8~;U|i €8/>zg0 *u\ZP2 )-s2Ԍ Xsdz}YTR\% 3ӱ @1APK61IDCo( mBܻw}՝s)2Pd p}40`F*()RCH JJ6$0 _H4& >I24Pv!l/N`I8)B4"`P-Pܚx/9b `'HTb^bE:)؁ ۂ Cv!8Dq1$ dh&m<&ā&sp52ud=YGPֱ}d 0Ib4 3fj,9ΌdZ̦0!3!0|N^ d pe"gh *C`81DpKi{"]DE) Ct K(ЀTGe6 WQ]:R!=(L494J9F;*%Z2*F$ d Tpv.9k2 jH#Q\ϱ9l]) Xꠐ@̪*/@&;CEv_ kpEG^թ E2DxbYp@Foghtc8;PdCG`KGhk=rlfڸBv6 KNђFlȷw؛*%jRψTf.PE+VRDZ VECȬȻTt)zՖ]"QAp_7FG2@-XN(;8 Bq;4k,k8 %#@Rɯ`*[QZ3J,$Cokt"?е\ C@+l){:T8"s@2G˜)pF 0*_˄y#3W|c9!i06 kJQZt3@Z$:KE=[NHpk% _@h@YRհ4kC0S@pk /쒆WE Тf [n -|9HZޔa$5/0 t+h2U\1]"5Hިz[eѝc`H ք ڈ5OHčؠڥ/j M. U*`89灄v-̼ +| @ᰂ+gNq@]ѥP#LX Z8|[Hý9F`( HP3,Kw ?j*SFbVpt*ؼ .HD#|+PPo{(% };sxps'-|LiS3Jw&CC^{>@{ۿ>7̡_|o_]˻'?aC~O!i | !8/ypz~r~r&ns~gp&H?b-0U*jQ;޵pqM`Fps }#g(Px G*IO^s~͵Ty f,Ȣ,̢KKh}_ЄOQ\'S}\؄DK!bVǒ,rZzׅ ik(q GpfofXM8jxRSbpFW~55"o=owhzxR8ƉCo>w!G*g88:6R.S'!Y&(&F()FHst+HR@Wy'ngUt¸Jǖn rt {&!6nʒT1/|>Ooathiskٖod'~'~wl}ٙ W))|%F'sO_/LtP'+vAc"(ptP OP PX'u#(nPnL}F@vE`.A*D@C2xuqa 8;ne&kJ6 f&3).A!!եUͶ3v'!vA3^( J_Сإե\*53c*J5cv3FwwQ6vT`#-a0'!n7T8GRPZw>8m3HJѤObjM @4IpȅRVͅ8vAvh]D8%Xv:T4'1LR5Rw(^8*٘VJjdge*DAq8mHlk$D1z4S;"oZSr }vm?8X HNokv`cDWXS%qyr׬12P60 ckPvӺS6YR[J 7CtlEz*ꚪB:E0*\Ѱ*/CaDɂc?sZ ˭#X*S[2+878 *b4jLPsY@ 4)CǢLj1+*` &6a*Ya pa6$W˲4Z+q\6"8'Vb"&%*x@նqW`0X˳ ZAon4*::k[:3W;O;p(}?G(+,ki!k2+&S5#E@˱ʵAK\63chcܻyʁq 1CڱAV9b/@/|/`Krrx  c )I942AWH qTe~ZG;?f;@ ܴ =e=o 62t5nñ;WWw;SmAy8C0B'dO+ă?X/Z6sW,>K@Hl_}A P\BS\PUsWY2^4Zos\Ic½w*bCT|<p9 > s-[8ABBUeyo+gPgum@@7'ngag/Ccsp/ZeiN=L"MԜ!"Uj;#ݔnQ l%;]Hr VleV6D*AЮ B#F-}}BJXT>DVDP˸f"@i Qvx{+pcsILP ec14AIn 7xgoa1=Ӯ#oxiOdo yԐwD[vMou~T蛢^S<Ƃ̾$ζm,L Mͷ=MUMϽ+̀8\!j< mm;RrMtv ы~M (!c@"ؑ)=y?mgډT.<-f9th8m"c9X!|bYg -0"XهJ$b-(fdEsT.{*4,>ۼTĝٔۿ-Mp!*V~MƍܭQ9!`DnJ1!2k f`p,oTl3Aen&ag\!}'Ȩq 7rF2geYKQ?b1lA QV@Z-GQ%"904'˅*vFfaBk0ݡ*tOk0RR+d{"KpY!Ss@ؾ2~a_UH* ؄ `^d9=n@Mi1QJzop"\_˒i0WLR1DsCMRq3/ X]bٵ;HC<!h@Ϧl}QH^ IH3\ 1.0.;0  ;,֫jUwOH )FUX4S85iSU]\`"lO벬~sƚHXiUd8^Q&kPu n/Oxke/; c.Op+9EH[>nf uչ\ L _%*`K\8Kb2LNstj~)ѿ2(a;ekNj4^%¦8c|~N0bܱd;nf6gE|8`Ry39$8[I>0ϒBZ'@=P^_r -`mTZ[K/T&fҰ)b7t¤qsd䤱SFA3o |SG8eƤ 2st(!M/ȔM6l(vҌaL L\bf͛9whSM ˆM: MYyQ vMG7eZ&CKjٺ}0^J 5n ;f):)0g`)rs2ό)F:GqC[u":s:te N ,d'ah=ʤ9f/t|kH+Iy Eʓ!_H!?I'T?J'NRHQS‚ 6F(GyIL…H)Ї Dt!bA$f7مbaFth!-  " @D^!E끸6]h(M-M3Xƍ,ȣ4} ɠ Ly~T0AbKIM+ktu2qF~ fim`[1B =D=PQѱ ݩ^sCM=zEnDhA,VhLV 0f./ h2䆇juxĆ{o߆˯Cml/LnGɡ0k.\1n9F^ !cSTJ DTmё;.D uRp&OPM|ĔG$M0 TS@!q3ZQ[`rPt APWÁ&;|%31#76rƱ_ }nlSt̏sca:;MOIzp>G..8iRD u:j$n@@=4G/Wo=WF 'UחoC/xB0`]ݚ+ U@MHTg@ڵt[Q4xo ɻLƍf hD/`e]@Ph /`XTn)Q  2؂@v#D6.s[BX P:)n)h<7 M I0.hnvJd(E0 a 1B(F2jd#nIcA/! ru$t!CL[7ghZ\!&iD0Cnyu492:l$ +ؐm6KH)TY@`4xd2we-8&yH55lĆApBFc HÎP7|,%)TaPTc@ѝ e`4=(I䰔@C &Y'>R6;4df;K*W :A1eT,!:)b:x1(xSl- ġ" hW""g`55kD%Nrm[7rή_IX§ )P~U+[m4ƵuML+iA7&mgn_yf儐Uly˾I="'A YhAG>UNaTBˤ8y (@BO.p7{*`>y&ͯ~Wm=: [ȡ*n⨠=ݫbu3u6ssQOfR[O '?ah x.] s".0*I!$dh(" #_@"%:a2" fgs`(C.Ф6:1, paq"# 01^gVͦ6KYcb EɞWNLO))yRR )NeYL_T"8 Ng 9 L`B3 mJe@0~t}C.PfS@p[!dq -ƈIa ^ئFм(nG䶐c=B7 J"H:ւL潛(JQg]'C:8F#Əñc`+o&7ZYyy^o P ďI:;L!CN4"u T΋UGս TC_\rͥ8oy4D fdݏ4A1]i]i^5R[r@_!UzxJ,oh$4-@\A5dl]a_u: 4EYqnU`nMp+Qad#N[v-&نeցP*z3s`c@9tvpi!igiwIFyo&a66y&{&k7pGSWppFHE.wpG}16 >aFIK@ /* Global variables used in the kernel. */ /* Clocks and timers */ EXTERN real_time realtime; /* real time clock */ EXTERN int lost_ticks; /* incremented when clock int can't send mess*/ /* Processes, signals, and messages. */ EXTERN int cur_proc; /* current process */ EXTERN int prev_proc; /* previous process */ EXTERN int sig_procs; /* number of procs with p_pending != 0 */ EXTERN message int_mess; /* interrupt routines build message here */ /* CPU type. */ EXTERN int pc_at; /* PC-AT type diskette drives (360K/1.2M) ? */ EXTERN int ps; /* are we dealing with a ps? */ EXTERN int port_65; /* saved contents of Planar Control Register */ /* Video cards and keyboard types. */ EXTERN int color; /* 1 if console is color, 0 if it is mono */ EXTERN int ega; /* 1 if console is EGA, 0 if not */ EXTERN int scan_code; /* scan code of key pressed to start minix */ | This file contains a number of assembly code utility routines needed by the | kernel. They are: | | phys_copy: copies data from anywhere to anywhere in memory | cp_mess: copies messages from source to destination | lock: disable interrupts | restore: restore interrupts (enable/disabled) as they were before lock() | build_sig: build 4 word structure pushed onto stack for signals | csv: procedure prolog to save the registers | cret: procedure epilog to restore the registers | get_chrome: returns 0 if display is monochrome, 1 if it is color | get_ega: returns 1 if display is EGA, 0 otherwise | vid_copy: copy data to video ram (on color display during retrace only) | scr_up: scroll screen a line up (in software, by copying) | scr_down: scroll screen a line down (in software, by copying) | get_byte: reads a byte from a user program and returns it as value | reboot: reboot for CTRL-ALT-DEL | wreboot: wait for character then reboot | dma_read: transfer data between HD controller and memory | dma_write: transfer data between memory and HD controller | em_xfer: read or write AT extended memory using the BIOS | wait_retrace: waits for retrace interval, and returns int disabled | ack_char: acknowledge character from keyboard | save_tty_vec: save tty interrupt vector 0x71 for PS/2 | The following procedures are defined in this file and called from outside it. .globl _phys_copy, _cp_mess, _lock, _restore .globl _build_sig, csv, cret, _get_chrome, _vid_copy, _get_byte, _reboot .globl _wreboot, _dma_read, _dma_write, _em_xfer, _scr_up, _scr_down .globl _ack_char, _save_tty_vec, _get_ega, _wait_retrace | The following external procedures are called in this file. .globl _panic | Variables and data structures .globl _color, _cur_proc, _proc_ptr, splimit .globl _port_65, _ps, _vec_table, _vid_mask, _vid_port |*===========================================================================* |* phys_copy * |*===========================================================================* | This routine copies a block of physical memory. It is called by: | phys_copy( (long) source, (long) destination, (long) bytecount) _phys_copy: pushf | save flags | cli | disable interrupts cld | clear direction flag push bp | save the registers push ax | save ax push bx | save bx push cx | save cx push dx | save dx push si | save si push di | save di push ds | save ds push es | save es mov bp,sp | set bp to point to saved es L0: mov ax,28(bp) | ax = high-order word of 32-bit destination mov di,26(bp) | di = low-order word of 32-bit destination mov cx,*4 | start extracting click number from dest L1: rcr ax,*1 | click number is destination address / 16 rcr di,*1 | it is used in segment register for copy loop L1 | 4 bits of high-order word are used mov es,di | es = destination click mov ax,24(bp) | ax = high-order word of 32-bit source mov si,22(bp) | si = low-order word of 32-bit source mov cx,*4 | start extracting click number from source L2: rcr ax,*1 | click number is source address / 16 rcr si,*1 | it is used in segment register for copy loop L2 | 4 bits of high-order word are used mov ds,si | ds = source click mov di,26(bp) | di = low-order word of dest address and di,*0x000F | di = offset from paragraph # in es mov si,22(bp) | si = low-order word of source address and si,*0x000F | si = offset from paragraph # in ds mov dx,32(bp) | dx = high-order word of byte count mov cx,30(bp) | cx = low-order word of byte count test cx,#0x8000 | if bytes >= 32768, only do 32768 jnz L3 | per iteration test dx,#0xFFFF | check high-order 17 bits to see if bytes jnz L3 | if bytes >= 32768 then go to L3 jmp L4 | if bytes < 32768 then go to L4 L3: mov cx,#0x8000 | 0x8000 is unsigned 32768 L4: mov ax,cx | save actual count used in ax; needed later test cx,*0x0001 | should we copy a byte or a word at a time? jz L5 | jump if even rep | copy 1 byte at a time movb | byte copy jmp L6 | check for more bytes L5: shr cx,*1 | word copy rep | copy 1 word at a time movw | word copy L6: mov dx,32(bp) | decr count, incr src & dst, iterate if needed mov cx,30(bp) | dx || cx is 32-bit byte count xor bx,bx | bx || ax is 32-bit actual count used sub cx,ax | compute bytes - actual count sbb dx,bx | dx || cx is # bytes not yet processed or cx,cx | see if it is 0 jnz L7 | if more bytes then go to L7 or dx,dx | keep testing jnz L7 | if loop done, fall through pop es | restore all the saved registers pop ds | restore ds pop di | restore di pop si | restore si pop dx | restore dx pop cx | restore cx pop bx | restore bx pop ax | restore ax pop bp | restore bp popf | restore flags ret | return to caller L7: mov 32(bp),dx | store decremented byte count back in mem mov 30(bp),cx | as a long add 26(bp),ax | increment destination adc 28(bp),bx | carry from low-order word add 22(bp),ax | increment source adc 24(bp),bx | carry from low-order word jmp L0 | start next iteration |*===========================================================================* |* cp_mess * |*===========================================================================* | This routine is makes a fast copy of a message from anywhere in the address | space to anywhere else. It also copies the source address provided as a | parameter to the call into the first word of the destination message. | It is called by: | cp_mess(src, src_clicks, src_offset, dst_clicks, dst_offset) | where all 5 parameters are shorts (16-bits). | | Note that the message size, 'Msize' is in WORDS (not bytes) and must be set | correctly. Changing the definition of message the type file and not changing | it here will lead to total disaster. | | This routine only preserves the registers the 'C' compiler | expects to be preserved (es, ds, si, di, sp, bp). Msize = 12 | size of a message in 16-bit words _cp_mess: push es | save es push ds | save ds mov bx,sp | index off bx because machine can't use sp pushf | save flags cli | disable interrupts push si | save si push di | save di mov di,14(bx) | di = offset of destination buffer les si,10(bx) | use 32 bit load(ds is our base) | si = offset of source message | es = clicks of destination lds ax,6(bx) | use 32 bit load .... | ax = process number of sender | ds = clicks of source message seg es | segment override prefix mov (di),ax | copy sender's process number to dest message add si,*2 | don't copy first word add di,*2 | don't copy first word mov cx,*Msize-1 | remember, first word doesn't count cld | clear direction flag rep | iterate cx times to copy 11 words movw | copy the message pop di | restore di pop si | restore si popf | restore flags (resets interrupts to old state) pop ds | restore ds pop es | restore es ret | that's all folks! |*===========================================================================* |* lock * |*===========================================================================* | Disable CPU interrupts. Return old psw as function value. _lock: pushf | save flags on stack cli | disable interrupts pop ax | return flags for restoration later ret | return to caller |*===========================================================================* |* restore * |*===========================================================================* | restore enable/disable bit to the value it had before last lock. _restore: push bp | save it mov bp,sp | set up base for indexing push 4(bp) | bp is the psw to be restored popf | restore flags pop bp | restore bp ret | return to caller |*===========================================================================* |* build_sig * |*===========================================================================* |* Build a structure that is pushed onto the stack for signals. It contains |* pc, psw, etc., and is machine dependent. The format is the sameOQRSTUVWXYZ[\]^_`ab as generated |* by hardware interrupts, except that after the "interrupt", the signal number |* is also pushed. The signal processing routine within the user space first |* pops the signal number, to see which function to call. Then it calls the |* function. Finally, when the function returns to the low-level signal |* handling routine, control is passed back to where it was prior to the signal |* by executing a return-from-interrupt instruction, hence the need for using |* the hardware generated interrupt format on the stack. The call is: |* build_sig(sig_stuff, rp, sig) | Offsets within proc table PC = 24 csreg = 18 PSW = 28 _build_sig: push bp | save bp mov bp,sp | set bp to sp for accessing params push bx | save bx push si | save si mov bx,4(bp) | bx points to sig_stuff mov si,6(bp) | si points to proc table entry mov ax,8(bp) | ax = signal number mov (bx),ax | put signal number in sig_stuff mov ax,PC(si) | ax = signalled process' PC mov 2(bx),ax | put pc in sig_stuff mov ax,csreg(si) | ax = signalled process' cs mov 4(bx),ax | put cs in sig_stuff mov ax,PSW(si) | ax = signalled process' PSW mov 6(bx),ax | put psw in sig_stuff pop si | restore si pop bx | restore bx pop bp | restore bp ret | return to caller |*===========================================================================* |* csv & cret * |*===========================================================================* | This version of csv replaces the standard one. It checks for stack overflow | within the kernel in a simpler way than is usually done. cret is standard. csv: pop bx | bx = return address push bp | stack old frame pointer mov bp,sp | set new frame pointer to sp push di | save di push si | save si sub sp,ax | ax = # bytes of local variables cmp sp,splimit | has kernel stack grown too large jbe csv.1 | if sp is too low, panic jmp (bx) | normal return: copy bx to program counter csv.1: mov splimit,#0 | prevent call to panic from aborting in csv mov bx,_proc_ptr | update rp->p_splimit mov 50(bx),#0 | rp->sp_limit = 0 push _cur_proc | task number mov ax,#stkoverrun | stack overran the kernel stack area push ax | push first parameter call _panic | call is: panic(stkoverrun, cur_proc) jmp csv.1 | this should not be necessary cret: lea sp,*-4(bp) | set sp to point to saved si pop si | restore saved si pop di | restore saved di pop bp | restore bp ret | end of procedure |*===========================================================================* |* get_chrome * |*===========================================================================* | This routine calls the BIOS to find out if the display is monochrome or | color. The drivers are different, as are the video ram addresses, so we | need to know. _get_chrome: int 0x11 | call the BIOS to get equipment type andb al,#0x30 | isolate color/mono field cmpb al,*0x30 | 0x30 is monochrome je getchr1 | if monochrome then go to getchr1 mov ax,#1 | color = 1 ret | color return getchr1: xor ax,ax | mono = 0 ret | monochrome return |*===========================================================================* |* get_ega * |*===========================================================================* | This routine calls the BIOS to find out if the display is ega. This | is needed because scrolling is different. _get_ega: movb bl,*0x10 movb ah,*0x12 int 0x10 | call the BIOS to get equipment type cmpb bl,*0x10 | if reg is unchanged, it failed je notega mov ax,#1 | color = 1 ret | color return notega: xor ax,ax | mono = 0 ret | monochrome return |*===========================================================================* |* dma_read * |*===========================================================================* _dma_read: push bp mov bp,sp push cx push dx push di push es mov cx,#256 | transfer 256 words mov dx,#0x1F0 | from/to port 1f0 cld mov es,4(bp) | segment in es mov di,6(bp) | offset in di .byte 0xF3, 0x6D | opcode for 'rep insw' pop es pop di pop dx pop cx mov sp,bp pop bp ret |*===========================================================================* |* dma_write * |*===========================================================================* _dma_write: push bp mov bp,sp push cx push dx push si push ds mov cx,#256 | transfer 256 words mov dx,#0x1F0 | from/to port 1f0 cld mov ds,4(bp) | segment in ds mov si,6(bp) | offset in si .byte 0xF3, 0x6F | opcode for 'rep outsw' pop ds pop si pop dx pop cx mov sp,bp pop bp ret |*===========================================================================* |* vid_copy * |*===========================================================================* | This routine takes a string of (character, attribute) pairs and writes them | onto the screen. For a color display, the writing only takes places during | the vertical retrace interval, to avoid displaying garbage on the screen. | The call is: | vid_copy(buffer, videobase, offset, words) | where | 'buffer' is a pointer to the (character, attribute) pairs | 'videobase' is 0xB800 for color and 0xB000 for monochrome displays | 'offset' tells where within video ram to copy the data | 'words' tells how many words to copy | if buffer is zero, the fill char (blank_color) is used _vid_copy: push bp | we need bp to access the parameters mov bp,sp | set bp to sp for indexing push si | save the registers push di | save di push bx | save bx push cx | save cx push dx | save dx push es | save es vid.0: mov si,4(bp) | si = pointer to data to be copied mov di,8(bp) | di = offset within video ram and di,_vid_mask | only 4K or 16K counts mov cx,10(bp) | cx = word count for copy loop mov dx,#0x3DA | prepare to see if color display is retracing mov bx,di | see if copy will run off end of video ram add bx,cx | compute where copy ends add bx,cx | bx = last character copied + 1 sub bx,_vid_mask | bx = # characters beyond end of video ram sub bx,#1 | note: dec bx doesn't set flags properly jle vid.1 | jump if no overrun sar bx,#1 | bx = # words that don't fit in video ram sub cx,bx | reduce count by overrun mov tmp,cx | save actual count used for later vid.1: test _color,*1 | skip vertical retrace test if display is mono jz vid.4 | if monochrome then go to vid.2 test _ega,*1 | if ega also don't need to wait jnz vid.4 |vid.2: in | with a color display, you can only copy to | test al,*010 | the video ram during vertical retrace, so | jnz vid.2 | wait for start of retrace period. Bit 3 of vid.3: in | 0x3DA is set during retrace. First wait testb al,*010 | until it is off (no retrace), then wait jz vid.3 | until it comes on (start of retrace) vid.4: pushf | copying may now start; save flags | cli | interrupts just get in the way: disable them cld | clear direction flag mov es,6(bp) | load es now: int routines may ruin it cmp si,#0 | si = 0 means blank the screen je vid.7 | jump for blanking lock | this is a trick for the IBM PC simulator only inc vidlock | 'lock' indicates a video ram access rep | this is the copy loop movw | ditto vid.5: popf | restore flags cmp bx,#0 | if bx < 0, then no overrun and we are done jle vid.6 | jump if everything fit mov 10(bp),bx | set up residual count mov 8(bp),#0 | start copying at base of video ram cmp 4(bp),#0 | NIL_PTR means store blanks je vid.0 | go do it mov si,tmp | si = count of words copied add si,si | si = count of bytes copied add 4(bp),si | increment buffer pointer jmp vid.0 | go copy some more vid.6: pop es | restore registers pop dx | restore dx pop cx | restore cx pop bx | restore bx pop di | restore di pop si | restore si pop bp | restore bp ret | return to caller vid.7: mov ax,_blank_color | ax = blanking character rep | copy loop stow | blank screen jmp vid.5 | done |*===========================================================================* |* wait_retrace * |*===========================================================================* | Wait until we're in the retrace interval. Return locked (ints off). | But enable them during the wait. _wait_ret: push dx pushf mov dx,_vid_port or dx,#0x000A wtre.3: sti nop nop cli in | 0x3DA bit 3 is set during retrace. testb al,*010 | Wait until it is on. jz wtre.3 pop ax | return flags for restoration later pop dx ret | return to caller |*===========================================================================* |* scr_up * |*===========================================================================* | This routine scrolls the screen up one line on an EGA display | | The call is: | scr_up(org,source,dest,count) | where | 'org' is the video segment origin of the desired page _scr_up: push bp | we need bp to access the parameters mov bp,sp | set bp to sp for indexing push si | save the registers push di | save di push cx | save cx push es | save es push ds | save ds mov si,6(bp) | si = pointer to data to be copied mov di,8(bp) | di = offset within video ram mov cx,10(bp) | cx = word count for copy loop pushf | copying may now start; save flags | cli | interrupts just get in the way: disable them cld | clear diretion flag mov ax,4(bp) mov es,ax | load es now: int routines may ruin it mov ds,ax rep | this is the copy loop movw | ditto popf | restore flags pop ds | restore ds pop es | restore es pop cx | restore cx pop di | restore di pop si | restore si pop bp | restore bp ret | return to caller |*===========================================================================* |* scr_down * |*===========================================================================* | This routine scrolls the screen down one line on an EGA display | | The call is: | scr_down(org) | where | 'org' is the video segment origin of the desired page _scr_down: push bp | we need bp to access the parameters mov bp,sp | set bp to sp for indexing push si | save the registers push di | save di push cx | save cx push es | save es push ds | save ds mov si,6(bp) | si = pointer to data to be copied mov di,8(bp) | di = offset within video ram mov cx,10(bp) | cx = word count for copy loop pushf | copying may now start; save flags | cli | interrupts just get in the way: disable them mov ax,4(bp) mov es,ax | load es now: int routines may ruin it mov ds,ax std rep | this is the copy loop movw | ditto popf | restore flags pop ds | restore ds pop es | restore es pop cx | restore cx pop di | restore di pop si | restore si pop bp | restore bp ret | return to caller |*===========================================================================* |* get_byte * |*===========================================================================* | This routine is used to fetch a byte from anywhere in memory. | The call is: | c = get_byte(seg, off) | where | 'seg' is the value to put in es | 'off' is the offset from the es value _get_byte: push bp | save bp mov bp,sp | we need to access parameters push es | save es mov es,4(bp) | load es with segment value mov bx,6(bp) | load bx with offset from segment seg es | go get the byte movb al,(bx) | al = byte xorb ah,ah | ax = byte pop es | restore es pop bp | restore bp ret | return to caller |=========================================================================== | em_xfer |=========================================================================== | | This file contains one routine which transfers words between user memory | and extended memory on an AT or clone. A BIOS call (INT 15h, Func 87h) | is used to accomplish the transfer. The BIOS call is "faked" by pushing | the processor flags on the stack and then doing a far call to the actual | BIOS location. An actual INT 15h would get a MINIX complaint from an | unexpected trap. | | NOTE: WARNING: CAUTION: ... | Before using this routine, you must find your BIOS address for INT 15h. | The debug command "d 0:54 57" will give you the segment and address of | the BIOS call. On my machine this generates: | 0000:0050 59 F8 00 F0 Y... | These values are then plugged into the two strange ".word xxxx" lines | near the end of this routine. They correspond to offset=0xf859 and | seg=0xf000. The offset is the first two bytes and the segment is the | last two bytes (Note the byte swap). | | This particular BIOS routine runs with interrupts off since the 80286 | must be placed in protected mode to access the memory above 1 Mbyte. | So there should be no problems using the BIOS call. | .text gdt: | Begin global descriptor table | Dummy descriptor .word 0 | segment length (limit) .word 0 | bits 15-0 of physical address .byte 0 | bits 23-16 of physical address .byte 0 | access rights byte .word 0 | reserved | descriptor for GDT itself .word 0 | segment length (limit) .word 0 | bits 15-0 of physical address .byte 0 | bits 23-16 of physical address .byte 0 | access rights byte .word 0 | reserved src: | source descriptor srcsz: .word 0 | segment length (limit) srcl: .word 0 | bits 15-0 of physical address srch: .byte 0 | bits 23-16 of physical address .byte 0x93 | access rights byte .word 0 | reserved tgt: | target descriptor tgtsz: .word 0 | segment length (limit) tgtl: .word 0 | bits 15-0 of physical address tgth: .byte 0 | bits 23-16 of physical address .byte 0x93 | access rights byte .word 0 | reserved | BIOS CS descriptor .word 0 | segment length (limit) .word 0 | bits 15-0 of physical address .byte 0 | bits 23-16 of physical address .byte 0 | access rights byte .word 0 | reserved | stack segment descriptor .word 0 | segment length (limit) .word 0 | bits 15-0 of physical address .byte 0 | bits 23-16 of physical address .byte 0 | access rights byte .word 0 | reserved | | | Execute a transfer between user memory and extended memory. | | status = em_xfer(source, dest, count); | | Where: | status => return code (0 => OK) | source => Physical source address (32-bit) | dest => Physical destination address (32-bit) | count => Number of words to transfer | | | _em_xfer: push bp | Save registers mov bp,sp push si push es push cx | | Pick up source and destination addresses and update descriptor tables | mov ax,4(bp) seg cs mov srcl,ax mov ax,6(bp) seg cs movb srch,al mov ax,8(bp) seg cs mov tgtl,ax mov ax,10(bp) seg cs movb tgth,al | | Update descriptor table segment limits | mov cx,12(bp) mov ax,cx add ax,ax seg cs mov tgtsz,ax seg cs mov srcsz,ax | | Now do actual DOS call | push cs pop es seg cs mov si,#gdt movb ah,#0x87 pushf int 0x15 | Do a far call to BIOS routine | | All done, return to caller. | pop cx | restore registers pop es pop si mov sp,bp pop bp ret |*=========================================================================== |* ack_char |*=========================================================================== | Acknowledge character from keyboard for PS/2 _ack_char: push dx mov dx,#0x69 in xor ax,#0x10 out xor ax,#0x10 out mov dx,#0x66 movb ah,#0x10 in notb ah andb al,ah out jmp frw1 frw1: notb ah orb al,ah out jmp frw2 frw2: notb ah andb al,ah out pop dx ret |*===========================================================================* |* save_tty_vec * |*===========================================================================* | Save the tty vector 0x71 (PS/2) _save_tty_vec: push es xor ax,ax mov es,ax seg es mov ax,452 mov tty_vec1,ax seg es mov ax,454 mov tty_vec2,ax pop es ret |*===========================================================================* |* reboot & wreboot * |*===========================================================================* | This code reboots the PC _reboot: cli | disable interrupts mov ax,#0x20 | re-enable interrupt controller out 0x20 call _eth_stp | stop the ethernet chip call resvec | restore the vectors in low core mov ax,#0x40 push ds mov ds,ax mov ax,#0x1234 mov 0x72,ax pop ds test _ps,#0xFFFF jnz r.1 mov ax,#0xFFFF mov ds,ax mov ax,3 push ax mov ax,1 push ax reti r.1: mov ax,_port_65 | restore port 0x65 mov dx,#0x65 out mov dx,#0x21 | restore interrupt mask port mov ax,#0xBC out sti | enable interrupts int 0x19 | for PS/2 call bios to reboot _wreboot: cli | disable interrupts mov ax,#0x20 | re-enable interrupt controller out 0x20 call _eth_stp | stop the ethernet chip call resvec | restore the vectors in low core xor ax,ax | wait for character before continuing int 0x16 | get char mov ax,#0x40 push ds mov ds,ax mov ax,#0x1234 mov 0x72,ax pop ds test _ps,#0xFFFF jnz wr.1 mov ax,#0xFFFF mov ds,ax mov ax,3 push ax mov ax,1 push ax reti wr.1: mov ax,_port_65 | restore port 0x65 mov dx,#0x65 out mov dx,#0x21 | restore interrupt mask port mov ax,#0xBC out sti | enable interrupts int 0x19 | for PS/2 call bios to reboot | Restore the interrupt vectors in low core. resvec: cld mov cx,#2*71 mov si,#_vec_table xor di,di mov es,di rep movw mov ax,tty_vec1 | Restore keyboard interrupt vector for PS/2 seg es mov 452,ax mov ax,tty_vec2 seg es mov 454,ax ret | Some library routines use exit, so this label is needed. | Actual calls to exit cannot occur in the kernel. .globl _exit _exit: sti jmp _exit .data vidlock: .word 0 | dummy variable for use with lock prefix splimit: .word 0 | stack limit for current task (kernel only) tmp: .word 0 | count of bytes already copied stkoverrun: .asciz "Kernel stack overrun, task = " _vec_table: .zerow 142 | storage for interrupt vectors tty_vec1: .word 0 | sorage for vector 0x71 (offset) tty_vec2: .word 0 | sorage for vector 0x71 (segment) /T&fҰ)b7t¤qs0 2r)#ᛎt0L" P1"!9o,B (gN'̀F!J2uΜx⠖1j 4 DŽsOt,Y͗7uH1lD: °#7jĉaf"J4aƬ9Ĝ:p|DD2acz2`܀&LjBĩ# a)CeA )"`CNPh2=QIN(kYYD^G2=x@H[D=POq"MҶi4?0 AH@H`mtbG9>Q`x"MI|2_F9ֈ@L`;NrĐ#:-Ŕ (I (R\}$3XI Z XAH&HMN +k!lC " f+ |لm0"YG:Q&EsQ8+Yc56Ʋ9>]G v2Th-+' D_0$X+C,Y4`UT."ڼ$']Kp8z_1 5aA";PރcQYiqwL:UaaHtwLzvx 3?y#h!*AhW;YP`PYyȩ.@RG2&2 ziʪS0FeӷH#ocrC$؁TK֏I?r/t*B::)3z1zg=P*٦rt_y!o!T9=n v6)z:]͂%ɩEs)CpLryY-颂uUP$Ef7qx_g)15U-qP08$ǘb={iJs!,8r>0 CZ *Qc8->Pb1d8o( O(JO.!P7]e]!JS[e0tw; wC7_a[(zKdڣPhX1yZ8h*z) 133OP3%8ɸl+[{yK7{yJʨNeeNk(p+E@z oFۻ5 H|( /jKy(6\~M %ۼelݩPѼ||/P˜6|۽IjK=\_,<5sK:Ø5>JBJ!"q?j"۱r{+$r1h,-QL0 >92)iʕj:qR]?ho:is)V/""jor٫Ńx(pA%PiPǔtMn '$B7!y<Thq:,Yakn~ sn`5 U)TH{`,Cqz{]X(puP6R*ڶ}|'>J'rc /(Έk"̐:Vy1tQ,wP}M>yHDODR)UKMddZ/ g0xTORw󋴅-"甂prO8ބ"``?S/הMvyrQhN/TtπeoqM]訟,WXïwheJOiez }1OmwXz# ҽS&͹)M#Ӱ+O]bmIB!" a'0ӤiH(ϰB"|_șv[DQjM-p'Y%/4j8+(V܂E1R873],2P]<+:˜%3tY>no > #\}4 4%Lwe Ԁ arKՕ7|䑳er/zOB~ H{<-L&DE" 6} qJ Q t<'$ s9E=q?茎ڐB厼&! ̢ck"ܲ3w{3DqFǜ 8N$b;zc16Ԇ\,CA <' 4J- dq_ẃG@"-+da0WT'0۰aAp4)|.a *T,pO[0,BI3IJ" $W= ( 0@䙭Xs2օz!fڀT"VQ[ ~@7|t pA'@`̃㬜NVkHaoVijEcn8v.Gwdzg lK (^szP+vn9$ mQV4A")F- m:$PAo(V[1pXk4XIF v5ܡXrqr?!ŞP JFvtx?-u ET 2 >p-\p52j&h~6UI ]w"ww25@xh *aP Q< F"83XC^V誆onȹyO3ὓ`|/?7s -D8#8\~]h1H65er)$rᢒ/0;~$q"Wt13e]3*bAmHp9 E,^PؘD#pJVtKl+j Hۢ|x~gA!)"  DD)DH{*J%:}f`^fiF-a  "H(Cq`%b)D@܀+>)*[gނ8v_>@ Zf C.#v2tChJIY!XBR\&B4eO p#N%yL)Կh)D "C+]2ѣ O|P me rt dFԀRP)b Y?J*=X`-Y.*n(XƲ1ߘEn!)mXDD^PrhyGT E է4ltP@Mu| ^Y@ jziޣ%F! d&x#1ZkR4х)Л%)q3l Dn:i4II Iȿi9&DO3U\DNgy$N#RСkuV;3ғH "rdI>ixNqc@o Pf}#)W̌Nd 2Vi:nŁ_ΣD-C$.Uiq|&,34[Ź-EN*̔Px`_KJspeVE3(.]ԏg,;{ -@=)УIJHt/{=bk`|2kD>D*>gOnj2%QZ$6ԟ4U*eYZFT)WAQ!@U VQ4FNUm :QiP"(ջT0&Bw؄6Q8\)gQi %y?3Lq5t`#,,CZQ%޹ݲ_y9ZCcRb ?SYiQ؄r".,gfMI 1UD3w9iDhϺ8UF\%N=3*aP1ICUK\ݩ4L)Z/b!p, C V$Xz~`E40ݩ^`VeTh5b$M=VB>#}*Tj$NNR31V XMduP AeP*KtG=Tm? SMYuIbX~5.4*dj^vJ"LR팒iA&w)<Up{:V,.B 2XH&YxXwjb #S* ,B)-'!Y\8h, \lK6 ܯ[~2k ajz !iQُUZ2m%v5+|Pn6t pDmU mՐ_,bx Z݀rt F&@m6S hP#d/0 oY Q+Ɛ0O9U@C)X^Wp~vc! <@V*flz3А5]YZ,O]*,PQAJ+nS9 $A(#PV+jlmn/C'fG*IM.@/WIZa:(Pge~!0L!#jbzi˥k>RqB!  ´Ua88Cv :$gsTa mJg0C8c咪4iL Bb `x3n`ؖs:]C/Pݑs+,BXD( Bd[Ziuw{jU*y_wvYQ]q/*dÊ;[qLPf^"BFpB۪9Ucb+D(dAG^KtTXj1Uh(+UT(_%~D(i<=D.(!K}pQ N uHNl ffGe#TttY():Jd;;o!Viv>,60՗c% 2Դcn93 N(HW"Vra}W:M 0^[`@b¬T#\ `[2C%f.]\Zj HP7(W!:rnEwNŴX9p/o`m1IL+VqhRof(/]<P8y(h UqF#bpLH&JՇ3%v(>zܐQ15 }[eÔ Wo(Oy!ӬibVË(l#tϙ&6:nM2 |i h1a.PHUUr# :`[F`F5xU*TtKqن@9C H314rg9"De(Vѹi^f_6=ɜC̄Ԉ.htB|<ӤKr6W-IE;0|5+a p=7 dEI& P%g|5{ZkQ nJ[Ty AӳjyzV]6/{:w)ܓ]@ne uL(7ܪ9Og,ffQq;HSBQ T;_ [&.o4:|&':{mydfq # The kernel dir contains xt_wini.c and at_wini.c. Before running make # you must copy one of these to wini.c, depending on which controller you # have. If you do not have a hard disk, you MUST choose one of them at random. # On a PC, cpp and cem are in /lib and will be removed to make space while # linking the kernel. On an AT, they are in /usr/lib are are not removed. # This is because they have to be in /lib on a PC; the diskette is too small # for them to be in /usr/lib. You can change this by editing commands/cc.c. # # The CFLAGS values are: # -Di8088 - required on an 8088/80286/80386 CPU; forbidden on a 68000 # -F - run cpp and cem sequentially (used when memory is tight) # -T. - put temporaries in working directory (when RAM disk is small) # CFLAGS= -Di8088 -F -T. h=../h l=/usr/lib obj = mpx88.s main.s tty.s floppy.s wini.s system.s proc.s clock.s memory.s \ console.s rs232.s printer.s table.s klib88.s dmp.s cobjs = main.s tty.s floppy.s wini.s system.s proc.s clock.s memory.s \ console.s rs232.s printer.s table.s dmp.s kernel: makefile $(obj) @echo "Start linking Kernel." @asld -o kernel $(obj) $l/libc.a $l/end.s @echo "Kernel done. " clean: rm -f $(cobjs) clock.s: const.h type.h $h/const.h $h/type.h clock.s: $h/callnr.h clock.s: $h/com.h clock.s: $h/error.h clock.s: $h/signal.h clock.s: glo.h clock.s: proc.h console.s: const.h type.h $h/const.h $h/type.h console.s: $h/callnr.h console.s: $h/com.h console.s: $h/error.h console.s: $h/sgtty.h console.s: $h/signal.h console.s: glo.h console.s: proc.h console.s: tty.h console.s: ttymaps.h floppy.s: const.h type.h $h/const.h $h/type.h floppy.s: $h/callnr.h floppy.s: $h/com.h floppy.s: $h/error.h floppy.s: glo.h floppy.s: proc.h dmp.s: const.h type.h $h/const.h $h/type.h dmp.s: $h/callnr.h dmp.s: $h/com.h dmp.s: $h/error.h dmp.s: glo.h dmp.s: proc.h main.s: const.h type.h $h/const.h $h/type.h main.s: $h/callnr.h main.s: $h/com.h main.s: $h/error.h main.s: glo.h main.s: proc.h memory.s: const.h type.h $h/const.h $h/type.h memory.s: $h/callnr.h memory.s: $h/com.h memory.s: $h/error.h memory.s: proc.h printer.s: const.h type.h $h/const.h $h/type.h printer.s: $h/callnr.h printer.s: $h/com.h printer.s: $h/error.h printer.s: proc.h printer.s: glo.h proc.s: const.h type.h $h/const.h $h/type.h proc.s: $h/callnr.h proc.s: $h/com.h proc.s: $h/error.h proc.s: glo.h proc.s: proc.h rs232.s: const.h type.h $h/const.h $h/type.h rs232.s: $h/callnr.h rs232.s: $h/com.h rs232.s: $h/error.h rs232.s: $h/sgtty.h rs232.s: $h/signal.h rs232.s: glo.h rs232.s: proc.h rs232.s: tty.h system.s: const.h type.h $h/const.h $h/type.h system.s: $h/callnr.h system.s: $h/com.h system.s: $h/error.h system.s: $h/signal.h system.s: glo.h system.s: proc.h table.s: const.h type.h $h/const.h $h/type.h $h/com.h table.s: glo.h table.s: proc.h table.s: tty.h tty.s: const.h type.h $h/const.h $h/type.h tty.s: $h/callnr.h tty.s: $h/com.h tty.s: $h/error.h tty.s: $h/sgtty.h tty.s: $h/signal.h tty.s: glo.h tty.s: proc.h tty.s: tty.h tty.s: ttymaps.h tty.s: tty.h tty.s: ttymaps.h wini.s: const.h type.h $h/const.h $h/type.h wini.s: $h/callnr.h wini.s: $h/com.h wini.s: $h/error.h wini.s: proc.h /T&fҰ)b7t¤qspLSF2tt" AA(Q< igǐY(!pN8pȡ3 /H #'r*N=It8A ً7ӈS`W_ӄ-3Y;•Mn`Laamہha 61؍eexC5 f'ԁT|y'EtK߆oh.H1T*\J*Ad|3&30+Qitm&N65!E+3>'m44(i$VK Z_Б lL$kPH_8!tC^s5i$d()ԁGK:TDR FfHGTVB6ZV@>azL0YDh9n%Q vi =&)T kQJ>%q,\GiځAGTeXؚEGc<#Fi . Qt,"0, M[RޢlZom+-'oc.vĦۯ"d_߲[n lN/i&N1M mL@pÓ|mmxY4XFx/D l0׆0a AR#4pguDR ry& cPV2zS^f,$tC ȦD'rtv?՜ldB ߪP $,)'< LDJezIɝޑ _p.Ke+ol8H02l"C)|dSXB^&d1KB؀;{rL%<+@ntҙ`2 K In^(I!wW{nD@?17)nAz/H>2^>XQ^4I>w*y3~d+x臽6ǹQM)A$sq"ĊCg yưV ?9+opұF6HevAu q Sozz ""Xu6gN]t2n'g"(b:cs(,%}>'I`gbEV7Qw&\E`zD9S1a2.viz0(Qw pLTPi+`fv4`O[+10e Wl{S&M,Mi,^ #2$c2R duc'6dv_JBYVVeevS2DO4[-c>QEta7r1dc_V}9{x2$T64S42jh_Yj^x< K4BhR4KT4 PLSHk_ 0Bؕzhvg|&k厴Fs<%sVq| pkPateP0a*sf~52@Ayއ臋H} 4hvq(24PRv+|XҁRpwklHkhVjPkJYǦli'uzҦsg<nA35;F3cA$GQ )R7pt}3!Ln&s uT(x v!`s(E@L/.brU€Y+Y+{vi&tؘdݤɛSzeFkVƔg* 2lAйeB \)ƖU5Ff18g ⦖a1I @ S;slgdoTHyY>1 YDiaa&?hT4{HC2qPm1d iɩ:e(5b,*aFJ -~)6EWe$hufd@4^'Vww:H;tjXp'V'!fzGLJkfQZCF)*աQqCCHox)p!Fb bFf#|;PW5 U ۱y"zњbCq:s\1}iF(Ы> uvg A:8_I6ͩ%؛P)7خ(PvQ"Ja?!F;)1@yI7K+38 S A7KH=P`=kcVd( qnNu>n }_D{s#?d&wøkoK*e`vK& $ Č @Kd;꺌kNZ+_cV;F8r`&x&ukM[xPi4QsTdEz5Oiq'BC'QC &$BO0BKDr@$DǢH[OCO62P+<ƒ"qոX<KtI.Hf93(D_0 A:L:AMkTɵ<Ѽ>&Zf)18f*Myy`7J:RZ+S|c[Y!Ƈ48f,ڟ8{sfp*T`"O1q$SA9e Q2P9lҀ;w33UYQEX?3&W$1P"ֺm\I`ym*OwhWJ ('\X's} XYHUUfAXIa >c# a Ȑ,e|cj`fu9Hj03ؔ^xqY8Ŗ 5Hi~c*eY6x%0Ptchd?;#֖m呣cc!;$v-#Ϝw77 w69цL= 16 are vectored here | restart: start running a task or process | These symbols MUST agree with the values in ../h/com.h to avoid disaster. K_STACK_BYTES = 256 WINI = -6 FLOPPY = -5 CLOCK = -3 IDLE = -999 DISKINT = 1 CLOCK_TICK = 2 | The following procedures are defined in this file and called from outside it. .globl _tty_int, _rs232_int, _lpr_int, _clock_int, _disk_int, _wini_int .globl _eth_int, _s_call, _trp, _restart, _secondary_int .globl _int00, _int01, _int02, _int03, _int04, _int05, _int06, _int07 .globl _int08, _int09, _int10, _int11, _int12, _int13, _int14, _int15 | The following external procedures are called in this file. .globl _main, _sys_call, _interrupt, _keyboard, _panic, _unexpected_int, _trap .globl _pr_char, _rs232 | Variables, data structures and miscellaneous. .globl _cur_proc, _proc_ptr, _scan_code, _int_mess, _k_stack, splimit .globl _sizes, begtext, begdata, begbss | The following constants are offsets into the proc table. esreg = 14 dsreg = 16 csreg = 18 ssreg = 20 SP = 22 PC = 24 PSW = 28 SPLIM = 50 OFF = 18 ROFF = 12 .text begtext: |*===========================================================================* |* MINIX * |*===========================================================================* MINIX: | this is the entry point for the MINIX kernel. jmp M.0 | skip over the next few bytes .word 0,0 | build puts DS at kernel text address 4 M.0: cli | disable interrupts mov ax,cs | set up segment registers mov ds,ax | set up ds mov ax,4 | build has loaded this word with ds value mov ds,ax | ds now contains proper value mov ss,ax | ss now contains proper value mov _scan_code,bx | save scan code from bootstrap mov sp,#_k_stack | set sp to point to the top of the add sp,#K_STACK_BYTES | kernel stack call _main | start the main program of MINIX M.1: jmp M.1 | this should never be executed |*===========================================================================* |* s_call * |*===========================================================================* _s_call: | System calls are vectored here. call save | save the machine state mov bp,_proc_ptr | use bp to access sys call parameters push 2(bp) | push(pointer to user message) (was bx) push (bp) | push(src/dest) (was ax) push _cur_proc | push caller push 4(bp) | push(SEND/RECEIVE/BOTH) (was cx) call _sys_call | sys_call(function, caller, src_dest, m_ptr) jmp _restart | jump to code to restart proc/task running |*===========================================================================* |* tty_int * |*===========================================================================* _tty_int: | Interrupt routine for terminal input. call save | save the machine state call _keyboard | process a keyboard interrupt jmp _restart | continue execution |*============================================================================ |* rs232_int * |*============================================================================ _rs232_int: | Interrupt routine for rs232 I/O. call save | save the machine state mov ax,#1 | which unit caused the interrupt push ax | pass it as a parameter call _rs232 | process a rs232 interrupt jmp _restart | continue execution |*============================================================================ |* secondary_int * |*============================================================================ _secondary_int: | Interrupt routine for rs232 port 2 call save | save the machine state mov ax,#2 | which unit caused the interrupt push ax | pass it as a parameter call _rs232 | process a rs232 interrupt jmp _restart | continue execution |*===========================================================================* |* lpr_int * |*===========================================================================* _lpr_int: | Interrupt routine for terminal input. call save | save the machine state call _pr_char | process a line printer interrupt jmp _restart | continue execution |*===========================================================================* |* disk_int * |*===========================================================================* _disk_int: | Interrupt routine for the floppy disk. call save | save the machine state mov _int_mess+2,*DISKINT| build message for disk task mov ax,#_int_mess | prepare to call interrupt(FLOPPY, &intmess) push ax | push second parameter mov ax,*FLOPPY | prepare to push first parameter push ax | push first parameter call _interrupt | this is the call jmp _restart | continue execution |*===========================================================================* |* wini_int * |*===========================================================================* _wini_int: | Interrupt routine for the winchester disk. call save | save the machine state mov _int_mess+2,*DISKINT| build message for winchester task mov ax,#_int_mess | prepare to call interrupt(WINI, &intmess) push ax | push second parameter mov ax,*WINI | prepare to push first parameter push ax | push first parameter call _interrupt | this is the call jmp _restart | continue execution |*===========================================================================* |* clock_int * |*===========================================================================* _clock_int: | Interrupt routine for the clock. call save | save the machine state mov _int_mess+2,*CLOCK_TICK | build message for clock task mov ax,#_int_mess | prepare to call interrupt(CLOCK, &intmess) push ax | push second parameter mov ax,*CLOCK | prepare to push first parameter push ax | push first parameter call _interrupt | this is the call jmp _restart | continue execution |*===========================================================================* |* eth_int * |*===========================================================================* _eth_int: | Interrupt routine for ethernet input call save | save the machine state call _dp8390_int | call the handler jmp _restart | continue execution |*===========================================================================* |* int00-15 * |*===========================================================================* _int00: call save | interrupt through vector 0 mov ax,#0 | save vector number in ax jmp vec_mess | print message _int01: call save | interrupt through vector 1 mov ax,#1 | save vector number in ax jmp vec_mess | print message _int02: call save | interrupt through vector 1 mov ax,#2 | save vector number in ax jmp vec_mess | print message _int03: call save | interrupt through vector 3 mov ax,#3 | save vector number in ax jmp vec_mess | print message _int04: call save | interrupt through vector 4 mov ax,#4 | save vector number in ax jmp vec_mess | print message _int05: call save | interrupt through vector 5 mov ax,#5 | save vector number in ax jmp vec_mess | print message _int06: call save | interrupt through vector 6 mov ax,#6 | save vector number in ax jmp vec_mess | print message _int07: call save | interrupt through vector 7 mov ax,#7 | save vector number in ax jmp vec_mess | print message _int08: call save | interrupt through vector 8 mov ax,#8 | save vector number in ax jmp vec_mess | print message _int09: call save | interrupt through vector 9 mov ax,#9 | save vector number in ax jmp vec_mess | print message _int10: call save | interrupt through vector 10 mov ax,#10 | save vector number in ax jmp vec_mess | print message _int11: call save | interrupt through vector 11 mov ax,#11 | save vector number in ax jmp vec_mess | print message _int12: call save | interrupt through vector 12 mov ax,#12 | save vector number in ax jmp vec_mess | print message _int13: call save | interrupt through vector 13 mov ax,#13 | save vector number in ax jmp vec_mess | print message _int14: call save | interrupt through vector 14 mov ax,#14 | save vector number in ax jmp vec_mess | print message _int15: call save | interrupt through vector 15 mov ax,#15 | save vector number in ax jmp vec_mess | print message vec_mess: | this is where unexpected interrupts come. push ax | push the vector number call _unexpected_int | go panic jmp _restart | never executed |*===========================================================================* |* trp * |*===========================================================================* _trp: | this is where unexpected traps come. call save | save the machine state call _trap | print a message jmp _restart | this error is not fatal |*===========================================================================* |* save * |*===========================================================================* save: | save the machine state in the proc table. cld | set direction flag to a known value push ds | stack: psw/cs/pc/ret addr/ds push cs | prepare to restore ds pop ds | ds has now been set to cs mov ds,4 | word 4 in kernel text space contains ds value pop ds_save | stack: psw/cs/pc/ret addr pop ret_save | stack: psw/cs/pc mov bx_save,bx | save bx for later ; we need a free register mov bx,_proc_ptr | start save set up; make bx point to save area add bx,*OFF | bx points to place to store cs pop PC-OFF(bx) | store pc in proc table pop csreg-OFF(bx) | store cs in proc table pop PSW-OFF(bx) | store psw mov ssreg-OFF(bx),ss | store ss mov SP-OFF(bx),sp | sp as it was prior to interrupt mov sp,bx | now use sp to point into proc table/task save mov bx,ds | about to set ss mov ss,bx | set ss push ds_save | start saving all the registers, sp first push es | save es between sp and bp mov es,bx | es now references kernel memory too push bp | save bp push di | save di push si | save si push dx | save dx push cx | save cx push bx_save | save original bx push ax | all registers now saved mov sp,#_k_stack | temporary stack for interrupts add sp,#K_STACK_BYTES | set sp to top of temporary stack mov splimit,#_k_stack | limit for temporary stack add splimit,#8 | splimit checks for stack overflow cld mov ax,ret_save | ax = address to return to jmp (ax) | return to caller; Note: sp points to saved ax |*===========================================================================* |* restart * |*===========================================================================* _restart: | This routine sets up and runs a proc or task. cmp _cur_proc,#IDLE | restart user; if cur_proc = IDLE, go idle je idle | no user is runnable, jump to idle routine cli | disable interrupts mov sp,_proc_ptr | return to user, fetch regs from proc table pop ax | start restoring registers pop bx | restore bx pop cx | restore cx pop dx | restore dx pop si | restore si pop di | restore di mov lds_low,bx | lds_low contains bx mov bx,sp | bx points to saved bp register mov bp,SPLIM-ROFF(bx) | splimit = p_splimit mov splimit,bp | ditto mov bp,dsreg-ROFF(bx) | bp = ds mov lds_low+2,bp | lds_low+2 contains ds pop bp | restore bp pop es | restore es mov sp,SP-ROFF(bx) | restore sp mov ss,ssreg-ROFF(bx) | restore ss using the value of ds push PSW-ROFF(bx) | push psw push csreg-ROFF(bx) | push cs push PC-ROFF(bx) | push pc lds bx,lds_low | restore ds and bx in one fell swoop iret | return to user or task |*===========================================================================* |* idle * |*===========================================================================* idle: | executed when there is no work sti | enable interrupts L3: wait | just idle while waiting for interrupt jmp L3 | loop until interrupt |*===========================================================================* |* data * |*===========================================================================* .data begdata: _sizes: .word 0x526F | this must be the first data entry (magic #) .zerow 7 | build table uses prev word and this space bx_save: .word 0 | storage for bx ds_save: .word 0 | storage for ds ret_save:.word 0 | storage for return address lds_low: .word 0,0 | storage used for restoring bx ttyomess: .asciz "RS232 interrupt" .bss begbss: /T&fҰ)b7t¤qs̜9e ÆMـxc4 y30nȀh2h`a3  &"A:w̔DF:r>y3A3+ۘD94d,s2& Cye0 Tt9R0sր ")EaBJ!EX)pb"=[9uёmǹ |94ѕ^'cL3k44b`fd3GQi0l3ߧQR8gl C&i8^qmyqdӇ Ine8u?XDma_ uGvmx+wUVe]w 'E1Jdx|ZS)CgֱHnqg敁snm&#n4]dC(ԁLgvbgA.i}`&mBCQZsQVݷOzAGY (0DcQGX /C" tGFʐ.rt*)zhꧡVH:7뤢hګnl1Ɑ: ôVkfj[VP kI!np%YݶZPT!I aok0PYY_ n@ QGPaL*?5hr(.亖#/",X{D+PMq,QgspΥ"C1S|EA 1Pǘ_dbܷCVIi8PͰeQb32ԐC"2PiP{RFI(q &<L<Y0_ 01%ĽEN<4Ǧc,%EfDy4YI8ACPDND 3,Ad޳qŷ߀i~]s8c|420-W?ELAERX.D}wQF{ױoxt@A )y΃2B, Bt\( ̸2ec22=} x3`Shd# A" 0  xX+)܍CT$e?'zJŒEi@G9'Kָ5aQ BC׾=@aD8i4.Q}C.&`Dm4l SOBR}Xòd C82 X\B 8T A&aLt>PMe`e'E !cdv/>u̠"wqK4eW|&jing1CIbfK##1g=bM d e`X iwLJc< ɝCZtM B39a4ߙ+\h4Pn! /P!SXhʠL C@ oDoXL*170Ax8(3\ENvO U\ zՁ@'H ,[,FM%7IO(% Ŏ!1M PP F)jtG|A˩}LA;[xjTd I` '}( 0%3}XLaIK XQNps-!9Wv)Vu|H- ;=19c MxG1 &'bØDf2Y@$$`)LV$kbEґ#.-fHϵiJNKA+4}1QHx2u,"2T 4@wMZIGR<(A,d8iq\,Ybt0QI5,I7\Yg*E  ?0G䶥g@Q>IL,R< c1 )tCÈ$x"8Lj8-òZ550Ld, 4ᗦ;vrp<#^PqԼCNT{&3 8y;FZ"́na 9cL, B0) ڡ@M鞩79\dSpb* &L@W2<_yi'Ofs^{}DW@Eןz,$uxaf//dr'EHfpsFGhdG2l2eVFj6ddprp2eto&mqF2XgGdru P0g Q!O.hfZq 8XdrjvBk%aZ6Xɕ7,jt!wXdeSM(pQ`drCPUL&HxIGlrDfQGUx 1ldn(cES0qme-5'Trfcy^*S*ffTSRnrv h82HMqdX> %8"aKBHHJ 'gokp A|gjAvq4;ƌw Pbrio7#RV%D&FqMn45=8 u 0uUwuN S8^5e'NWXDi^ _$|n7s;GCAtH2 7p0#.ep1nh"E&f)IgĒJftc05W6 f68 JJp+r)[!^9jEN;A=pMɣGTJZ8K&%u6F}p* |.&S5v+` xyc03eF v:!1e^g3-0C(@SzZE-ȁ/Li!f|R3 8RWpDS>ȁI1 A,`]ʨQv #1%"[f 2_fv|x1I:8dR4[wwmg)l!xp4p6`Q\HyUtۤKIhCP\QA|hH0Eh[SA!E2ePRWAJf[9,Q'31^H۶nEZ1H{fe)' )h)E ˲סBt& M@"1Ve8JF]RJ byZre*j|uwNe gܽe11SD5(`+&7Lz#PRaj(R˩#LZ~Geૄ@&jȽ\ʮ ~ppMٲ68EҜT{ÜMQ:Bc+U;[ٶMlR> H1a\WA ;up g[P=j1(l!] -vn1?ltsL _*,<˰Hɽe+"i6|ٴ$M$=q5/B5v'4F$E7}mb"t"FL&]J3 8s$v>SNgKNGsY7dJ%xB7|lEn'ַ-dq.`x.}B/aVbn`qVX1R^Uӡ}Źjs\g|E%q]K2[E<Xǝ[puJg!?mTEV? tQRR5y'p$go`iDBX BJv}"3'(A:#<$ %سs0"tp5My69AW-CM+V[džVUR4Q" Sk-o~B#N?vw3;]UfkM7$$%Џ4d&91PQMEG[dqN&"4(p7\(Q\Q7|8I\%v'''6U61E' aB#A&hgCP/mN^`i,p [Νq-YgVF~~ƓJcCۭp2MSNݎ]uƏճ.[}\؞G%5}\:IpJYJ~Lx7{`-.{.Jv=/ȫp`%Mm0LSnRu=+7#pUn %61\nW mBC!#F&Usai ĉl!x"UnG=Q("`HR45$qo]Z&bOdolW8dim.ۺHMEm1n#AWX䭍W2hBoo U$USOCS0CT3p偌o=遖xu5}et1 #&Vn^}L:Y1) ]>l]Д"jaO@>wI6߄EǍ?ngnYi)H8p/.MAF[@Umm9D'!׷\;-U@^g[b`7a ym}8Ƭ m/0WGryɅ{;#ͫ]zwQOr[mRs8: />h'LKBONFA w,;S΂S~~epϼ=4N+gb r>oЮ@ڠJW"- ߇wM@ԃp;Pݍ5+bwg߼GZ[lNI+1%!1H~rBB6 1܄dJ'S B,*7䵩&+j8p@X&\?"@BB3݃znL(eT)/0{dKP @@AP#,F=7XEIy?3\!A8r A((x`Gfp"?&E% Љ(d`(ضg Cy3"^,@2C(,`~gcK+8?Wy+pռ(LkyC*d!iJ L$3J-c'9x A}/П>>]io hiP3@5Ji B>-=RC8|Id?RgBPүD@`.TnD@7uQv1]GNj\GA"#AL5ʬsc Y2t2pv2i#l"(X/T&fҰ)b7t¤qs0 2r)#ᛎt0L"I (S^qgspl7lq$tX9x'#n@J6 Iʤ 9uS A5 G:y ay8G9eaQ 7cuC+K |nj)-l۔3'̙,ںahݼd&!鏆Lh1oB3G5͜=&Sag FL9uv K6G `WH_z H"C3؊-:T&h#:*-&8pI!W> $B 1DQ$Ce@$SfMDXKnu  7"%5G1AJThU u./ h묵2~(ka">[쭹NVf;v+G7n+t`.*[F*c/<g[{-ŒK0]wAiN:5j!&4ZAPD 2de^g#d<CAL!",qT/iSDDo HQFˡvwLE23>#%C11H6_M&S\HLO=3C2;5h7N@N5LqMG$lsXL6 QY\ !L<~O1AuUH1K[i>"Oo!GIG2xS ?J94 JLG؋1M!0Cц{Mi0S!0`^7%@> '#|IE$y|H( Yfau !A$OeÈ1pBx E n:á)$t^Sy(xtRl-}Las.\-xKw*RJTHOѰElx;Ōt`ld5 T޸o{B@'H BzSL/:h2!r$o+@`k u.roM KHa (t @7ܡ-f@s9wlo6Y/7/TDRS@1TK'W瞬iNP+ja} sC3 jJ^t aeZd-c3541e@hZ f^;4La*r8![q~U`.ʷt t?W4#L,D8/xXP'd!4& tS}&(+:]i2ecZW% X}f]І17R%AO%Pf@d. Mo]Q{Ah;/M{}N@swī:|7't,h!E5NL wLQlQv̓s/ |B}U8%!Br>R!uG{FلkE{͕Fk1aPlp( E@E<&DW}tnsytxf>c'~7 U3%L(V} 8BD+ S1Tp:Ft[P\GC0mla7Ys{(>f8oldwq  Gh:hMٴp'X''jh!fo=|!&gwhf&R=yWv1(/C`m1Q!z{eQvc7M96Qaf_>c}sj%x^}ftJuFȍuq!2"%U(-y}b>% } Y ^ggS`r#(O0"Eّu ^UnCpnII4G#8N<)b{%9Ѷ5'c'_l)G!A*<ae$TD5 V'aFibm@OjS#.ij69S|(> %nL`nAW}Ly6Cfu6ё/ IdII! X)+`HI9ItI6]> b)fdfMO`gt/1feuF4iJx@kZnA*gZ?LgfM2AyiyEy^LTL4 晋K+kxa84q\A%KhWe㢉ǘYJL2&Xhݖ9MxOV(Yt(1M8J>{F*"فIhAh#ӅjtuȘ:]TEX} ޡCsn"(Pc_']UUZ*XzYfNAqy+JO*jn~8Bxҝ{/y=p 0;9a:9o:*bѹک pz(Fjʢ '=S ᨣ1VWW!2yBΑ#ZlK[:HH!ac@s!Saz47!d4੸q\)S(p/g4'hI2[0oN2JYk5P%[1!V@_ <*k[ZL_`a̔(dP#"_\stPpJspk08b *YxpT L&YpFgU"H؆o*(E!Y-vY5t›1] HXr S6Į4]ny0$1,t{õƀ|)Dl9 ٿ6l(X&nYG)KX%|>P Bvit\w Ӆ Ƌ]6~ F׿1xJ68R}L~mPFGn]۷^NttuePW8IESCILL{5"Wփ=>j_ a=DC>BO lCy짱ŤْGcjzezHQDpUG@k _3"-Ai `tm.'N#(®hqGjI5OF(P}6.6褲:/Mʴ?SPwB<˷aaM31Ls#71\j['W S9xfA ;#bzJDbOEsi%ɯϟX9FjO9z|هF {0ØsJ>ҫ.寊$XD>" r@: h 3:_( Ec&@o L'ŁQ$ CH9"%`7bܓy&ԙb:U'@:@J 8@s> s@R@h4:.h {t) I1n88`z|tb͆7;uJX2H pC1 Nȸ|EHz lMUN9d.$EVMRiVz6mN~;̿x΍Mlc|v  GCp9Y &-w@w@aH$Di@MFeuPIT?oQ;<pZ(u :TG$7d%2I ?bڤ-C" sOV9" DY"wu$9L1UK`t:iN:{8/` @jƥԐ-֝K~ɞj(NNP)~JD;[œg\_Ϭ8@DŽqgd:R@)[ϐBp͝83ekf~ND:=%S#n e.-bcfE2f`uij93MJ(.̐Wr"&Ӥ%l{g p3 lb&Fsy=6M8ƜHwȒ5%% a)B9! 8s4mMcH78)5%S8N:-:My0gFD^`hJ$Xi`dc؛Sx&M4Kܚ2yM66ɕpNﰜlhq %>&ћRsh7'&p`#`rJL,g񏙳GlO@?B oO7Sm\i莵D1—4YrF8k& 708Q4rY@ l@N\Jm~[i#0xn a`Z(xS̴Y:¥&u(#tbƱ((Z@I ^EӤaT]d ALyp`Nk]0= ]lO^ 3@J.+t6>Rz* F Ԁbkyh#mCENdbč R=BԇW(tB `zHZ4I"wxГA'$N->b#L*3(APOXRKF"'IA)a^;kr<!gC숅Ib8A ӌpې Wf/ӁN<%d`SO'>%(Tʁ iAQmbXP5Ru _}XGQu9[g@~LNјJ1PG$ko4P.)ՃlNJ Cq]㳌 6 Ro`q)Ki8<`:yv$VSԶ*ӔQ\.YCH8OT {(@0Jc7ToFbbӱڰ[Eko͋Q4JZyC ԉʈ#GlEL ZS*`|^)]hB5&'Ġ%c1fH*#Wy'4_89D* n  8фXLbu'&oFұBVN8YMPH%A y*i1V G(%Tbi 3gUdA:&m Z9eH2"p'vxbұO*L^ XMV6  ]d+bV3 e[]DYzdG U PYV!35"ϦF(gɀ-Oy4;Slty#׋ςwUVEcWG'.☘ 3 Hjehp@!YJx͔J~?5@k$_#h;VH>6jdl̬rNDC26>ll&[gm)=Q Z4nAŶz[{pƭ]46ҟU,3-1|K[pL}VgR%Q)Lm#/Tp1eΤq34e@yC&b7d@ C' 3o84c"J"c r)#g *^(P0b6u* 4/&2> %j)"|P$iDJ( F@Iz!fSaJ-D}ˁ0EC<Gʐ 4 NXnJm! !lMEEh$1te1z w^z ThQFC?*HHQH<G) 0 6D 1uQEP!N:&Qv QqCx>`N\sAPQD$aESŶJ!EPP11+6RrQLBlbNdq!2,.%/,SѼƢ<3ΖۮZbR Bk|!*el@ĠBmM[ Q0jQ!cJ_RF $+OO)I<2Q3 a_dzb d +q2b<4E3QODZ ƾUg K8W145v-OfդQ X/On4d|+kP_U5emAV0w*5S kr6(_TZ#" V0e (S&՟H2yQ!DK0"M;QTMj[ζmm*8dj!q8wv1!4s6)P}jq&(An`[7 kuR\AyJ(C4 aOu > $k͋d$fe –dtjl(~͆Ȅ0. |a"iCōkʏmm2|ejBs 9Y2Qv驒C2 &CD$ʛC@ 66e{:̻Nɺ  7߄؏mc,HlY*9YD$u^t'k} ‹)9,)NԟPM+ep/x@mW 9{̍ɕf+#RB1ג>c&Gq&@xǗ) 0[(W#X@G1bSkka13l9&Wsp%(@c5[TE S:.v._._G:8nSe4FpP M;qDT8&B-SKEY҅z4zk fdJ&tprSrT5Z5:[#:5'q(/H]de A7}o.5UQS`(g'c( +щ&u Pxn W8thR\h,a`ء~~lh}j /ۘËHHS`/(!x?ט}} R{eg9en$Y&߆vdhȈn)'94m:e?*ؒjhK&dtee6|w ~H}[`hl3-He FGtU$%P4Fw@u MiRcI/E}_h{ EE{#ǂpQ\{'%!FgM|4@(`WQvcf_L'Wcc(;f)<yxy Tz)o@<(q F% v1xH$u;"6avrxB=xc9F 4}ėOG\ciGB5@'2R6LOVpIgP(iyNy)+jBEΤ(X! wڝ Pd>D`' !`'yJq~Gx$gW9Վzk5THA`^*hb+n(){GVd~)1/iW`H^VlRsGQ Ov7AcxDKڤOQS #.1)5Aucchc V1'h@+ꖪzV^$'- 'Fٙ"gGm^?iyy{qqqw0gpR7zua {Zt5s|"{`A\kr  !uqqGx3(ՁX^I+ǥhA㪠Fo7_fmei*7H8CGn!_n>gRIk W8؈ij0k*"8N'`tm#YTnzHGddF!8Qbnc@Z.>oGAXf5;')쪴i;wa b!S vLsyIPb{A{uKpD}Q8!'Oe6Z Qd_dO~Q6eU кde V恍J*L Rz-T2 $9nxt*pXQ&!V#G~qLz'Q: e&p'W}mYhӋ ˡY@x@@*e+xڼy] [G륤 R._rs Q%|up6!˱T¡ i>P Ex%He`j]h2v 뼔 Ի)0a<[;$hcdySp\IܗRbxծ~x!~&pcmk6QT6"/;l}EKǵ|OxczieA V #E%dWCka|hƑ:ӫnܩpl*:H߻w\ךq{lqC i|L ,J)$ >pcisWRXQrHa3[$JbIlOL a#K>8kYھ2m)K;0py, ](ܙ\)e%P@B!rV `8bZZ+ eK hQKHxJB{#w$ͬ<>%+l@+eLg|iһkK6ڼ P:c{v!ŻI=VZ*ƆQ `~;i0-pv#8LisWTCB,tLcbؙʩP ½~*ܬ̊N 7R-e-آ&((Fy.ը[LZ i-vyo]R+=( n(c<& 1=ׁٖFrokɠKգ2%֑"G"~W~(}4l_} Mيzag2oh7pr (.Q6?zpG"y$pP,?O?Nq#0t-d]pj6AAL}tL5g`t|n#f1@4}}4_gơ8ϝN}Q1N,]ZghW +>VHx_ OPJFWG!G4茮L1{MZ6PiC|(h*oPSR%qg}ޚĶ<>\=ܥPc~(X߆0tOs:>;ϲIQ_''q'fM4Qyj@a r*]J_LL*($ovrqAGeFeOmdebtWk2q\ o,!iH`CvgbC T2s#d8qd HkeQFbc%rtYa=i1=,t9_L! Vx BXgfo2E)(w"5*"0Lo2QX޺ d>%TPONd%NI~^ JK *K,'@ ؚ>_H(- ȀdMnX<0`Iuݾ_W$_1hzh_JaR8P\}n.!n""0$ EЈ}PD"bP((9^e`&elsCf)*^}k/"dܢa\(sҏ?@/׌ZY['N#BrCI4@ێCxG@:r84a7byCŀ􆊎lPبJ6*G ZaOy<:u {8KiIR|Fٙ"s iǶb|!ah>Q5HvOTw`fO⊷+N !!êdYT)nՁA/BJ6^u>UJ2#^D\m)(@Azg%Iaqy A&}5Daq,OjkP$^DY2:{CM^V>֠li. ,d( L6*qIVtݱur  qpBs(N#+"0<,ʈ$A9 A,x4s, 0Ԉ,ߴN.f>qHdՈC_,q 7՚CDxIP@ RLIQ G"qP,\dN1DtŤI^2W"p:|0Q!(/ o (|d[NC'K̝s &7llpe~TrvwPU.M (Ѓ]ߝywnY^l(p&KָI6U1p zo$7; 3 T;vRx6tO,0J'/l PYCܝk~,IO 6TTq~dJH FB A+ $n^wX͉2Y?+3O2V'&IT%-PA"LH<IIl ӾF@/)mIXZtfA a#D2i! P2r- Q`H MAN`q2sE@A8nf |t:6N=0n-JJ#"О9݂l+M=pD;y'k鱺BM?1L;PiC B X* +(~0F0jFxf(Rq9S=1D BH`HTł4j-TP -^.4NQH@&$##q$VUƒ7U@rTK:TSjF%dZ{g Dpƛ <1- $1`e ̓ؒR 02u`:NjD$8^jd)vxutR-I I+IFa*kBEu6Yhtp'L9I:IlQ )8^IJfZ]YuUF]O::i)$. tV!y ԣ*G=.jS!W)*UlLB\ڀ9 /H)#4js CL*XWfI"VōV;)\+;%s怳)Nb9giR"rg2>i<@ SҒoH'O!,`q*D#R4̉4lB9tU R8fhe $`AT))J`Edd+ACUFb,ino)fJ&6NhU )p [A0$@a8m-Q TR #,$bq!*f0:]Q=15Z@ kWZwlZH("/d Ժ*yQ})>q d!"uJN-@bn`H͑x -EL;l P4ٹ,5$O @YMb$A * ج āB0?QHHB.WВ%I,20D0:+`D>PUr])UvΫbCI9w\knCvWDPmMn0LADN$űS$qr5Gg(!f#iK$Qr#=DdbڱC<EGQ:lt t`&pH%䩉1Hh Cd [u3' _{j&kiFr&TaiL _.,PmsdC!C\C@VP$A۬6THQi-߀.nJHa_}d hAly![~ی^x+ ^z|n(2xɡ)9ӎ8TA,矟}N(@9'^;tGKA>y s/c9qݸYo8>/o4B>ngo{K 7?CUS_7;@ uع!pd-+~3 Ƿ/Z"6Ю 6Bmdág6![i! ĿBB+D 9%61*JeNԭ  U ճ#ZVJ\U5VkYJս"8C [WK9ݍJrK~ rlP̀ Hf0ˍԪQoSB^D7U΄*-- V< p'gz/5 Ua H0)ta jϸX%l834 =|Kͯ~$ 3l!w(M`VP /)P &%t45\>[9HKs)LaֽBNT  8qXU~pApB\c6 oh aj+q/_N\8 9@Sԉd _P |4kmgnFP3L$v*6w}Wv&*R(Sr@1gcDžgzlhvnX"T(t( hx^[}age('k5^6s(};+yx`x7xxGyyPgp|ORb0Ŵ|&\{7؋Rq&`g~ED.G`Bsut%[$s`u|R (Xhvxv93 xUR}x[ y]@phqE+#k0-36#z,я8%9'l,+Y0>_ C)OH KE9(Kt^DgtVw;6t_B`R\U7epev[b~GvTave0S\]wSm'oELF}aF0\Iq$N;)R8uy;yTa7y'􏶕T 5Jْcimaxi$vsa_A}b!=IeS?af|}'&ȁOS1ȁvp##rf!3o0*(X_^GwvR9p'#H|a]Uxvq5r&R5SLqtψ)lRg4a)v~6cSiJ)چ1 vW7w7xT*AHA0K`.?H:vVBppB8NQ(S(}hO!&r- +"jIJhhog(38Epti (a;gjZJYJ~Ǒc-\ '.Ôx4~1y׈;(r  )ԁс]J{:Aٛ™~_+a @ 8( bp)#.ɔ$I) U]&Ipo8S($Tj)pʭ֏*cQ*#Ѯ :zy:0Qj:e88W(O/bqqIAbc٢y9q9qptT`6i49Dc[@GI;IpP S s+Ja+SеIpCQuI:{zʶb^+~+vky^6ed:8Ha xe [rShˈ׈ȍJ4Ҥɺ &``{ٰߪcoFXWŖ`a `icth jڻ_n)5ujkZ:|)vҷ)iu y1tA''FYx&2liZ34$x z#ypФ$h Nÿc}YG~ǣhwP\&sQA҇<~S@CK*P<[:]TbJMX5|2(l (Xy+'&h&8p0wPh$m~UR+X7b2![c4+Id 9E\hyH夝lqLZ:i{e h K d}!|R$1A1_3(Q`}rnmm>^a7s4+"Xt2sUMH>C&]Mp[lz1h/Lmj椃DUakr^Nm}F`dAx _p:gm=}/X"sAO@BE0`s kg ܽ ׌gNxiuڗ+΁v]yw,1)59%1:VhD2gG{&"hR"(?0,mأ-CF]JM̄liZk_A?m\Ƙ(!ܼھ%sp].l\^ߜ:kn: #!灓[RP"wodw;*},\˩ r]BD!#P|$oKqq,&,PC=Ahz!ϡB>p]E0V(J~b> [vx㿟CpU@`վ4?r ʎ=̻LҮkqHiO -7U\)NaNaG,÷Xfp 0QTn+PۆjIjt[Hb;BO%ͣsMI}' |Њ*&qsa]v.=  B5+;SX`e%UJLq%Lů^-+AD"A ŗCX"@\GNl@[, r)> 曑#li`BEImVU(CAq4: 5r#1Fj+ZEyX[cpr_sϫVSzy@o'̛Y׾؝|-`1 @eBā#lk `(i8=?( $0%h}JǷH3aC8 Ɂ C%@8,ouڡRS$md*GqNMgs.1H̲ <8Zl:1ͨlgGwWa3ֻ,Z2@=B Be:>ȴY>` H!P GQ2H@$i%#;,h@UI)чaWmS]0S[هaS_,sjC V?{sˠYHpGX PI9'^Bԝ}Fh9)3YU Bf Eh''⮜Xʭ@CrZE?%ec N"d'QL9L.̻W1 EK5,[R_~ij2&Y-gbVI*Ylj3bFu 0 #di&a0e@`T 3*(/iӟ4c2G`GIIfHKEM$u$ YT XIES[ DK*2G40Za ibR<4üXkK~ZvAHBpjUJəoB1gܓ آH"ܐR޳g[pEQ:䑇Shf~]] /ߠ aHT $죚ߺL']/p KQ4Vu.Ѻ7 Y]B *"sufB RM@FAFfQҙ<^[12Y\< !x$[Sj#\P35+̅hF~].am 082;\yކT m^7`P@4 <%$#4l'T- ַcznUƲ-$bK)3eɡT <% ;ƽXA4XMd +nD> (s&L hX')B+7񔱰@KI)l5C hg6K:ctӰMa 0J)1 U㽖*1d% iǨԃ07ƃP>:A%Ăsb)) %fC8T ]tJQwk!lO^Lg} ,hiƐ8WI>CV$IzZJp-%BeȀ8 f)Z>2AB2 -N*>- 2LE ڰZPS'8 j6V&"WЙ6Yq*T5ŭD|,_Ӈa$`1 (dƂ11YY-+ ,W",g 2KN:Y"ekHJUdp½[dTr\f,S pw.qoǵ [Ya-k񢺵nX"q݀*Ցp̐يBRˆ;z.ĝZFHu!E57h\wxV`  դFDUMK7!4"bmZV@ʯKs]޺mK>{Tf/T 7bԔC4l 1B0b"#Ę7n.q3D6l@)L.@HF%K.8Xf  @$M9eȀs4 ƈ%S(;iV(J)N@t(dÉ6˴Ƞ*ʔ+X!AW7rڜdgkׯaӔ$MR%SFs\-XseG æQcøyY܇10gDGEfˤ1gRln; n2!PMrâйx.sѥɌTK؄"HΉXl A""8-Jp Y]Lix@Ur#H@9Rac9=B"cPa! II:1P`>PzS'#DM0S[1$dON!C% Vdz<:Eg#`dSga]:zkG -qi^r1g,!V߱P`Zu.:J|t4t%BP(nX[(%F3 j0@ B`B'9d+Ek^#. {fFƂnBS4"8rX,ӥn,d}n>:겚5o7&`enxwFK/~UZ3/*^<[uL\n3py?L)ؗꉏkNtX-FBK7MR_N(@! PpJ!rDowp1ͽ%Td]{_}Rw0pM$L(LKnYMhx,7z_f a3;! lM%_e^|\l-](Ӧ5la J)H_e3IIc;ӦwS$>:x-cz'|- pP9 p) IKMZ)72HСʔE`!87QHP-Ou00q3!N0ϚOe<2LڇIz8^@TW6"e M ކMM- 9Q& (6,'L<EO_ЇA+/T&fҰ)b7t¤qsti31 d䤱1o,"|#EI4ipΛ ¸!BN3u؄ S$IR#G7" Á&Չt޸#vN1t4d;iƔi1L8ev g(ulkv:S^tkxnݻy2v|5pPT+!4#MƵ `q^9F90yHaI9ęxSdc3绢y'pı^N(7yK5!NID2І %G:DG_D4({kJeiW\Fr2tQklwb[=['$N9aVbPneV[w1nhFFdDFPVOUVaTCQЗ,^o>aPjB AF&Q ƦKyZzAQDE#tY;f`B.X/5QGqkvfSVjjY1aXUgv)h䦝2Jݹ^Np}4T$*i]MT%.jJ(=E7`j! C(GD|> w2+JX$ +md$ |mгB + ~ R P_L@{SiZF:򑐌$'IJN4|0x;Q!e$(C QҔeD%@F|%[IRd.!GґO&/ NPc)B¨R3RA @0_6қ'-mINIj^V̖82k (ұ3DgbRҒ h9u9PHsßDNd|'=sOR3lL)nԗu@͉IM:L`Df :S؅V2KJ3 )Yɑ!$pPXJRxAռhVJTJI gX[PRQl;!zUr}fI׺y0&v\b  laۼ2,}uXueYFuh3Y KVs8:XҶֶm(ږֵ"H,dzZ md7D׹"8uvvwJoMzU`@Wo(_ӫB B@$D! aH{{ @.Ei; Ku*(Ța I`ŵ>Hm3S)0DEWb`TD!X KNS%_P f &#yj a *ACNO22Y0 kپpA@0] []G4& wޅZH.ceѬN:%1Xq3OZx8NkyL[*/}οV߫c6& :DPWj4TA[t^ftɭx" #dS]~1šQxAN¸U' UbI Sr72."+x2Fd1i牤'K64maC~q 'tM RO !z d~f!.dba$8,Xӆi#3u@3-1G;=ib.Y__PkU2qQ0Ya&g!w"(I,@1mWiǔLJ.hx'A9]dk6^T,S<B/%D#%IY'360- mHb"h]Iyy c88*>,b'![qCbZb[]*8o0 -Ї;+R,f!KDyS1v!F6> x@cǂ)q@}aTbF:0ȠhRbn Iz&9K6bi+wݑ_JGi&Ȟu(Zނ I'>:!QmC,w3)l$a*Xɗ/CyXNW Тs_Fbj.DwtTtv_vNvA}9WQ'acz^X_u_*ve?hFvs'oF1bxCp 2Ń϶vwz`H4NbʀmRS< be4aQ{v_%K!bFQނ~O6aSœo-R{"W+J9}Z<3R;z&3*"Jm['[_*}S  b{Fk@ 2ݨ{L6R'a=`@x{ǟ. pppVyx1փ|_ JSL":+OCX|Z{R8D. <̪ (>gF|v {@C1c3Y}2vc)=.-cAٗ3,xt,|{nNB3L at'+klʻת<вNLwe-%leozWPL]i0nFЦb U0<g-m}g/*˧.c {˳\|&1p7 7xjQ=xכbV oĐ1GO>5 >}Y~W <=\?rbn*94;Y,xqBRc̦<{6>IW舮Z.",':/L!NB'NTC{Dlh" ╬b>17 Ln{\Coq'bp!~3r#R2*@b ش\_n~N:WuO蛂7 A4>g. Ϊn\#nI(fќ]!*!wi5l-_n,3sN~8Q^ G$9b8s.M og^뷎~mag!e|VNR?,^0 \\^A@I|8O'̦_`[\\qR:,ڀ*~>AR-qsB-+-I1 >x_V";k8+xR0)/8A+k 6935X_1yQ}ylߦ.z.+e+ʜ5.R@L[OqL` .AfU3{醩Lx{x•,Il%CgZCx:y-qUE {n >p4c BP Z;k卟]p! ;/RSO eJָ!̋ /s& N*Vzco {u޵st# r&DS1B % H~C cNPc4 D,GEzoq9pXݼqp=N )5!bܐۡP=7teyj"<r9btJ=t FeS O"D.<Q t' gU)Nb12CI E-[C|xV:&BAXro P'QM gC4rC(𦰡z ܐQ=GvM3fW`@UPH'<7璇 B ] aP HEd23[VuTH =#.hǠÌIe 1s"Lq N g(,0Ŧr5Q"*e$qxVq }F8záDojl Hm#TL7pt ю YIв[@cc#LyB0:54  Vڨx# =Sdzm=AS knG{Z 0KiT} `II ]3R3%z1iQo@iү A O|+u.RR;ɾA/Qz#N YY#=$'5 &Cd =!(BwAk'R!O0fa)PZL\h Px,Po93>e +1p%1]YfCSܽ+g >=(\ S[Yخd @0N65)Bd謦Q+ Ey9t T*;lBH@&*ٹH (CG B10&¬_4w@{< G|pGjva !Lj ]-yPLI( d̍2A`&`HvԖܲd(̶z* 艎 "% rEf'DM` ]SKcd5x@#m^sϜ-a]- S87a[3N3c89'4w&˰h/+K ԗ Ky5KIL#R:GF&&$pl碬`..Hv *MS .,8u.5 JA6W6-,+DjDm.-3= 0nfẒtHY.$# \?f_~0PBE1  OnGp"N A )3ݬNAU1qh@qg/ iC?#8_`!E/StP;*:)7I- j m9/%(:a `LcTA63 #H;73hTTXQ33hZ|bwd -M/Hdr| mKf*FH BijHV$cfce-Ŭ M+bNyzu+jbA[*eIDnRw"Q3'!2$TnIcT:F?70J/ ) X˙УN"G⋄LAtRS Gt2o:o839 ]bY$1$fQ1 +]A.`D!+oBzc@ܝӨ)%LHJ>I`I' k4N,?#J ݢPSP ތch)b0.# Ic~J$,ugBT1+ȍР*[HQ"$1bd`,ͻA.S@ H( dcuفkY#yBT%:Ey`TE:@bd/n r1VB+v.VE*$ Ūb$*KrJlR!$=fER x0unl09UJԴlUڃQ*OOc*ce;ԫtQ6n&Ȫ*z5:Q6"lVgPXlf҆x@s+n*M%*fn"I1̪/ rba3^ 9C?@Ce% &H_꟩OB,w~0AⳈ@*/Ym֋E,k,M9RG_m31:*)>O>bQIrVn3PWf3;[04+ NdC{r4`9ߣJ'kdoBg2i [Hktʵi%[$mgU4n"ٌ xEZz cJtCL#^ ?(.T!CBT^$d%'DB a*D `l>e72"$:t4r_eLsB϶ V9JrU=4i(Ysly[М`k߰ZTRpx\ye7LK5[WKjNQYUV ՀĪI8* )"s=ǬOjsB#ҝ&J! 2H>p"A\c,-jKg:]T*. okQDIUȋvNuSr 2ѵ70)N@<3[_!=k긖1֪[Fb,o<1`ydޙy cZ¥u5 D*:nniט87{ _@hmO+tY^S`I@s3bLU$KKeh+oP;,|Y7Eu_|tjƝ f pCDuu%nni~$#;Ƕf0Z fz,Z}o.*;tb13PᝉP%Z3N[oWf䲰D^bf G7`Nx5>Ye㌌w GuY>lC307Ol 6NAѿKpk k.w* DPyk]2!@( 1ș4d@uq:RˑMԇ/3sF,.ZY̗v-gZt]xzYa Bט)=eRL!Mݦ\W굓cmO?f4u =ռ*JkwF1,\wRu!el=HCNN/U kNߩ YV^iasYU1U)ğ=B+&ʷ(df!fl j^]6-!X`בA:!ž f*~\FB-o}ң;HH ta !E-mmV@8rPFu xf3 o&UeU> wu hUmEx֫Z^ϴWu@so^EA_A"\#8\aşS` YM7/lV^"|xȵNC-cg$f,VUޥ #":Eʋ@G I<5c#q"Ё<6 1 (`:NdI/aS9ZZQ T-|?C} Š7lNxF4tĐ<$]+zfvvJCM2f=&aFI+v+c`pu9NgoE##b/aĩ/&X f!v7"s%jhG=I5AǓM[wI5m%mCEh&'s4\Chh9i|ꫢ78ho7ٜ,B$ d:b={:!m$z Li D$mǍ.͏vVOPh2=QIN(kYYD^G2=x@H[D=POq"MҶi4?0 AH@H`mtbG9>Q`x"MI|2_F9ֈ@L`;NrĐ#:-Ŕ (I (R\}$3XI Z XAH&HMN +k!lC " f+ |لm0"YG:Q&EsQ8+Yc56Ʋ9>]G v2Th-+' D_0$X+C,Y4`UT."ڼ$']Kp8z_1 5aA";PރcQYiqwL:UaaHtwLzvx 3?y#h!*AhW;YP`PYyȩ.@RG2&2 ziʪS0FeӷH#ocrC$؁TK֏I?r/t*B::)3z1zg=P*٦rt_y!o!T9=n v6)z:]͂%ɩEs)CpLryY-颂uUP$Ef7qx_g)15U-qP08$ǘb={iJs!,8r>0 CZ *Qc8->Pb1d8o( O(JO.!P7]e]!JS[e0tw; wC7_a[(zKdڣPhX1yZ8h*z) 133OP3%8ɸl+[{yK7{yJʨNeeNk(p+E@z oFۻ5 H|( /jKy(6\~M %ۼelݩPѼ||/P˜6|۽IjK=\_,<5sK:Ø5>JBJ!"q?j"۱r{+$r1h,-QL0 >92)iʕj:qR]?ho:is)V/""jor٫Ńx(pA%PiPǔtMn '$B7!y<Thq:,Yakn~ sn`5 U)TH{`,Cqz{]X(puP6R*ڶ}|'>J'rc /(Έk"̐:Vy1tQ,wP}M>yHDODR)UKMddZ/ g0xTORw󋴅-"甂prO8ބ"``?S/הMvyrQhN/TtπeoqM]訟,WXïwheJOiez }1OmwXz# ҽS&͹)M#Ӱ+O]bmIB!" a'0ӤiH(ϰB"|_șv[DQjM-p'Y%/4j8+(V܂E1R873],2P]<+:˜%3tY>no > #\}4 4%Lwe Ԁ arKՕ7|䑳er/zOB~ H{<-L&DE" 6} qJ Q t<'$ s9E=q?茎ڐB厼&! ̢ck"ܲ3w{3DqFǜ 8N$b;zc16Ԇ\,CA <' 4J- dq_ẃG@"-+da0WT'0۰aAp4)|.a *T,pO[0,BI3IJ" $W= ( 0@䙭Xs2օz!fڀT"VQ[ ~@7|t pA'@`̃㬜NVkHaoVijEcn8v.Gwdzg lK (^szP+vn9$ mQV4A")F- m:$PAo(V[1pXk4XIF v5ܡXrqr?!ŞP JFvtx?-u ET 2 >p-\p52j&h~6UI ]w"ww25@xh *aP Q< F"83XC^V誆onȹyO3ὓ`|/?7s -D8#8\~]h1H65er)$rᢒ/0;~$q"Wt13e]3*bAmHp9 E,^PؘD#pJVtKl+j Hۢ|x~gA!)"  DD)DH{*J%:}f`^fiF-a  "H(Cq`%b)D@܀+>)*[gނ8v_>@ Zf C.#v2tChJIY!XBR\&B4eO p#N%yL)Կh)D "C+]2ѣ O|P me rt dFԀRP)b Y?J*=X`-Y.*n(XƲ1ߘEn!)mXDD^PrhyGT E է4ltP@Mu| ^Y@ jziޣ%F! d&x#1ZkR4х)Л%)q3l Dn:i4II Iȿi9&DO3U\DNgy$N#RСkuV;3ғH "rdI>ixNqc@o Pf}#)W̌Nd 2Vi:nŁ_ΣD-C$.Uiq|&,34[Ź-EN*̔Px`_KJspeVE3(.]ԏg,;{ -@=)УIJHt/{=bk`|2kD>D*>gOnj2%QZ$6ԟ4U*eYZFT)WAQ!@U VQ4FNUm :QiP"(ջT0&Bw؄6Q8\)gQi %y?3Lq5t`#,,CZQ%޹ݲ_y9ZCcRb ?SYiQ؄r".,gfMI 1UD3w9iDhϺ8UF\%N=3*aP1ICUK\ݩ4L)Z/b!p, C V$Xz~`E40ݩ^`VeTh5b$M=VB>#}*Tj$NNR31V XMduP AeP*KtG=Tm? SMYuIbX~5.4*dj^vJ"LR팒iA&w)<Up{:V,.B 2XH&YxXwjb #S* ,B)-'!Y\8h, \lK6 ܯ[~2k ajz !iQُUZ2m%v5+|Pn6t pDmU mՐ_,bx Z݀rt F&@m6S hP#d/0 oY Q+Ɛ0O9U@C)X^Wp~vc! <@V*flz3А5]YZ,O]*,PQAJ+nS9 $A(#PV+/C'fG*IM.@/WIZa:(Pge~!0L!#jbzi˥k>RqB!  ´Ua88Cv :$gsTa mJg0C8c咪4iL Bb `x3n`ؖs:]C/Pݑs+,BXD( Bd[Ziuw{jU*y_wvYQ]q/*dÊ;[qLPf^"BFpB۪9Ucb+D(dAG^KtTXj1Uh(+UT(_%~D(i<=D.(!K}pQ N uHNl ffGe#TttY():Jd;;o!Viv>,60՗c% 2Դcn93 N(HW"Vra}W:M 0^[`@b¬T#\ `[2C%f.]\Zj HP7(W!:rnEwNŴX9p/o`m1IL+VqhRof(/]<P8y(h UqF#bpLH&JՇ3%v(>zܐQ15 }[eÔ Wo(Oy!ӬibVË(l#tϙ&6:nM2 |i h1a.PHUUr# :`[F`F5xU*TtKqن@9C H314rg9"De(Vѹi^f_6=ɜC̄Ԉ.htB|<ӤKr6W-IE;0|5+a p=7 dEI& P%g|5{ZkQ nJ[Ty AӳjyzV]6/{:w)ܓ]@ne uL(7ܪ9Og,ffQq;HSBQ T;_ [&.o4:|&':{mydfq /T&fҰ)b7t¤qs0 2r)#ᛎt0BĝcDΡñC:rްYL6 xJn@Is&MD6 P\B0nȀSMRB9.t IƢn uHᝌtXDi@,yϰ;A@'› S -|Qg[h@铥C)`>h N$h2F9P=v)2|9^MxP:uyӐÿdS>zv5 -$ =7"GA +Jep{UNn-BebH% BU(PCF\` 7){  p:&aX/`[b7C!K~ AcT(Зh@!3Gh~!Pr$a`&7.؀P2`D$9i8@4'@!,0f rS.xS?ɨK8Au3GEuq-Ti q(%Vңl } !C$CSspOLfT:(N5do J~ `r.iYWoT%P$A (5HF6Pe jIVSYN8]h*RzA6(!*>hI!PEh /$g a#UXg>+ZAVG6I-s:PeղmdٖCԆ9$μe6EܖjkMFPu厴H &"czt᛾) L7M Z(Xr8[NG<=FW*~x.`%]8 Vm-'[[U740 8-Ņkp[M٩C6 \s7쾅 n'w:\I@PDhX2s2?C&VWM%ޤPGƀC}Zr84y0 ('ю! ZT )Z 9xh&P)u\[hz/cX84\r),"?7vCh4*CE7Zzm5Lu_x:St0pNCmFwD=w3} P߭0p{aQtpo? A" ([1B;'&lWFqf\@* " Br=h5h!p`1чNh,E1nyܡ>}u 0ā [s$lo@ߤ/\ke:A* X4@%Eds!dta;[(7ADǐD%~ސpZ"\ל{J$ҷ+50@oP uܐO~W|wWR&!bgPg}}x'^shg_LalGk>WO{_0gvL+b#pRA;/&_HH(D,A)dТIt-uZ6c*^xM6&X$ dGZ\s|E{(tXcXsF(VmS^X8ԕQ!O'q[ndb&b"G_`SG:S^`ltw1VXIuPiRR6` N'X1ZpjH;_@HC*u0+1|[wiq9Zd6`"9aŁR!)hR?rt&'jfy)IV Sq!t_L8{ u׸Oyt-ҧOAioqFV   TRRm詞j9$ՀQ 2m_`gcpM`pɈŘjd_Hؙ|wVnԁ5x+:eW%0"31"V=У>@B:DZF*c0 ?kai"bqXZ>ڃUqfBdu0 )Y8gks[6Q zsi9+X5dBr:鹞]g9nF5f*R8H{Nb$|f=OC+wB"d"{&:Qq+[Q pyr_R (0<8-TjyDN_q! ;UAY"&pi")pYOQ MDlDxQr iu(`\x!*Ǫ P*b( rj ro"QR!+¯&_r!j34N ɧ4u[;bpZi>&n"XVa!9z:%eSXgB^9bdí5kzdpl(PL35[k` @Ϸ0^;uE@rsXʉY83~!1!JrRXTu1ڲM%_SG@gH(PY .:&m&5;r(2Mʴ[P@K%tB5-pDSs`Z{jdG;(A7ʫF!(˷<ʥ[՛* K o Ǧ V[k=HȽK(% "g:;0QraVd;i*CBbJ[Tjzz?;!:BxLGny*+)R+1u0HyI2qʴyǃB$Ÿ0>nL {@2-9 >0uJnr F(0(Ĺ<,>Ru!0u9fETQnTഓr׿,i&ōx'|' Pfj&RULui5>{'Ne6h앃(+0ef,hg&gćzj\O`JDznZ8(ޜS/ Zhk9w1uIͤ Lh<5ulA Иzs /fFhѨb-5uTp㌒*8e$S R[ɢ,:q31Ojdhj X13IA SmJ+׈TQ"-u!*W5IK=6(li<ů|Ũz"aild{+*.SjUy>F8em9qο&.X*ikFұR  }<z]mzSKSxkBVwb"f`{#ӆ̷T e J @ V[ݣث]+!+9A]֛QgZ\טyZz <NbW&G<*qS@4V&T3stdCqXe<];8%u1q UQ%#uÿ͆/"e-${1PJ5B. <7B>7S 3wG5%3Q $RӮ6@ʽ,EQ(`6g+*V' edf2 vpLq#|Jx6P5@`!`+2_Ј+Rs>OGGhPBOx{{C9$mtpF1%m^ZRR>Fٜ! =QNSGcXQ_\+Y(Py뙎<>Ο^=-m*+B+r Alꍘ/85&@9YI(ވI>!8S!/#PI(/oO2/$?)85aS104_b.7  O<V3eסڹ[ub9i]o==wܖqZ=qs!xw/!1Z+#Ѓc[@+Ȉ1TCEN"签lxgg Ob@[Bژ %F73D/*;Y%ʉ!Scgհ3Au*J)8(ʯtNS._O65/ZJƯ8T1<8 txUh4>kD./9zض\'J 5`-4<\R+!DXd蝐@S l +΀P ꗔ6dCịyZ(?pBoݪ;# jHEE@!ʮuGhA+H? a@~Vk]\IT_=RP: D/8}F%~Mq,kc(&sr)@#f91gt"ΕGv2ЊCji . wZ܉uJ*ιcwb;f] wh`>0Iä2z'pJ H&z!lv 1dV~YI,[,DDTaa*jS'pm̭iUq{bÈxtcPT*E!P!2֩DTSzTBUĐ-D lH*[Pte@1Dؒ:d!,ź(h+;C{@Jg*5(VCfD_@EY A-CSQ:J . L9CKR4DK}4r>lBQXJRI:w%ǐ@ԺqP`,d䏛15J%[84JU۫,v@-),+@=:P!b 6Dꍅ Bq!4aQ C{ &h8PC tu@1G7%s"e EC4T53ڠ)63؞#Nd< 2EnB()hҁ/p$c'儙DRy@IW`eCwJH$|֤,sz~=H@#<v)D~f<4Xg9"?fP,m-,98U|j݃pN<DPX"6 8tL>&YJnLSYB% nyi !X_;ȳC4 0l.fT:NNTXcyi Q FUʟX!cRP-HX3{z fQdgĈ&FaQ&3IP; Cpf䉬Bsܕbၜ:yA>eעcy IzN(]|Ěrba JHU# DK2O /:PR."$%C9T|t09ےglrIBYaI*wuXUn7 !BiRfM%Jâ׌Us|ӬxOAQ@|7COґ G Ўi qtt!p a2_u\ȓK>BsC|+$q8Ex-\NStFi5Lb\[՗͕P9$$Z -߲Z rf&>Nfń?N{(^]zl%AZe[=:VKO0Yvk)Qݚj#.=B-9JYfm%ܐ -͡p_**U/̈́vVmW&*g*6/hV0E!V.Fq8EZ+Y>g|Tia&TAh% ۜXP0 WSPIծu?ȯZր /*C$@<=V/l =;g!S:<5J/MHUW`II"X=hF4pS!J!@ 8+x4`n*I@Ţ Q,8!?Q`bKwy#E~Y%fFJ1M}JSXl9N#p2v5;u$,g3wyʗ|  Q:ӨLIczARnu.:J)K)#4q699'ɠ),}БAE֡DA7m) hGU1XiЛONVhӜm<矺5kE%E?@w[ Wj_B =.}U7Az6'ajVЖ&exw0scY1&3"Gs#u7F$;0tD>dԭ7Ϝm)3a0/^^C{A2Ռ_X (lRU=ji"-p*k"xSEIF4DKhKpNFOI q&Ө.h5. b/4a{ztv2TTD_3RuE`i WE 3nVهpR%Ё!Hw$-X A-d 84] 鸅Ne>qbƑq܍6~/gg$j:8zEPT>iIJ=ytGf ]C9vhl hH@JRN2ǒbf1P ˫&@*'Mnh=7νw,dٍCY"3[u[Ola\RmaGVz)ҭH[& g D{UBإ13{5mqTgS]#WhՔ,PR*=[-[afq!*`o㔓ۜ>~%eHְ i H5Oֲ,_X& 1W]ha>Xgܸ]&pOLWsc(k\oNZ\ !\8 |vg֓OE dVMxon+&wt}69y;1OgwH1u >Iwݮ&Ӭ .7(6s.n֯{ƻ ;쐇 $reFڃO&#xGv a\[moF5Ld@.ՍҀWKI1J9;FzWp;uC{u8CѶ= ]4SZY/cfSqUe}|mDgcOYk6j/WGWݣļV =:Fd齭C(* S/-!|= S>?5k7M#define NR_CONS 1 /* how many consoles can system handle */ #define NR_RS_LINES 1 /* how many rs232 terminals can system handle*/ #define TTY_IN_BYTES 1000 /* input queue size */ #define TTY_RAM_WORDS 320 /* ram buffer size */ #define TTY_BUF_SIZE 256 /* unit for copying to/from queues */ #define TAB_SIZE 8 /* distance between tabs */ #define TAB_MASK 07 /* mask for tty_column when tabbing */ #define WORD_MASK 0xFFFF /* mask for 16 bits */ #define OFF_MASK 0x000F /* mask for 4 bits */ #define MAX_OVERRUN 500 /* size of overrun input buffer */ #define MAX_ESC_PARMS 2 /* number of escape sequence params allowed */ #define ERASE_CHAR '\b' /* default erase character */ #define KILL_CHAR '@' /* default kill character */ #define INTR_CHAR (char)0177 /* default interrupt character */ #define QUIT_CHAR (char) 034 /* default quit character */ #define XOFF_CHAR (char) 023 /* default x-off character (CTRL-S) */ #define XON_CHAR (char) 021 /* default x-on character (CTRL-Q) */ #define EOT_CHAR (char) 004 /* CTRL-D */ /* * This MARKER is used as an unambiguous flag for an unescaped end of * file character. It is meaningful only in cooked mode. 0200 should * never be used in cooked mode, since that is supposed to be used only * for 7-bit ASCII. Be careful that code only checks * for MARKER in cooked mode. This kludge is needed because * chars are stored in char arrays, so there's no way to have a * completely out of band value. */ #define MARKER (char) 0200 /* non-escaped CTRL-D stored as MARKER */ #define SCODE1 71 /* scan code for Home on numeric pad */ #define SCODE2 81 /* scan code for PgDn on numeric pad */ #define DEL_CODE (char) 83 /* DEL for use in CTRL-ALT-DEL reboot */ #define ESC (char) 033 /* escape */ #define BRACKET '[' /* Part of the ESC [ letter escape seq */ #define F1 59 /* scan code for function key F1 */ #define F2 60 /* scan code for function key F2 */ #define F3 61 /* scan code for function key F3 */ #define F4 62 /* scan code for function key F4 */ #define F9 67 /* scan code for function key F9 */ #define F10 68 /* scan code for function key F10 */ #define TOP_ROW 14 /* codes below this are shifted if CTRL */ #define IBM_PC 1 /* Standard IBM keyboard */ #define OLIVETTI 2 /* Olivetti keyboard */ #define DUTCH_EXT 3 /* Dutch extended IBM keyboard */ #define US_EXT 4 /* U.S. extended keyboard */ #define NR_SCAN_CODES 0x69 /* Number of scan codes */ EXTERN struct tty_struct { /* Input queue. Typed characters are stored here until read by a program. */ char tty_inqueue[TTY_IN_BYTES]; /* array used to store the characters */ char *tty_inhead; /* pointer to place where next char goes */ char *tty_intail; /* pointer to next char to be given to prog */ int tty_incount; /* # chars in tty_inqueue */ int tty_lfct; /* # line feeds in tty_inqueue */ /* Output section. */ int tty_ramqueue[TTY_RAM_WORDS]; /* buffer for video RAM */ int tty_rwords; /* number of WORDS (not bytes) in outqueue */ int tty_org; /* location in RAM where 6845 base points */ int tty_vid; /* current position of cursor in video RAM */ char tty_esc_state; /* 0=normal, 1=ESC, 2=ESC[ */ char tty_esc_intro; /* Distinguishing character following ESC */ int tty_esc_parmv[MAX_ESC_PARMS]; /* list of escape parameters */ int *tty_esc_parmp; /* pointer to current escape parameter */ int tty_attribute; /* current attribute byte << 8 */ int (*tty_devstart)(); /* routine to start actual device output */ /* Terminal parameters and status. */ int tty_mode; /* terminal mode set by IOCTL */ int tty_speed; /* low byte is ispeed; high byte is ospeed */ int tty_column; /* current column number (0-origin) */ int tty_row; /* current row (0 at top of screen) */ char tty_busy; /* 1 when output in progress, else 0 */ char tty_escaped; /* 1 when '\' just seen, else 0 */ char tty_inhibited; /* 1 when CTRL-S just seen (stops output) */ char tty_makebreak; /* 1 for terminals that interrupt twice/key */ char tty_waiting; /* 1 when output process waiting for reply */ /* User settable characters: erase, kill, interrupt, quit, x-on; x-off. */ char tty_erase; /* char used to erase 1 char (init ^H) */ char tty_kill; /* char used to erase a line (init @) */ char tty_intr; /* char used to send SIGINT (init DEL) */ char tty_quit; /* char used for core dump (init CTRL-\) */ char tty_xon; /* char used to start output (init CTRL-Q)*/ char tty_xoff; /* char used to stop output (init CTRL-S) */ char tty_eof; /* char used to stop output (init CTRL-D) */ /* Information about incomplete I/O requests is stored here. */ char tty_incaller; /* process that made the call (usually FS) */ char tty_inproc; /* process that wants to read from tty */ char *tty_in_vir; /* virtual address where data is to go */ int tty_inleft; /* how many chars are still needed */ char tty_otcaller; /* process that made the call (usually FS) */ char tty_outproc; /* process that wants to write to tty */ char *tty_out_vir; /* virtual address where data comes from */ phys_bytes tty_phys; /* physical address where data comes from */ int tty_outleft; /* # chars yet to be copied to tty_outqueue */ int tty_cum; /* # chars copied to tty_outqueue so far */ int tty_pgrp; /* slot number of controlling process */ /* Miscellaneous. */ int tty_ioport; /* I/O port number for this terminal */ } tty_struct[NR_CONS+NR_RS_LINES]; /* Values for the fields. */ #define NOT_ESCAPED 0 /* previous character on this line not '\' */ #define ESCAPED 1 /* previous character on this line was '\' */ #define RUNNING 0 /* no CRTL-S has been typed to stop the tty */ #define STOPPED 1 /* CTRL-S has been typed to stop the tty */ #define INACTIVE 0 /* the tty is not printing */ #define BUSY 1 /* the tty is printing */ #define ONE_INT 0 /* regular terminals interrupt once per char */ #define TWO_INTS 1 /* IBM console interrupts two times per char */ #define NOT_WAITING 0 /* no output process is hanging */ #define WAITING 1 /* an output process is waiting for a reply */ #define COMPLETED 2 /* output done; send a completion message */ EXTERN char tty_driver_buf[2*MAX_OVERRUN+4]; /* driver collects chars here */ #define tty_buf_count(p) (((int *)(p))[0]) #define tty_buf_max(p) (((int *)(p))[1]) EXTERN char tty_copy_buf[2*MAX_OVERRUN]; /* copy buf used to avoid races */ EXTERN char tty_buf[TTY_BUF_SIZE]; /* scratch buffer to/from user space */ EXTERN int shift1, shift2, capslock, numlock; /* keep track of shift keys */ EXTERN int control, alt; /* keep track of key statii */ EXTERN int caps_off; /* 1 = normal position, 0 = depressed */ EXTERN int num_off; /* 1 = normal position, 0 = depressed */ EXTERN int softscroll; /* 1 = software scrolling, 0 = hardware */ EXTERN int output_done; /* number of RS232 output messages to be sent*/ EXTERN int char_height; /* number of scan lines for a char */ EXTERN int keyb_type; /* type of keyboard attached */ EXTERN int minus_code; /* numeric minus on dutch extended keyboard */ EXTERN int num_slash; /* scan code of numeric slash */ /* Scan codes to ASCII for alt keys (IBM Extended keyboard) */ PUBLIC char alt_c[NR_SCAN_CODES]; /* Scan codes to ASCII for unshifted keys for IBM-PC (default) */ PUBLIC char unsh[NR_SCAN_CODES] = { 0,033,'1','2','3','4','5','6', '7','8','9','0','-','=','\b','\t', 'q','w','e','r','t','y','u','i', 'o','p','[',']',015,0202,'a','s', 'd','f','g','h','j','k','l',';', 047,0140,0200,0134,'z','x','c','v', 'b','n','m',',','.','/',0201,'*', 0203,' ',0204,0241,0242,0243,0244,0245, 0246,0247,0250,0251,0252,0205,0210,0267, 0270,0271,0211,0264,0265,0266,0214 ,0261,0262,0263,'0',0177,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0 }; /* Scan codes to ASCII for shifted keys */ PUBLIC char sh[NR_SCAN_CODES] = { 0,033,'!','@','#','$','%','^', '&','*','(',')','_','+','\b','\t', 'Q','W','E','R','T','Y','U','I', 'O','P','{','}',015,0202,'A','S', 'D','F','G','H','J','K','L',':', 042,'~',0200,'|','Z','X','C','V', 'B','N','M','<','>','?',0201,'*', 0203,' ',0204,0221,0222,0223,0224,0225, 0226,0227,0230,0231,0232,0204,0213,'7', '8','9',0211,'4','5','6',0214,'1', '2','3','0','.',0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0 }; /* Scan codes to ASCII for Olivetti M24 for unshifted keys. */ PUBLIC char unm24[NR_SCAN_CODES] = { 0,033,'1','2','3','4','5','6', '7','8','9','0','-','^','\b','\t', 'q','w','e','r','t','y','u','i', 'o','p','@','[','\r',0202,'a','s', 'd','f','g','h','j','k','l',';', ':',']',0200,'\\','z','x','c','v', 'b','n','m',',','.','/',0201,'*', 0203,' ',0204,0241,0242,0243,0244,0245, 0246,0247,0250,0251,0252,023,0210,0267,0270,0271,0211,0264,0265,0266,0214,0261, 0262,0263,'0','.',' ',014,0212,'\r', 0264,0262,0266,0270,032,0213,' ','/', 0253,0254,0255,0256,0257,0215,0216,0217 }; /* Scan codes to ASCII for Olivetti M24 for shifted keys. */ PUBLIC char m24[NR_SCAN_CODES] = { 0,033,'!','"','#','$','%','&', 047,'(',')','_','=','~','\b','\t', 'Q','W','E','R' ,'T','Y','U','I', 'O','P',0140,'{','\r',0202,'A','S', 'D','F','G','H','J','K','L','+', '*','}',0200,'|','Z','X','C','V', 'B','N','M','<','>','?',0201,'*', 0203,' ',0204,0221,0222,0223,0224,0225, 0226,0227,0230,0231,0232,0270,023,'7', '8','9',0211,'4','5','6',0214,'1', '2','3',0207,0177,0271,014,0272,'\r', '\b','\n','\f',036,032,0273,0274,'/', 0233,0234,0235,0236,0237,0275,0276,0277 }; PUBLIC char dutch_unsh[NR_SCAN_CODES] = { 0,033,'1','2','3','4','5','6', '7','8','9','0','/',0370,'\b','\t', 'q','w','e','r','t','y','u','i', 'o','p',0,'*','\r',0202,'a','s', 'd','f','g','h','j','k','l','+', '\'',0100,0200,'<','z','x','c','v', 'b','n','m',',','.','-',0201,'*', 0203,' ',0204,0,0,0,0,0, 0,0,0,0,0,0205,0,183, 184,185,137,180,'5',182,140,177, 178,179,0,0177,0,0,']','/',0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0 }; PUBLIC char dutch_sh[NR_SCAN_CODES] = { 0,033,'!','\"','#','$','%','&', '_','(',')','\'','?',0176,'\b','\t', 'Q','W','E','R','T','Y','U','I', 'O','P','^','|','\r',0202,'A','S', 'D','F','G','H','J','K','L',0361, 0,025,0200,'>','Z','X','C','V', 'B','N','M',';',':','=',0201,'*', 0203,' ',0204,0,0,0,0,0, 0,0,0,0,0,0205,0,'7', '8','9',137,'4','5','6',140,'1', '2','3','0',',',0,0,'[','/',0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0 }; /* Code table for alt key */ PUBLIC char dutch_alt[NR_SCAN_CODES] = { 0,0,0,253,0,172,171,0, 156,'{','}',0,'\\',0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0202,0,0, 0,0,0,0,0,0,0,0, 0,170,0200,0,174,175,0,0, 0,0,0,0,0,0,0201,0, 0203,0,0204,0,0,0,0,0, 0,0,0,0,0,0205,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0177,0,0,'|',0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0 }; /* Unshifted U.S. extended kbd */ PUBLIC char unsh_usx[NR_SCAN_CODES] = { 0,'`','1','2','3','4','5','6', '7','8','9','0','-','=','\b','\t', 'q','w','e','r','t','y','u','i', 'o','p','[',']',015,0202,'a','s', 'd','f','g','h','j','k','l',';', 047,033,0200,0134,'z','x','c','v', 'b','n','m',',','.','/',0201,'*', 0203,' ',0202,0241,0242,0243,0244,0245, 0246,0247,0250,0251,0252,0205,0210,0267, 0270,0271,0211,0264,0265,0266,0214 ,0261,0262,0263,'0',0177,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0 }; /* Shifted U.S. extended kbd */ PUBLIC char sh_usx[NR_SCAN_CODES] = { 0,033,'!','@','#','$','%','^', '&','*','(',')','_','+','\b','\t', 'Q','W','E','R','T','Y','U','I', 'O','P','{','}',015,0202,'A','S', 'D','F','G','H','J','K','L',':', 042,'~',0200,'|','Z','X','C','V', 'B','N','M','<','>','?',0201,'*', 0203,' ',0202,0221,0222,0223,0224,0225, 0226,0227,0230,0231,0232,0204,0213,'7', '8','9',0211,'4','5','6',0214,'1', '2','3','0','.',0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0 }; PUBLIC char scode_map[] = {'H', 'A', 'V', 'S', 'D', 'G', 'C', 'T', 'Y', 'B', 'U'}; /* The 'pc_psw' struct is machine dependent. It must contain the information * pushed onto the stack by an interrupt, in the same format as the hardware * creates and expects. It is used for storing the interrupt status after a * trap or interrupt, as well as for causing interrupts for signals. */ #ifdef i8088 struct pc_psw { int (*pc)(); /* storage for program counter */ phys_clicks cs; /* code segment register */ unsigned psw; /* program status word */ }; /* This struct is used to build data structure pushed by kernel upon signal. */ struct sig_info { int signo; /* sig number at end of stack */ struct pc_psw sigpcpsw; }; #endif PUBLIC struct tasktab { int (*initial_pc)(); int stksize; char name[8]; }; # The kernel dir contains xt_wini.c and at_wini.c. Before running make # you must copy one of these to wini.c, depending on which controller you # have. If you do not have a hard disk, you MUST choose one of them at random. # On a PC, cpp and cem are in /lib and will be removed to make space while # linking the kernel. On an AT, they are in /usr/lib are are not removed. # This is because they have to be in /lib on a PC; the diskette is too small # for them to be in /usr/lib. You can change this by editing commands/cc.c. # # The CFLAGS values are: # -Di8088 - required on an 8088/80286/80386 CPU; forbidden on a 68000 # -F - run cpp and cem sequentially (used when memory is tight) # -T. - put temporaries in working directory (when RAM disk is small) # CFLAGS= -Di8088 -F -T. h=../h l=/usr/lib obj = mpx88.s main.s tty.s floppy.s wini.s system.s proc.s clock.s memory.s \ console.s rs232.s printer.s table.s klib88.s dmp.s cobjs = main.s tty.s floppy.s wini.s system.s proc.s clock.s memory.s \ console.s rs232.s printer.s table.s dmp.s kernel: makefile $(obj) $l/libc.a @echo "Start linking Kernel." @asld -o kernel -T. $(obj) $l/libc.a $l/end.s @echo "Kernel done. " clean: rm -f $(cobjs) clock.s: const.h type.h $h/const.h $h/type.h clock.s: $h/callnr.h clock.s: $h/com.h clock.s: $h/error.h clock.s: $h/signal.h clock.s: glo.h clock.s: proc.h console.s: const.h type.h $h/const.h $h/type.h console.s: $h/callnr.h console.s: $h/com.h console.s: $h/error.h console.s: $h/sgtty.h console.s: $h/signal.h console.s: glo.h console.s: proc.h console.s: tty.h console.s: ttymaps.h floppy.s: const.h type.h $h/const.h $h/type.h floppy.s: $h/callnr.h floppy.s: $h/com.h floppy.s: $h/error.h floppy.s: glo.h floppy.s: proc.h dmp.s: const.h type.h $h/const.h $h/type.h dmp.s: $h/callnr.h dmp.s: $h/com.h dmp.s: $h/error.h dmp.s: glo.h dmp.s: proc.h main.s: const.h type.h $h/const.h $h/type.h main.s: $h/callnr.h main.s: $h/com.h main.s: $h/error.h main.s: glo.h main.s: proc.h memory.s: const.h type.h $h/const.h $h/type.h memory.s: $h/callnr.h memory.s: $h/com.h memory.s: $h/error.h memory.s: proc.h printer.s: const.h type.h $h/const.h $h/type.h printer.s: $h/callnr.h printer.s: $h/com.h printer.s: $h/error.h printer.s: proc.h printer.s: glo.h proc.s: const.h type.h $h/const.h $h/type.h proc.s: $h/callnr.h proc.s: $h/com.h proc.s: $h/error.h proc.s: glo.h proc.s: proc.h system.s: const.h type.h $h/const.h $h/type.h system.s: $h/callnr.h system.s: $h/com.h system.s: $h/error.h system.s: $h/signal.h system.s: glo.h system.s: proc.h table.s: const.h type.h $h/const.h $h/type.h $h/com.h table.s: glo.h table.s: proc.h table.s: tty.h tty.s: const.h type.h $h/const.h $h/type.h tty.s: $h/callnr.h tty.s: $h/com.h tty.s: $h/error.h tty.s: $h/sgtty.h tty.s: $h/signal.h tty.s: glo.h tty.s: proc.h tty.s: tty.h tty.s: ttymaps.h wini.s: const.h type.h $h/const.h $h/type.h wini.s: $h/callnr.h wini.s: $h/com.h wini.s: $h/error.h wini.s: proc.h ... makefile!at_makefile"buf.h#cache.c.Z$device.c.Z%dev.h.Z&filedes.c.Z'inode.c.Z(link.c.Z)main.c.Z*misc.c.Z+mount.c.Z,open.c.Z-path.c.Z.file.h.Z/pipe.c.Z0fproc.h.Z1protect.c.Z2putc.c.Z3read.c.Z4const.h5super.h6type.h7stadir.c.Z8super.c.Z9table.c.Z:time.c.Z;utility.c.Z<glo.h.Z=write.c.Z>inode.h.Z?param.h.Z@pc_makefile# On a PC, cpp and cem are in /lib and will be removed to make space while # linking the kernel. On an AT, they are in /usr/lib are are not removed. # This is because they have to be in /lib on a PC; the diskette is too small # for them to be in /usr/lib. CFLAGS= -Di8088 -F -T. h=../h l=/usr/lib obj = main.s open.s read.s write.s pipe.s device.s \ path.s mount.s link.s super.s inode.s cache.s filedes.s \ stadir.s protect.s time.s misc.s utility.s table.s putc.s fs: makefile $l/head.s $(obj) $l/libc.a $l/end.s @echo "Start linking FS. " @echo "If disk fills up, remove some files or use asld -Tsomething" @asld -o fs -T. $l/head.s $(obj) $l/libc.a $l/end.s @echo "FS done. " clean: rm -f $(obj) cache.s: const.h type.h $h/const.h $h/type.h cache.s: $h/error.h cache.s: buf.h cache.s: file.h cache.s: fproc.h cache.s: glo.h cache.s: inode.h cache.s: super.h device.s: const.h type.h $h/const.h $h/type.h device.s: $h/com.h device.s: $h/error.h device.s: dev.h device.s: file.h device.s: fproc.h device.s: glo.h device.s: inode.h device.s: param.h filedes.s: const.h type.h $h/const.h $h/type.h filedes.s: $h/error.h filedes.s: file.h filedes.s: fproc.h filedes.s: glo.h filedes.s: inode.h inode.s: const.h type.h $h/const.h $h/type.h inode.s: $h/error.h inode.s: buf.h inode.s: file.h inode.s: fproc.h inode.s: glo.h inode.s: inode.h inode.s: super.h link.s: const.h type.h $h/const.h $h/type.h link.s: $h/error.h link.s: buf.h link.s: file.h link.s: fproc.h link.s: glo.h link.s: inode.h link.s: param.h main.s: const.h type.h $h/const.h $h/type.h main.s: $h/callnr.h main.s: $h/com.h main.s: $h/error.h main.s: buf.h main.s: file.h main.s: fproc.h main.s: glo.h main.s: inode.h main.s: param.h main.s: super.h misc.s: const.h type.h $h/const.h $h/type.h misc.s: $h/callnr.h misc.s: $h/com.h misc.s: $h/error.h misc.s: buf.h misc.s: file.h misc.s: fproc.h misc.s: glo.h misc.s: inode.h misc.s: param.h misc.s: super.h mount.s: const.h type.h $h/const.h $h/type.h mount.s: $h/error.h mount.s: buf.h mount.s: file.h mount.s: fproc.h mount.s: glo.h mount.s: inode.h mount.s: param.h mount.s: super.h open.s: const.h type.h $h/const.h $h/type.h open.s: $h/callnr.h open.s: $h/error.h open.s: buf.h open.s: file.h open.s: fproc.h open.s: glo.h open.s: inode.h open.s: param.h path.s: const.h type.h $h/const.h $h/type.h path.s: $h/error.h path.s: buf.h path.s: file.h path.s: fproc.h path.s: glo.h path.s: inode.h path.s: super.h pipe.s: const.h type.h $h/const.h $h/type.h pipe.s: $h/callnr.h pipe.s: $h/com.h pipe.s: $h/error.h pipe.s: $h/signal.h pipe.s: file.h pipe.s: fproc.h pipe.s: glo.h pipe.s: inode.h pipe.s: param.h protect.s: const.h type.h $h/const.h $h/type.h protect.s: $h/error.h protect.s: buf.h protect.s: file.h protect.s: fproc.h protect.s: glo.h protect.s: inode.h protect.s: param.h protect.s: super.h putc.s: const.h type.h $h/const.h $h/type.h putc.s: $h/com.h read.s: const.h type.h $h/const.h $h/type.h read.s: $h/com.h read.s: $h/error.h read.s: buf.h read.s: file.h read.s: fproc.h read.s: glo.h read.s: inode.h read.s: param.h read.s: super.h stadir.s: const.h type.h $h/const.h $h/type.h stadir.s: $h/error.h stadir.s: $h/stat.h stadir.s: file.h stadir.s: fproc.h stadir.s: glo.h stadir.s: inode.h stadir.s: param.h super.s: const.h type.h $h/const.h $h/type.h super.s: $h/error.h super.s: buf.h super.s: inode.h super.s: super.h table.s: const.h type.h $h/const.h $h/type.h table.s: $h/com.h table.s: $h/callnr.h table.s: $h/error.h table.s: $h/stat.h table.s: buf.h table.s: dev.h table.s: file.h table.s: fproc.h table.s: glo.h table.s: inode.h table.s: super.h time.s: const.h type.h $h/const.h $h/type.h time.s: $h/callnr.h time.s: $h/com.h time.s: $h/error.h time.s: file.h time.s: fproc.h time.s: glo.h time.s: inode.h time.s: param.h utility.s: const.h type.h $h/const.h $h/type.h utility.s: $h/com.h utility.s: $h/error.h utility.s: buf.h utility.s: file.h utility.s: fproc.h utility.s: glo.h utility.s: inode.h utility.s: param.h utility.s: super.h write.s: const.h type.h $h/const.h $h/type.h write.s: $h/error.h write.s: buf.h write.s: file.h write.s: fproc.h write.s: glo.h write.s: inode.h write.s: super.h # On a PC, cpp and cem are in /lib and will be removed to make space while # linking the kernel. On an AT, they are in /usr/lib are are not removed. # This is because they have to be in /lib on a PC; the diskette is too small # for them to be in /usr/lib. CFLAGS= -Di8088 -F -T. h=../h l=/usr/lib obj = main.s open.s read.s write.s pipe.s device.s \ path.s mount.s link.s super.s inode.s cache.s filedes.s \ stadir.s protect.s time.s misc.s utility.s table.s putc.s fs: makefile $l/head.s $(obj) $l/libc.a $l/end.s @echo "Start linking FS. " @asld -o fs -T. $l/head.s $(obj) $l/libc.a $l/end.s @echo "FS done. " clean: rm -f $(obj) cache.s: const.h type.h $h/const.h $h/type.h cache.s: $h/error.h cache.s: buf.h cache.s: file.h cache.s: fproc.h cache.s: glo.h cache.s: inode.h cache.s: super.h device.s: const.h type.h $h/const.h $h/type.h device.s: $h/com.h device.s: $h/error.h device.s: dev.h device.s: file.h device.s: fproc.h device.s: glo.h device.s: inode.h device.s: param.h filedes.s: const.h type.h $h/const.h $h/type.h filedes.s: $h/error.h filedes.s: file.h filedes.s: fproc.h filedes.s: glo.h filedes.s: inode.h inode.s: const.h type.h $h/const.h $h/type.h inode.s: $h/error.h inode.s: buf.h inode.s: file.h inode.s: fproc.h inode.s: glo.h inode.s: inode.h inode.s: super.h link.s: const.h type.h $h/const.h $h/type.h link.s: $h/error.h link.s: buf.h link.s: file.h link.s: fproc.h link.s: glo.h link.s: inode.h link.s: param.h main.s: const.h type.h $h/const.h $h/type.h main.s: $h/callnr.h main.s: $h/com.h main.s: $h/error.h main.s: buf.h main.s: file.h main.s: fproc.h main.s: glo.h main.s: inode.h main.s: param.h main.s: super.h misc.s: const.h type.h $h/const.h $h/type.h misc.s: $h/callnr.h misc.s: $h/com.h misc.s: $h/error.h misc.s: buf.h misc.s: file.h misc.s: fproc.h misc.s: glo.h misc.s: inode.h misc.s: param.h misc.s: super.h mount.s: const.h type.h $h/const.h $h/type.h mount.s: $h/error.h mount.s: buf.h mount.s: file.h mount.s: fproc.h mount.s: glo.h mount.s: inode.h mount.s: param.h mount.s: super.h open.s: const.h type.h $h/const.h $h/type.h open.s: $h/callnr.h open.s: $h/error.h open.s: buf.h open.s: file.h open.s: fproc.h open.s: glo.h open.s: inode.h open.s: param.h path.s: const.h type.h $h/const.h $h/type.h path.s: $h/error.h path.s: buf.h path.s: file.h path.s: fproc.h path.s: glo.h path.s: inode.h path.s: super.h pipe.s: const.h type.h $h/const.h $h/type.h pipe.s: $h/callnr.h pipe.s: $h/com.h pipe.s: $h/error.h pipe.s: $h/signal.h pipe.s: file.h pipe.s: fproc.h pipe.s: glo.h pipe.s: inode.h pipe.s: param.h protect.s: const.h type.h $h/const.h $h/type.h protect.s: $h/error.h protect.s: buf.h protect.s: file.h protect.s: fproc.h protect.s: glo.h protect.s: inode.h protect.s: param.h protect.s: super.h putc.s: const.h type.h $h/const.h $h/type.h putc.s: $h/com.h read.s: const.h type.h $h/const.h $h/type.h read.s: $h/com.h read.s: $h/error.h read.s: buf.h read.s: file.h read.s: fproc.h read.s: glo.h read.s: inode.h read.s: param.h read.s: super.h stadir.s: const.h type.h $h/const.h $h/type.h stadir.s: $h/error.h stadir.s: $h/stat.h stadir.s: file.h stadir.s: fproc.h stadir.s: glo.h stadir.s: inode.h stadir.s: param.h super.s: const.h type.h $h/const.h $h/type.h super.s: $h/error.h super.s: buf.h super.s: inode.h super.s: super.h table.s: const.h type.h $h/const.h $h/type.h table.s: $h/com.h table.s: $h/callnr.h table.s: $h/error.h table.s: $h/stat.h table.s: buf.h table.s: dev.h table.s: file.h table.s: fproc.h table.s: glo.h table.s: inode.h table.s: super.h time.s: const.h type.h $h/const.h $h/type.h time.s: $h/callnr.h time.s: $h/com.h time.s: $h/error.h time.s: file.h time.s: fproc.h time.s: glo.h time.s: inode.h time.s: param.h utility.s: const.h type.h $h/const.h $h/type.h utility.s: $h/com.h utility.s: $h/error.h utility.s: buf.h utility.s: file.h utility.s: fproc.h utility.s: glo.h utility.s: inode.h utility.s: param.h utility.s: super.h write.s: const.h type.h $h/const.h $h/type.h write.s: $h/error.h write.s: buf.h write.s: file.h write.s: fproc.h write.s: glo.h write.s: inode.h write.s: super.h /* Buffer (block) cache. To acquire a block, a routine calls get_block(), * telling which block it wants. The block is then regarded as "in use" * and has its 'b_count' field incremented. All the blocks, whether in use * or not, are chained together in an LRU list, with 'front' pointing * to the least recently used block, and 'rear' to the most recently used * block. A reverse chain, using the field b_prev is also maintained. * Usage for LRU is measured by the time the put_block() is done. The second * parameter to put_block() can violate the LRU order and put a block on the * front of the list, if it will probably not be needed soon. If a block * is modified, the modifying routine must set b_dirt to DIRTY, so the block * will eventually be rewritten to the disk. */ EXTERN struct buf { /* Data portion of the buffer. */ union { char b__data[BLOCK_SIZE]; /* ordinary user data */ dir_struct b__dir[NR_DIR_ENTRIES]; /* directory block */ zone_nr b__ind[NR_INDIRECTS]; /* indirect block */ d_inode b__inode[INODES_PER_BLOCK]; /* inode block */ int b__int[INTS_PER_BLOCK]; /* block full of integers */ } b; /* Header portion of the buffer. */ struct buf *b_next; /* used to link bufs in a chain */ struct buf *b_prev; /* used to link bufs the other way */ struct buf *b_hash; /* used to link bufs on hash chains */ block_nr b_blocknr; /* block number of its (minor) device */ dev_nr b_dev; /* major | minor device where block resides */ char b_dirt; /* CLEAN or DIRTY */ char b_count; /* number of users of this buffer */ } buf[NR_BUFS]; /* A block is free if b_dev == NO_DEV. */ #define NIL_BUF (struct buf *) 0 /* indicates absence of a buffer */ /* These defs make it possible to use to bp->b_data instead of bp->b.b__data */ #define b_data b.b__data #define b_dir b.b__dir #define b_ind b.b__ind #define b_inode b.b__inode #define b_int b.b__int EXTERN struct buf *buf_hash[NR_BUF_HASH]; /* the buffer hash table */ EXTERN struct buf *front; /* points to least recently used free block */ EXTERN struct buf *rear; /* points to most recently used free block */ EXTERN int bufs_in_use; /* # bufs currently in use (not on free list) */ /* When a block is released, the type of usage is passed to put_block(). */ #define WRITE_IMMED 0100 /* block should be written to disk now */ #define ONE_SHOT 0200 /* set if block not likely to be needed soon */ #define INODE_BLOCK 0 + WRITE_IMMED /* inode block */ #define DIRECTORY_BLOCK 1 + WRITE_IMMED /* directory block */ #define INDIRECT_BLOCK 2 + WRITE_IMMED /* pointer block */ #define I_MAP_BLOCK 3 + WRITE_IMMED + ONE_SHOT /* inode bit map */ #define ZMAP_BLOCK 4 + WRITE_IMMED + ONE_SHOT /* free zone map */ #define ZUPER_BLOCK 5 + WRITE_IMMED + ONE_SHOT /* super block */ #define FULL_DATA_BLOCK 6 /* data, fully used */ #define PARTIAL_DATA_BLOCK 7 /* data, partly used */ /T 3ig2m@ nBL3f1&̘ ! :c AN1"A1L9kh29e4)ҥ  \j''ǖayGN)W4(=,ed1k*\`c;yWY7)QHU%Fj0wdA_Lt#T4ua./C.!~*((yјgz "y'G驤*v"`i:Gf)`| +g ,V;Gʩ+k@W&0 |Ck zBQL$1tqn(j[V~_ EI-tOnxlb=*Q`0s| &|E.̯LrDr&O|!EAj`tlՈƹDk V\u`(W@U@XS(2v !G<ŻoYݣ!HjB!)WBd̖!Jۛ%T7Q. @`K1>ȅAV*|C >A<}O\Ԑw uJ~8M!wjUsB0_ D !LP4bF P}sJ$ԈbG{S=AŕveB̫j1#Fsqr)ep1:]w2$j3(KqFiePR2e-%)d<h-%(Za7wMё?q.*ATCu`D[Yx$sLC~daͣ?2Aeh7jns npHIw&dr4P~iᄎG%ht8g" x1-nR s0PAaYrmp9>QcqXpyyBKd3T00*ajTmJ:ERb-HU:tH7dC#=% ['FW)tGjq3\e@Id?%CZTXvPS-E'2'cǤo9A`b#u46Th8TEqu Leu_ēȁ[C%^d%xFl!%Tu-cB9Z%YmFQ`&-!(L9qVJa ŎF@kcbDj'&i(jYb(Ka7p9Brw]k9f&kRj!f!f ?mti2v@5Qؗ]&w&(hDOETH%t8=C)'@LYIX#.4LRqiHBuEs|I77;mdE$AK 9s.c?)8!c@Kd;=zЛȪW)=h6y#bgsa`I~z@f r¼_td;g K9"'K7?OBqrI 75!v(! 4TB2% !P+kQLW|w!>`Tz0Jĺ2eF:yH |@.fa7IyUsk P*6)TT3P0MuM)M(\' Y@Epȋ;Č!f ɒl^_<_MINpy̅ q%+M#ݍ04V!f0N"6 JKEk.^4#M[ƅ)3&M6 ф#N9.Ӱ)7 䔉S'VI^xA:r-lqu*B:Η7CHT2 Ag@sH)}M{ZS7A_0V &9%C2+u0δ6(J`nKؚ"$ G8@E7QiZs6ʡ3?7ԡ ,$f|@ J[$8mbn&3@%T6N&F4ɡ ȠA^ch-=ܥ;9/5ڡecŴD"2hGwxhbߐ >d1G ' pRj1# BA)&pP.:> 8#9+@_ph: QHm#7)p_u)R*8 A;(SV 3Ɏ:ֹv']\pG2꠆7RDZ e H3RRx+K? ]}JOi u⟏\lCPp*t(R΀) + 8 tH='9>y ̐:"l7"O;pHDl8@A(8Uy: .|Sӌ:! L 7dRf324+ix wrT̑&_0ŔhI:W9 rP*d? <$A Ѓ&&ƍ'sO򙿠a 0c[̌yԧ@*QW D$Ɵ 6nd%O@b+#ɽ_EtG_<rBR%ǛճG{:^M"ԏ}ak+2R'rrIw(чPx#PeA`X-#7@{AT rak12Nb7wXQ{r~7H]"S}1 0ׄR!7ol}&BzSbDx3Pc(D6c0ok 7((<6q P Kl?7ʴ?eaPa`$#u5t yЄ臾 H|gPg0nxUfDQi`3TmgK0|h|"@vp $YqXNYUM0< <6j㎩\͕:C{P!g X|kx+x8xUgCX~ZG];2D~]?Y1v UsHLrk$LIa\!i RQ(ёSJC*&)_J쁀Łk =hrWnc?A2$#F$#A%y,OHGQlq ͔G8(z==v0sf`)$Znj';#%0V(p.Uf'{xB USiNPLd00(E$txCQie9$'yzzÌw;YՇ;z#vYyH8=&Ӛ yS7̩zEE<CאW~ `$]bǟ>5k †n80#HdK)@ QCwHFJyӁNP Llpa` `?8\Z>umҨe%:'>3Y@*&dwph0]7Uv Pav.b6~cG9RG=֣6I!N (ObKB!rYh(g2&wL_cP!Z݉dlqQɏٍcxRyA!wU2 BDi&@oT(XU  ]Yq<T:[U Sp +gBu뉪Qmj1Rz< ,;49pM!q$|ekZ*::)S9yzz^8ɱ+0Siy)eq-q:VTG P`(7@KnZk<볘fjsBXYXwpXm\?9$ 'Bw>\Kä`'t`^# 6Pѧ3?XMmhJ| xMJ uV`nP|DdabjRa^z$M5&65e*:=bRƭ¬?F*jJ֊g ۚ 6{.皮ɮJcsi0W 3ʨx*v$ļvdWѦKFts;CbS-{z06omJ۳P &WI}e}C@5kOt( /T RN1e@ #M @PAfBATL%`b[uՉ&f"*(4ָ AQL$1nQW(S,Fґ'ͱF2Bspb@&f@uQf t%C5R](HqW9G >Okh@pTODGgoUQ% *4'}񧙂^}-1AYf5jyhgpڪJ jk.deBl)&Cmx 9DtuDC'DDmPƑCypÕ9޹hIҺXtTJOHѧ^=`>Ԭ\wq*-Ġg\w5aeflFn6Yu#pYq9rFjrDbĔdvŐʉY  i01 ; 8!F1Ei&pE]8=I0uP\*ў5AbܕXcyo&Fn(HaywR/C\4Yfqna߱,T@gr[DF]D ZrUS݁Qyda) (1@Nq[}2IAZt& aNl[EaR=`[X=7P5-L3C –3(p0_q&UyBR4&xRpYک K*3p) azc+8sVO,&m}΄++R(CRD ZB cf9RhLc`ĢE. H:(G;я%OB; RʸW:Q 3cNp fPmRc䥡.DT@ý!I.ԍlHO[a&V!F8XV\wȩE|Cf⃷]-kSB(Mna./9 Cڶp.c\0jqU dN3I1s>2GsHϴ-ϒӓ/qb ;D\O$V}Ʒ;upO]:pFMnQqiWR_^SdtE bId},ds9g,\ɣV@p, WU(2a"9ð. eo"XQOHUdmBJ'!j\Ч4ixAp2aw„4!'$Zgmh1ڪRs\෸~6ES+KjA ӖkX q۾T]}W LS@.A \V,7=R!;C=P_dQbam|:eH9/T&fҰ)M7aΔ9H 4nސaH'.@ (a y3 :%) atCFkbƍsXNJ 3҇d@\H6Wyj-&+VwS`2mk\m;a7tI#gV4Pɒ|EJ2:zr 77rh8_GmDF:IZ[4)PY3DuI ˠfqӍnʸt !\y eY96q*cuԩ8;i)<]0mFlql 6^rHriF9$='U4B-j=BqdžʼnTRo5YeXc8j1RZkKpИH!Wr XFUс0FgHh)`m#`4u& . K1.!v'~@Gzhnܙ'C{T+!)*i~Jz>uaj BB zKZgw,"Q~@@=Tkfv-* LF#aO߶bPT!I !``uOFv(%_b_;]eؑFK VASH$'q cW;! 1@Fd7QnFAGBJ[]s7F Ult̴VX=]X09r< sH $Q B 8DaRj̇UfFI qic r*R*~0dq]k̐{vZjWl 7gVy HvL|mC. & ]̶; NH!;ELVB Ȝҹ+ނi|d| !@`Fge|}؊<:ϫ#z@1;Ѓvچt۟B0sKs k@B?ri{{9jrpM,t{ V0}_T @JR m v7Q(џHmiDCt&*&%v?dh1X#MH@'nyOh[ i}Bt>3&0KR( F]ZH] P.rQ$ %?D.{PB1 Cȿʉu D .:ns]lc{q] ?kk'#qJB@du7/0b'eRrqfʧ>كu]pιȅ!M(e/|+É V$53ܿ%0[sZgⲱp>0eNuc9p1 f/cAdg-$ H Z]t4@w)JvZ2UjKM _iTko`Cd"IsKqQI*ᠣIԝF55JhG{j-RCdSPإ.rC<u5 ub o<^ 9T!Crn VVe6ud) 5*M$TI\2L"0w0-@ AP@V tFRcq_EIma`>LJ O66. (3Wд 6 rJXd@ Ah;w.AFP ]Lr~ (^ wah Du kTRP0s^JSb*ˆ,rں%zhwk9A>;M`3™̐ =I-# Q<ߋsj(v^YS+S^ y̴dnN1'B+``v)Y!/ 2@LfP(L:Zw@"b16&B1U\3zOU3UFq'5q#d !(a'4hq_ޔ`RJ?KQ<.CSVA!.!^]3aP a:+ Jp5%\1TepSfE!6]R{! p@$RqWup-r8_984'!b/%F.ā.*vPxc 5c84hyVceIZ,/^SAf׊yC 2{5EQt|!0 s!I%df\FJVAhhkrA$gHKz?~gaLC_ЋPx'>VUf=6Gڥ~>X h#yrY aLsqCē<_OE]US0i =D]zS[]: 9x`HPe8ע2/<)Q2?V1dJvsAe @2AL32j7Rd:33RBo}`Yp%W]Ш4m\(g],#ݦi措& z)k!mlqKeV+F%ƗylpzYFxCev|FC=JIsOBٚ$.&DaA?b)DPZ!1CJMfp{g@Q&8wIusmZm'sT:)Y&DN1aAo2;}S&ѹ$\"ӨKTE/R* Si4wifUAi"юN+o ij٠jEGB]Ɉ1HynƙV1Vpg'[@-1/zS_E@TJ6RrLPj:=bPVZ A:q6s5KpCK*h:!@YNNpNճ?(q?;E)pJz_0I4rNUYZT*Dʪ5E:CRl%>0 9šzK*`:CqA*p B%(.ez9c*0yc[جaI%Xt+!!T7cU4]jI=ҢRr!ǜrF}l(']$B/T&fҰ)M7d!$NxHD'3g2m@ Æ @$dʰ$ 3~#M}*494ad\Ay :#/WpliˠG?Xu`GbRafhp"Х.-S+0*(X't@6H'dΉPiW.'L mN\PˉʹYB )PFRҚL}& 2f@7qʤb<2̊8MzBqhReGGǜa+N60M}R Q(& Bc :__~Y 0ɼ*'15"up aweB4eHa*Bx'1rBU1qN(P=40 ~ qM8tB5*zBc;d  HqGtdUNw}I1h䲁u_[h,&t"_@ZN-NPMMx#!G2e7W+O_ A74( w*J~Ttuw_ wZN"GLwmQ(zH * 69&u#VD[߂h:ܘHfS6TH臀(Aas^8uxX VFCEY7*fSL}CLHqh\Va(@ {7Hczk6nG7/r@ap] 1UdQ,Ac*Snz6*IxQU79a1YAiUyAFl"@@6$w"We+a/F,'/T&fҰ)b7t¤qsm$GΛ3r´  (d8%:eڸ" sÀ` hF| GDA4tQ#]59afm2{EW-JEX^M6Hw*T X|!EMlK3@Fuo&" MTkDxӾI0{D Sp 0@pjB W27LUQMo:r8PM|DwG$ᄭx+V0uS1 4,C hRo2P|u C_}]]Pt!]@=Tngw9*^{ޞꬷ:CQL$1{(AVdgyH$䖟 L2DF UQkԓ@!u- \UT:\Uyw%Yp5W]>aniMfR( (6t JQ˱> yvy^LXSfD4qa0`FDJl-8aA`Ѕ΄'>DJ&+A&(Qr#Z@D٥DV_2[AP"K=wqʷr#!0J#R@؅ qS7$aPS('C`P-3! uP/T! v@}jnAX]^,́XTӑJ2́,͡msA@ 31*B:H4-yZܒ2F':G6 쳟 !o=d!! 8ԡ P6E%a)CBʰ 4qQncXA,R.6]cOA3tXFO+ H!ͧu2 bH&p OP"m!ޓ YR>l[V T=H L7u{Ad' @;V &'|’(-}'.8Hxʰ@9U'~p .eAF[]'> j}V2|&AUDn"81&An[5o{@[FsH*|]QQ ldQZ`E:A _Caw+x#H Tr !$XAjG/Hf1>,/Z`u,!a8|:@"l=@6%Uc 8x Ld#NfHJ,k pL&٘ f.R-*| SB"3 ` SuqRw;g$>p6׷-hP9ȀM@ܰ)t ND7 D_pBpcJ[p$y%A|$je/ ,mx{7} #o;2Oo|R&miޘ&9]8a)Kp+t4] ;]n'=,6DhqGQ Po08P~Ҹ(XP`nD8Vx޽g % 3))|&61b Xy 9r5,C5(d!ultr!dwjgB5mJ7G$ Po^t\V.}0#{.SE.~6Ƃ7NDT8.vլA "\ I 5W(:̒L.ߛ2p;aw+7 =ĩ.$\9n / 7z{eb6!]qic>>6DQ!W (v-86~g{nqdIeM_P@\X2PTF/L0 LiO 08$*6HvH#8[$Hh1VׁRuadS(5iLJi7&eзQdp)_V}7&=jb7]fW,K.JdFSS`KQ^JyK|臀gs؆l\K!QÈlf.F(tc s,aH~p'ksSslDuuQSΓ#AI#7C2OkM3I ^@snȌ8?xn挽!CKza( %d2Km8fEݸ3aE&W(Xղm(ُZ OF@S1 7 !9%)8'y)җ^!)U`% P6v9 `3n^S%!2gxfH3Pijg'VP)Ek7Xy1~X٢X`z&zdY;W~W9'G@OnB/P0dIU.,cPGaVŨI'c%+bD.hiGH!EI%rcDベa)9If! p8%=JM tUg0t@wRQ@%A<2A:Eeƛ t4 9ufAy$q|ę|ޕ}7e@!GbiP4GsB!_fjAwp.YFqhfxp.QdR})iArsSwaDC'rBXO1J bHodXv`I]|5R6'6a83,ID45z&LH`7 :`aA$J1SL6e>3CgT_fXZ`LHrWJ~ŦGAc1x%~>`.A[\ZV@C]Ч$8jVAz^D00T'Z&^!E0@@G(=eG3]}II w*}4'D_`xIwUC2A}'42[7_o'4"Q1!s[w. x wD!x$J4a}jiRs-U |;~zMaGRTPW3k3. -'/[38l̫D.!g9~I` ,̯` n:[\l.4^2b!F,!dlg\ (`NJ<dž44ǚ<|IӋ,bgsy) =*!WĤaDtwP<{Aw8%2A$:d3rAS quP/1nD@14a&q?MX,.$S΋z1GPp1-0DW|\"pc'j"ٱqrw aJ{UF^!SѨU83B&vVz, A~STH^"e@4XlM h -׼ysvW ʮLHL{iM18z!_OiHUc;AX[!(R:D\QW.Mʹ1sjO};=ճTHR]=s=qLfsq!mJ q}\Tk_5wFhT!U؇=%jhjGx [9`k4jH~4\qjݾzvA=337!8/9DEA,g0f"d(h=y j;)OFfE= :sB`Rb`?6@ )> Rtc7C)1q{=uCrDa}E6m`6!6S7hBwQOM/_<E0H^$ys35xLD1F Uh; 3b PHIl?OPN0Ć|`R(L7 ָmawIIwD\]xn6sΝo"QaG1K$(8c}nnB&)!T |s,j9M`rhP9L^<D.Њx*P Q8H含Saw&2dpie -/XCM?ŀ8t[ !%s|I@ P,Q@\slށY@֐JС 0QFa_KB΀ Q0!hj"څvI>g(KH IH '%,4Њ0 "l+ǁ,4T>63 ZxL q#0 q 5L@DYU¨7*uB@zS&=WĈᮦT̎C<$qIO@"if$(u_X9(&AϖTM W^`7a WOx!,J@#5bH[)[ a~@ 8FATsS;lA=#1C <,0P b$/P>AY1&vIiGk0jHWJn#ց8vA{5nBLpo&v e%4Aq(ŸU΅p 5DX*X?p B(#D$},}* 6M<h9K0Hy d!#G> /܅+xv&*PW Ttfn<~D3[Pd${0D' sX $f $s X$S}-RG.2n䎧A"UP> $f ȳt|0*p+. `A %yf&*FD݄# &Lj:9z(jr`Lc ARuIO2F(2 D+)"%1$üIO 8|OKPN -!`n`RnLnXFU[yHDDSz)uPLYk2XS p 2ʱ$+[Ƞ YE])8xLR[hn](nJY[,ѡ}2^ K-ULoQf2T~h,WP~@2a&,@@v4Bps^AQ@#DdS>\ bP|p6Ȇq1~p€>88 痂3Ɛ/|:?jHߕȀ"OD WQfBoZH ث!Sd2g}BlM CItW(I)L Wݸt~#tV6S*#Fi!d m9ՓJi*g1r=LtbOdXgN񘢰M $kK3EI')P9as,xu̝?4nvn6JdJrv -a%Xk6fdlf2xE/A7uB]eI= r@NsEip&=^i,DthaR"dA9oCC&uf;mK?Qѝi$Tw3pBTRXղ90zKj/a `3k=Rz La m_e.@X2@@e&/5Ffhrc1nҜJ+-1kn2Fq_=+~R*T%H1b@7RBjb "mѼɰFdlM A2m ̐7H΀{oIi PTy2b^]ĨC3Ԙӯu؂ VunҎsbBQ/T&fҰ)b7t¤qs0L7l!7f@18L0nʼs7%ԑSf  i$:hʴQB 2r̼Ĝ4m,tg dS'Ϗ@$E6iЙ ':CΩzl4 \ ۼ&I$B ]j 0gػw`Pe 1 D:OjB;$E& +e3*PZz7l[ dq2DxݬƋD5ÐQ.bV4sUN& Єitb <:qViwK%q| Vdo\՛_ LOaWSQWi0gЊsĐK0դvuGiQn;ہ5*x!\wBiMtƋknvuL)C'BQ"> \ĕ)K\3liWȘ X4օ,X~$ж.(C .$j[ DVG°u ܙŴ|򔨜 ޕ<,] WQZ\"׿!L9c85%7$?gY2!'ygtɞF3,KO*0XMUQ0Nd:/&k(ډ2 BԴj  ǰBE As֌H:}rF!M(s 2Afmf[: cZsG%evЃmVp3#;_nf*?YEhۺЂo9_\#Qäit+䡻 7GWQb~RWL)!p0d$nICwh$ŸAV(t12iWqi;#Z6,9[946Y _ "2 4d-Ag](iC%Y8 r=strh-wԸ$Hu)D<"S׉(\F,FARa+%<֓zzGur;$Jb)o0GEI}ӊ8A"UXPTdYAe2$< WkGqO(`,;B I%"sw3DuTo?Qq7]yfT*h;4.yQ=W#2hOqE[5;8iw6PoTt!c 1 RiQ! Q'2<` WwcRպ(0-RP{K)YTAJ3:tCRPED'5;Gwf/T&fҰ)N9fisMTqBD7d@TɸEGrBP!E)|IdI@{«eAQ>YG e94F/-Ћr{k ,(h-"1|gXb1B.)VF' +kU^[-h{ 8Davkզ\ 4KR[ok UV =!?XFH&,fA+-t d5"vYp,U,', D\ULE݇|ğm>gOݡ[V'nE_T)^  -`M(]%v{Ľ_@"GYC;a_hCER(B'ae&Da o":poCP%$`kV54!e1"jֺ-ApMy29LƂe a$6HvƷ/4!G|I *A,Mvs&#JҔ PP)48ˣ+APJNzzze.ˎ`u"~4+|)#`08(}tBA'eSy)#E 1[H&HNat``1X`b-v14l̘|Ȏ)dg3魓)͚s'¢U%8ԭT2P`/Lgӳޚ'A̅hDot=ɑ?WBFuVQإex/~Y0![iʰP[Q}pԫp&mIF YZ)!,!oBK4C@B@7 MY@&:§>:䧕E7RSܥSȑnlS(&!5 [$ k BۥrS]'0 $5H ]& bQQTK$ri# A98T Lx>()k[e %[mo8Cj<1{T&8.}o \HP\20 l'^ 5 + تp8H aw>d =AEuNiUۘ uZGѐniCpK2jeu $$qTx^YjY)-+py diulЬw5}-%HE7H5M [B8E9,OYCQbSޖ8dC@-ae\ur4\$[ խ1@*Èj4b&e2  J;ZϙdpgH (CL5n9C@@")-UY,HR%9\"xR6;%ӖIYE2qSJeW''iK6A[G IAO UBy<"D_Rϥ,~Q"#EIaӤk2p01ISܤ8`UtjUœu [4jǺz%,b)iX5eMˁr.qkTUܥ+ "ʯ`/ [S9>aOi,Y33]2.ͭ(pYe6ݣ)Xz=iHU'5;!q6aaܻU)/;kcLXBN"T Z@Y.}EL)L(v SJȕ3A?Wݒtf%!6VG~]T0^4nʴBuHwJTw#? $PsOs]x=hFSAB!~xh#oE^xCIbuu99%:RacuRBlӄϔb06kL݅M/(V*A`'1"fGD/RdPBli`l* a׃5^R@Ske#&b$P54( 2G<""#aMF?V$u1|.G5OYr>1ewxlvlz;iJ2oATw~R8@wB_{Js i4NxfRpq^)R7osY GQ22DFjo)ErigMoJ(Pp᎖fU~ԘN2VBTKH]Ep LRDy(pq qr G3tRr&rY,P I@MTp^"viv 53-T?pCϔ&*jEP)rt`4Sl-(`e`{؝Gq /T&fҰ)b7t¤qspSL9ey#!0t&a 2nT ¸!9eʬQ B!]TtE0Λtb}¢ sl 7_Ɯ#K9#t"Ag2sDŽaÆYmָyC۸s-2l"{ <ϲ \>RIfv6|6mMO˥p'S,0ml Q1j /dxl}P`Du0 4/Rل_ :y^ x gzر| hi!螂_ Wa7 'Ffd|& (m"Qӌ!8ce"aF *IXpc$mEaE R|!DTt`T1&,Ütix|ɔO @mj V֟*裐Fj AQL$1XV(J( AݧtƐex)Xa.h]Y a_%%Gcb GpkVRr8 BesidYY+,ƪO*~Tvb_aTˣOnqȖ*=`AqjkX 7ZAd5$Ca!ae0 fAG*,5LBnaKMPkZ>D (@)2(2a(Y&&[/Ka+T) ]ʼtQj@CE2 THTjLAZ&]GTDRճ2dA0M\V`#G >ETv7fw)8UT'8$@ S`S%cH`(DdɭNz7CX2L&蠈 Rp8$V4&щKA4/a 0]+>آR- %03}(XF'$, B$a La': ;<)9 oe1P0Dػ6f@%d6%3D`0"ԵK4ۻUJE Z*X nY*XMazmqj׾2 QI (,Ml g)LiX bQJ ҍO4YLV .=o0i…$~\;0< ] ,@_JҼIz˕GU-Uҁ%6%2XSN2!D**(#Ҥpul;+ e~W,&(Y– {-k!9XRQ&IB`('3S5r vK[B XaSymQP+#+hKpE>ns+KC|fPXfL/ Ob$TpnG`\wgR&w+Ed*N7wwqPNwAeA0(|PD|/S5AB3\ '[y3dӄ[WRPODDR'0s͇6X-Ld,$\a Q11'EP[sƢ%F(w% q˂FQ~bKnaUWe*SAAo 1noՉWvvES P zQr%qsvx UVs@%Bxs#AowDX.cOsmBKe`%f-h*R=;k81'~|X=%b[w5c0W+(1n((<(u))RUYyYc+P5",-)gppu/òc.^UTZu$X[/eeU%'c~c;Q 0׸0@BEjIՕ #iD2&)2q&,iB;jn_1gD,tV,!6D јw'jnCw&_5TT&6sM)?ɥCS7_L41tDM?f3 GE$IE_FbDD5LJE JdJEGu9}`/:I84ETQD@MdL]LoZN紦84NLEDPLu Hc_eaXOK*F ;%՗WYTTKuM'`SVUUWWH_V_Vbd pV] VocU-W={24aeb;zu%eE(Ase**@3dP+x1e9q)וʢ.Z0>YV0#R0&g(F5au9%H$XsŦX=3DA%$SS5]y5Y.g4&^rע.Һ#jpn)/zc1R(U?zm4'$1ZeFhZ#_R2f8_PLĨ˔9py Nd儧}DDKNS+x\d2C%$M' @V >d4e1RO@.10Rr5X\㌟g2?ĩѧaG:(kc 76{SDwU,N  gyP 3Ej6*D[ ˳G wCZ\sO A1ph][eL  \NZ1/~'G:<:V䋸Pi:WSb9uf0&?3g@\\_ZEMԌǔ8L06:`fdZD8gK+p~,3 L2ψ\;B7k <Ew4Y;utS+@oKWƮS=ҳM;A.)1Z'ҿ.+]p\⥙Z>kf*f.{tdmPT[I1M)͵b[uWaɡ (0DcQGW" h0[R.! H(@Gp"n8"C%X(#+q$>xcO&%baF1 -ĥ^Fc^'䗰Ifs$֓ Þ|矀*蠄 WQ $etXס*j饘f BQL$1DVŨ_ YQh@gWM9)]Aũ{)ٗk]'SPAMNYʼnUbWmE_q[e TDL|OQDSQG)`rP8@IuB^EqHԺo%%rZEꪠ ;L,X .A4QS$E]؊+ox B {%E EHݰ^ DFuhPiWu}7t9c nCcEv][Ѕ '$>nSC?{Z<}xS߅5 c }V%p] FF>tX'JA*j $5)P 4T>Q1T#Wp_F2V1[]+<N?íe/j(\m"Kz|}P!8Te:QW`ruxJ bߑ 1W^u!k_0%e([b(5 h:Z _K]B`S\ (@7;<u@q}RtȖMa|#&HHOt>4:Jvq{ܽ5ɿd8Y$.ZAA'cN.@/i|1@y[6(ZjLF92X@iktfh&Cxk-⮛h.7dׄ9NV NW:f(&Ԧދ VP9% ΂+vyM@&y-U2$o3@`o A`d$\&C=Jol~En/ JY oTYH] 6:xf ɷ] |!ݟ$ AlMCvǻN'NE)=Wc6+n'QKT;u1XSHfKyJ=Sq77qSw&4ww{w]xM 2LNp0sWr[AwPOtN >3@$c?vbcBae)")=Bh)AFBO$V<1^v8 PONSMxzH4+!DQ2OeD~Aht)BgwnrCth?~FY&*jt4PAIR.kI`yfs|F-||@5JGt%+h>d`RpsN$PbUN#72ppHxa9"_-*UMSiv. y!m8 uɳ<`ԏxӄ6L6Qq>kv8HgS$ tc7]Tӄltb.KUxF #'`! b+bg#qa/j4n.:1J蓄rr7* E@ ˨.BY㑐|yy#%OT`yuYL8WA81p=4Zs?g'(ʳs$wgxFk2R3IYR053GK_S>0 Y 8R_,YSl}ќp5VZ"o]FՑ_"ZPEZܙ(85҈qIiAh[222p?(О I8OI 啟ޅz?yY("ϴ[u[/p]6[ʄ`1X 67%GQ\E8^uH!:t#o4 aGa1m0J[Y'èo`i aPD:1IP(H/ IEHJbJ?msEYIMUTZx]P6:b9bi=9G)iP:eZ@uЉn`k؅ aڝczOoLk:qi(#&5ZRqٟ<;Ewɜ+k X C\JN-ƕ3,0AC8hB;D)#*GB(zx!5Pp׋)7+=t"T\vPybDŵ{Hâ-Nq1By1-f2 EyI.E@ca/LPGf4u&m/?rjY1Wo,z4B'?'|y;H1H 21#h!'`Nc7g 3G&4qlVm:6w{0 {[~ JWRQ_aima|ۊNRdbȋR%bວ{1(NCOGjYKsOr3Uĉለ;1(Ԉf_PtZP UU2DOCid5xL_P"Ø5,Z~a $jֶ1:N.D77kxJYxJI E0TR(J9C&L$7(i@  Qz'I@CWBL|C|@o@<6Fr .6,Ӕ)Fr2J16;þQjjס{T&c,y#3XԼ'Q-y7FL0<1Y.x{,Re*O0Gy(QIɂaGY^Yn<ט!T\S"gH b(^q9b$K)+hʈU9i:x,|BU`IPzxt T<%)9OSLf_(fK ̪W(ʝhxg;da7꡺OȄdB~Y+j sejyfX"Ӏ7UWOe\Zba<+,-(=  zEry+(}l`?=7g: u>k۬([2)‚LʦlՔ!CPn8mڪ5-^ ֙7ؑ։rsWyUZd-҉"u u_L1g:T׉#yep҉Sl1gCb<5[q#V?,\K0Χr.A;un;uB{'[ݿ|ŜiK斗;H/@1,b:qH}ƅ !@"AQ׽"a3)xȽ8d-V;:ΑI[!(eсHLղtV#Ϥ,WǻJ<_8E`B|c=#e\x7ּbF|mF zY"U`#9TQ^\r.1Wߡr |ֺ5g!NrhFI]D .xiK,t'T}¡]^ +KDlYpx uё058.My0/T&AAS4l( #M @$`7)#M2iBL:wʔ"2e挑7rk%a׎ P< d B$A\&\0tAr!СrpR`n[` s9| 9{W }k'~1:!AA01-EHZ /PX>BɑЄ @ʁA&Vp[a5z"F*0x.{b&(%&n"Ʉ,v1#KNe8`Q`-9!hרS<Lf|s c0I u̧N QkH ᴑM{H3a\0*\.u"ɷPꗺM.</gX OYu"sU*hT= b2I1O ׾e>Ј5A,\S3 rC3 )HVY+mzS "f8="RW)s]cOR,3D8*?݊w\&{:M]zf$(֑hx0;̆ e0Z k1KﺖiNBy4; "t )!G'IhR>l(1T*C,'F3w(R4V-,fȕ f0gd'D?bZF$ LkY chrYplAhRȑ_Qkw܁rLCz¡xcJ,IABHsSl iR-lc HWzW$ AI`Q ܬ-%Y \M 1;TR^00~"6U X6[~YĸT7k[b74)e X,\2B苋A X,O)jD-&@+#BE5JTaK0.N:MmB#v-l+fEA?jd5S\5Z4*t (d `A jPlt3/H?(@AuR`ɵ{@I\Vk4 -BۭE n pȧ/8/WO@-Z#4DM+W\WL!rpL+ţヺfG2M]CV\L`tKxVk*31Ѭ.O}_ îi}nsXm^4l8o)ޫ_Pa$x8j3^O93݁n+I$)EtJ4҆hțe y4,ҁ ~"&vc\T/cLbPA$1;Sua,A#U1&oTCJ)Jex v5Nt+kD%uh5UߤD_@x'=SPS0NMDA&U'<8|5'~^N_ЁYՆRvރ5vA=A-Ѓ'E_:AT UP%6‚"Yҁ1s`S "wZV7;#z,#$WzzuGx3'XDB<5T,oFPtYuYZM7J982Ng%nŌ{JxЉuIXoyV 0H KM Q(}#}a5Jwjq%fdmyo[Q35 !~ECJDqO!'Ќr>E[(?4c6)'ltc7h8{6@7s<w1a!w&g`a>=&)r09e8@N> C0p`FhGTxqWEE@;dÆD_A&U(EO@TV0ed2@ah Y1[3M tYY TmD>8:0R6lii9s@ ?5!tfnCȋikUq0qZJ[vvIxfVL'Q)kY2xtQW|3zDSij&Y}h{œłšո(yH;%a6@h=(dTw=|(_e%%4(5QH'}s靵ti+rsV!*au Wdi]m66ԝeh FMN)P9['n`L( P"`Y"Z,75)j:*4>ӄMnٕZȅ'=g9Bʹr h)nfG5'Ptg"a! AYB %8Gȉbqha\Q._^1Etle{F\Z J5J!!&&8_J4b 9Yx*m\71{r{2B% IubZ;8OE7瞿oBm4Lq6F9IF&Vh!'6U}oy1o`{&҄#q>6iGʄUHMm9pXؤa9FQA|\s؇}uTQ~a.FkPU)v 0'g&z#ř2'}y%)\yR4K>.0("{' (T=`b&6!]Q״v-͵ck@Wp*;*J{d89{D9'8Ie֢;(BGC"fEZ>mM_CM9ep!M`y)A.97$jc|M9.1Z4*: 1Q==Bəc sK:#l\ V3)C[OxAC1hچ[|1eɷ 5ԣփxchi(&EcD2cP2dUйSFxK-Y!bQz`dE{dado3m.p_ 4N@CL ѴC{ٗM&L+;ZdCUT0!5Bm7v&rrPufmIN0EcSăvChtʩı`kk@u-)eYipΫF/T&AAS2rZfL9Ӹ1FN0tҼq yCA9!)CG9 ʄ!2nBa/)IA'R@dmpa9a4 эB @tSM$-ac1l1Ll-b #'7 ۲q0)W=hfC0]}s,THq:cZA:ĞXɮ"& p8g͎ Vûe3N6 ]S#K_t\C&'xDy;9QMw֕]\yE,݇Qa!LA`Ke4Ӆ)vp'±T_A],xVC,eEcȑ^XG5G[p4N=&5iSneaFO ץeLTrӕvƕJ 'bgPTGl8_9gYfHhƞԦI81tБ mhfD7io} ivfuN]!"TdpNҹqnӣѡAQq ǭAkCR]"bbkJaZ.kF2ӳCntGpvIC vnWLvI CQ 5ĚR p*";`ǀ!ۓP2VO )k) n$Urtp0}(me/F5UU4ЙpFVMv UE%9Bw,OPULENQ& 9\t<DCE Itk~.8ᆇCXgtTY7ԗ͗s6wߝRaE;qD&!tR4Ve\F3ɬu7oK-'1Dt5Hf /T&fҰ)L0lIC 8r)3N7n@ Ya… 䙳  1$0#ơͼM*YiCbD̔STt\̸G7.~; 2nsH:jhBaI͗1hԑN9B09I'DRlٔ ~s aÈ.6 +N$+e:)_ 3gÉG3$Ȕ%)o1c̙s;b RdʔK+_ 1i805P)0a@Ic-|tʹ  '}Sb#4u8./K.!B(!bHGuan<!C$^aɡ"-z#, uqc:NxRK1F9N)lЗMG^aD#Qh7*Ptix|X@% h&&L磐F**(EB0"_B !@P&t *iv9R D|J!Vuz Pr?ATцĒ$&C*DI+P8Ԭol@;ɒSlq ZX~I.ˑ4L}(wp42dS|} A0cDTw+򷿟M{RVG4a&#B@, &p;{(x·9M(LaU(4H-QXRHWԦ:5JmT:Rݤ33dM*\v VJUo!KY"6-9[cK*3sY`4A4̨9;LgF)n_!#W;Puk&*]{%Y◿f*2X a1.ȡyhY(M,ڭ\.ۣ̀YQ,g;ςHd$4GPd#J䆾%nzB7ΎS!E.wC`(Q7[I}(MfN>e_hi'A ZY$Ġ906swI#lюilh.QMi q)MqjZ"Mmh*u17HgZ W, :rNװAk=39N 6GI(p,|мWU !WÊլFM4jB:VR lq3|fRSrh*ěj'͏)6ZEq2S'n\' c)36Z"F q\<*yI9Kʩ8ܧZe1 ejK\5b,ьMP(S+8fL[cH84m02u651Z7+íj5X,+.:xŋUufg'$ eYNu)pIr= #U׍MiӋnO~8i;<k 3ƒ;"ܛa6%$Cu,@s߾O߽T`xa 0 }VƗz#:(Pg~a31|&}C]M!qS}uy0gUw,1Nt@2i#QiQftNOs8.S`LUi(bF X WLe=Rc'qEUmqF$փ'd 6٩@@=Tj饘f馜v)*`vl1:ԧ꫘fL$1^V}9 !Ji؅ T  ) lc FGrJ}&Gbn!Bb-ł¸FlSXD΁ƴ޶{l=pndoQ G Ʃ Yw[扰 + _ڷ WJYˮ̂`-z[*B_t]~q>s._8!JtW@ Bҵ:1b0lgBAR1EAHf9AE5w|(8 O º}߼,/T&fҰ)b7t¤qsȡ)3M7ۀ3 o@)%/ICL  &\8Rh B'O3)3A as%,Y͚&9 1r̙T6oƬ!MY2P5 H єkE7 Cˉ qC8i̓Ah%& R591ɔ9R7/M^HE]('O7aiPXQ]efM "c! BDteT1͆l9#S=ׯygOV{ƭCwxGn \!ETud|Fp`i1܃`%ۃ/=w< ^u|Az<Đu!vKy_{᭱e (6CD!q}adD wW^{A٥R|4Qeu#L4u( . QD h@xɧ/Бejhnܙ'C{CmHzhb%ZgU ( baFbjdy{xDoȦ,XF~ksԸtʖ AM1G.0pC!-lsbY٘ 3%PLhE[٘T4 +s0wͱDMTnwVVpPT!I Q"Grq_ ĢSaI<GdW5fʁL/7GNONGIGPp4$j ` !| R L彄(P!Ł {yKKԃb2>p=b.BK@KSMcbS6&fk"v1$ "ɘ2NIrD tQ&ќ&Y7S mi:Me 'P@-^IHxT/} ci #{Y:Kxub^>8Л,P/= a$6A0i#N YRz7mE8XҚ l8әtB# dMPP/8D6mZ1 :Yw-3@|AY ᵚ0I:"@-#_7 u Aj鸁5 lgW1wT^,&Ϛgr& c SVL1i C;(=g`CM;Q}ACaÒAo5xV#6q3uG TD&±̤%)X[+ }5:! A&Qf.1ΏC$״,VnAD2.RSˋ%4cSEArwvݩVp嫸1o8Pp0r<3(k5 CxB{m|Qx/[ |0MPhu!pxa\v1B48Xy<.pk [Jxw9ofcY<I@ ޵TM1S}6 a\-e:&q0aB%1'Yc{4 ֪h{p?C_ yz1bK5~3#mY\f6x|E6HG6x2A;ΆKж;|6K(}S1]Wp=7V1b`kk `PZ26S%D}դkl;l1''@q}]02B5<#SӔ~XLV{=H!3MGrQuQU7Y3h~aseQp=q2e?W! Q>k%&VRdqnfjGpzȃ`nP&dXk1k}#1aE牄3'}#{Ul Qp&l90R#t*eLq7W)VVȄ6!ц8vVMfvDd'o\W^d e1lgSd&tHTX_Eqe8RaĦ7EUhxbkvHA># чZ'3mq/'w+ćZUЗ:f^d8[D5qTWCHZE{zW~e] 07=^.4|w|a&n!-&5q$E20CP]Q#~U8FLePWMN$VE.IF|GG~MfjIa:Tc`sU"(/CXC@O YЀV3k!0NydpB娏Fcycy"ؖq9ue7WXMY(u:3b\SfGf\&iK_HVqʼn$XgEM.ʼn-ViQ#:99B.3 :nc0S~s7wГ7tք7 AyFәA񙬈t1ͥ"ar5:!<+t7@?%68%S,BǕ_/犘l6!cƒ:Ȑ<# f"j%74ٟ/Y4NXaiȈt >X!7NP:Sw%%1Ma{a22C<"$=rc~>?E+Nz?z@(;3r8=CĎbHi|Q@F{k?u4W06GA$BF|dd 8bWy7H  `Vsczcc5:h )Hi:~NaZi`i]QvP䬾fjIyyZv`)Q!HFL r8Kg;θ4XgqrL:DMu8uAu!)_QMvIE`0RzYY.lRO>dXut~l/Wf #&F10GS/w YƱqŪ_4H 7pWUpf%YBYl/N1{V?GC"2;!tVmu5Qx1op*=guFX{!`yl!1![9R16Ac {;; f!̘~4bY-R'KeINդdJ2d&|xMv[8$Vh3=e R'mni?#w*/ǘK Wn||Gΐ.iE'{\z9z14H,{>N$;8[gbT'Z/kaήKe֗^QYn%|Ͼ-THimk|1G%ɞWc -!9g#,67rW0B3yFBV1;_z; ~/* Tables sizes */ #define NR_ZONE_NUMS 9 /* # zone numbers in an inode */ #define NR_BUFS 30 /* # blocks in the buffer cache */ #define NR_BUF_HASH 32 /* size of buf hash table; MUST BE POWER OF 2*/ #define NR_FDS 20 /* max file descriptors per process */ #define NR_FILPS 64 /* # slots in filp table */ #define I_MAP_SLOTS 4 /* max # of blocks in the inode bit map */ #define ZMAP_SLOTS 6 /* max # of blocks in the zone bit map */ #define NR_INODES 32 /* # slots in "in core" inode table */ #define NR_SUPERS 5 /* # slots in super block table */ #define NAME_SIZE 14 /* # bytes in a directory component */ #ifdef i8088 #define FS_STACK_BYTES 512 /* size of file system stack */ #endif #ifdef ATARI_ST #define FS_STACK_BYTES 2048 /* size of file system stack */ #endif /* Miscellaneous constants */ #define SUPER_MAGIC 0x137F /* magic number contained in super-block */ #define SU_UID (uid) 0 /* super_user's uid */ #define SYS_UID (uid) 0 /* uid for processes MM and INIT */ #define SYS_GID (gid) 0 /* gid for processes MM and INIT */ #define NORMAL 0 /* forces get_block to do disk read */ #define NO_READ 1 /* prevents get_block from doing disk read */ #define XPIPE 0 /* used in fp_task when suspended on pipe */ #define NO_BIT (bit_nr) 0 /* returned by alloc_bit() to signal failure */ #define DUP_MASK 0100 /* mask to distinguish dup2 from dup */ #define LOOK_UP 0 /* tells search_dir to lookup string */ #define ENTER 1 /* tells search_dir to make dir entry */ #define DELETE 2 /* tells search_dir to delete entry */ #define CLEAN 0 /* disk and memory copies identical */ #define DIRTY 1 /* disk and memory copies differ */ #define BOOT_BLOCK (block_nr) 0 /* block number of boot block */ #define SUPER_BLOCK (block_nr)1 /* block number of super block */ #define ROOT_INODE (inode_nr) 1 /* inode number for root directory */ /* Derived sizes */ #define ZONE_NUM_SIZE sizeof(zone_nr) /* # bytes in zone nr*/ #define NR_DZONE_NUM (NR_ZONE_NUMS-2) /* # zones in inode */ #define DIR_ENTRY_SIZE sizeof(dir_struct) /* # bytes/dir entry */ #define INODES_PER_BLOCK (BLOCK_SIZE/INODE_SIZE) /* # inodes/disk blk */ #define INODE_SIZE (sizeof (d_inode)) /* bytes in disk inode*/ #define NR_DIR_ENTRIES (BLOCK_SIZE/DIR_ENTRY_SIZE) /* # dir entries/blk*/ #define NR_INDIRECTS (BLOCK_SIZE/ZONE_NUM_SIZE) /* # zones/indir blk */ #define INTS_PER_BLOCK (BLOCK_SIZE/sizeof(int)) /* # integers/blk */ #define SUPER_SIZE sizeof(struct super_block) /* super_block size */ #define PIPE_SIZE (NR_DZONE_NUM*BLOCK_SIZE) /* pipe size in bytes*/ #define MAX_ZONES (NR_DZONE_NUM+NR_INDIRECTS+(long)NR_INDIRECTS*NR_INDIRECTS) /* max # of zones in a file */ #define printf printk /* Super block table. The root file system and every mounted file system * has an entry here. The entry holds information about the sizes of the bit * maps and inodes. The s_ninodes field gives the number of inodes available * for files and directories, including the root directory. Inode 0 is * on the disk, but not used. Thus s_ninodes = 4 means that 5 bits will be * used in the bit map, bit 0, which is always 1 and not used, and bits 1-4 * for files and directories. The disk layout is: * * Item # blocks * boot block 1 * super block 1 * inode map s_imap_blocks * zone map s_zmap_blocks * inodes (s_ninodes + 1 + INODES_PER_BLOCK - 1)/INODES_PER_BLOCK * unused whatever is needed to fill out the current zone * data zones (s_nzones - s_firstdatazone) << s_log_zone_size * * A super_block slot is free if s_dev == NO_DEV. */ EXTERN struct super_block { inode_nr s_ninodes; /* # usable inodes on the minor device */ zone_nr s_nzones; /* total device size, including bit maps etc */ unshort s_imap_blocks; /* # of blocks used by inode bit map */ unshort s_zmap_blocks; /* # of blocks used by zone bit map */ zone_nr s_firstdatazone; /* number of first data zone */ short int s_log_zone_size; /* log2 of blocks/zone */ file_pos s_max_size; /* maximum file size on this device */ short s_magic; /* magic number to recognize super-blocks */ /* The following items are only used when the super_block is in memory. */ struct buf *s_imap[I_MAP_SLOTS]; /* pointers to the in-core inode bit map */ struct buf *s_zmap[ZMAP_SLOTS]; /* pointers to the in-core zone bit map */ dev_nr s_dev; /* whose super block is this? */ struct inode *s_isup; /* inode for root dir of mounted file sys */ struct inode *s_imount; /* inode mounted on */ real_time s_time; /* time of last update */ char s_rd_only; /* set to 1 iff file sys mounted read only */ char s_dirt; /* CLEAN or DIRTY */ } super_block[NR_SUPERS]; #define NIL_SUPER (struct super_block *) 0 /* Type definitions local to the File System. */ typedef struct { /* directory entry */ inode_nr d_inum; /* inode number */ char d_name[NAME_SIZE]; /* character string */ } dir_struct; /* Declaration of the disk inode used in rw_inode(). */ typedef struct { /* disk inode. Memory inode is in "inode.h" */ mask_bits i_mode; /* file type, protection, etc. */ uid i_uid; /* user id of the file's owner */ file_pos i_size; /* current file size in bytes */ real_time i_modtime; /* when was file data last changed */ gid i_gid; /* group number */ links i_nlinks; /* how many links to this file */ zone_nr i_zone[NR_ZONE_NUMS]; /* block nums for direct, ind, and dbl ind */ } d_inode; /T&fҰ)b7t¤qs04F8epfoxg2ma栜2l1  Y`7d@IssO9iqTEՁA('7 g s*oAT Evi$DH%L4•FΛ7t7_)OP!e13(&whd!)e8Jͅ=#b3%޻֯9  FLæF"\xCt\|yѧWv0w0<!9]ߛ~=.{Бgv^Zeh"cc8 tgA7q!l} Ê,0(4hUP iեcu 5iHqPT!I BXU )(G Qg0TWNu odBuCSVMeFSIUMTiQGN/]L]5iOpPE VtThrotA/Du8ЄoHpfh"|~fC|)e&HHshHG ]Wt|F(H؂~qGGkԕr ec9évd25;qed G,. EfQGIB ¼STER|Q$/Sl1[*K VԛLeav@;s͇pwor\ztex qE3IC\cAU|uOF9%DU6XjAWҝ1E)! NǾFF(0!}QTHD61M WtePu\V5u%6ϗAVgԯ,Gqț]Ə@9dIXZWm> iG_1e˒KHe*EkU|@s@Đs#鍺 "1) L06gئ>֢ߥ8d "6yy,r\L[")uJ}dzΪX1;˶Fm3Yc}_-1^*-@2a{ MwQ$4UB4 .BJlIlJr7 = !pV!a3A*-6ɔ"7 Ρ#q;ny[.![lYsjD= vXό6 κ88nX&0q+N9.|[.F.Au;׎Գ k:tXcq _-7 "5)5 BPţZؾ&z߽ZS7}vGz`=C$/ @']fx8oU,,9 FoI|8rpjc3 2}'AwH+Bn~+$ۻfù},T bK'^Ka6Z5 {r| u"@s̄WdE_Y1t2NGS:(7zGx;6W-m-z,8rax:(%%G)7Uv3tdtR, m.FWw: UEDp)bRXtPUaeuU JxO&2b=/T&fҰ)M7aΔ9H 9uB 7cր#ÇdFZ! 0tʤ$3 9tCN9,<,T2N0p( bM2pF 3 7n&@vl4nސQPa|SZ7)Ŧ!%–e\qŢ W.7Ϧ|0LI+9oN۱ӬoK֯̐ QM<.&Ȱopsp.,G.y˭Ut! np[-aǖPA@LR6G.el!9U_)TF79^k(fP,qAOط}紓SrGPsbۢYr>N@MlHG<j2OlvKXP13 pB>xa=Ćp Ct`V#Ьh ZZ9E .1CBƐOМ"&OZ s"R >A4ymf nD:*= A-m @zCPMIq[ZeI0/P=8fi ` \B#"@s!x.22*@!0jp3 |ƄSbOU^Xgb@?\\b׾nz0h?1L ~/\yL$e3/=I3)  NrA(S,fRزNօ!iL)M˄,҆@heC - 8 }Tgib,s$śR 9e>5SCUyj5XyFA#RCnb}r',}ַF:S;hqc7YYseCGѕNK ueݖP1ԥd2;jUpfFG E,q^K(}ҋ(GFMU"hT`Z j+a~8B i^*LD ^0&щRƘC#BEI٣#S.Ơ|p/*ԇ#j3gIid 6g=,XtH[d1, ,lf ;ƄpIRhnIL熠|g s.W 겕|<ɯr7oHdfΝA7LfAnJo94ZN!1]hG?+Ec=F9f6VnChKk8y8 Dۮ)EIq–Z26rPw2{^לA^vUp0!)fݒ!)bHҌo}aWߛ¡l-as jL6eFCǜp9A ǚ1H|͒#jJ̡.]<t ,\/>=S_ಣm =wAH 񌽯gA{A`5xe't>lo/'.lpIg3޽3dXMDLVb2 RLGN54VC{ pa'hS]!Q33h)h,7} En%#rn5 |WMJ]S}> URqDI T3vE*aЅ~{hLf@apS{! 8Ƥs=xv*K0 1R-P)Qq(uƈ=U]@ԂPGjqhw͆)(DdCeXKV8IROV88XceuJeƇo2fUp*`|uhyvB{&}BB!87kZdhkF1+lV#DXNJbP@fl_evT(Bo,oH7RKbGs2tL#tTp' }(lpj]qitŇyVHgKM>Fr@u/suvw0.Qm1eQ _qAQzԖ.uYqA|B׃NLDF*BܗVL7)j׃Hx,BIn`I"Ɔ3 .zj(rJDH)p`jE} `(MWșd5`_YNqCXe7H8%=PzY9ZX9^赋ݹAZCU>.5z J$)&W)b +J{(&)2R*mmա g/**0zem=u)iPHiPF)BzAz4DPV T UP6y]**Eu='`&-*JH,FI=1DT7>9 rD`ڦAjEJmFRSЯx{t*y*߹Rv٧Y] * ;C  *o> &"**)!&SfX)Q7B+6g]:U@tmE[^%=m&ڞ84]PXCi&i3nZd;S8ˢACe[9iAik/qnj^F[vx&-)]w&.[ANprR 3.C-kӂ &JC=ZH?ޕqMD*C`Y%6!-E3t`3ᣏKb_:Z5aKlSUyAQ弩Cgbh7r\Zl⧊ 8M2 Ep @#B+W`A%kNknukرe_T-_aѮ,o\v58,X;q "XDkgC.M\fdF~_=ù)ƮEcwe :On1Ӄa&oz;NSmRd| 3f9(R/ 2iȑ~}_ ȟhq PoБ걇{rQQR ~Ay%-kh`,b^{ʗcFlLcQC(_k KQo4a 6jނpT"AeؑeJ~AE&`J|mƉ_I.XlFn nGi%!NJ:il zҟֹaCIɁ`cE*K 3FFLT1_hS@@ Lb0L1Q{@a l1}fPmA0D){(*ü \eo*ҡ/ pc@/p2\q& ii ,\`er yX6+ /KD P3j195ԛir F7jమ1(ZwP96ɺ 5Nt .Jxxtm㬷2|xГg6ӺP8պҘ[ݵFk. epFttI"6Im( P4{ 6 { 1lkb5( S̠7SD E`N`ylZ2LoȽ=͡-ۡu`%~Qn|h51;!B${!4Pp@@i$U4v5a `HOV|5X!РZR 5 ӪZhG=bCjp>dL%,퇂6jERܢ4)mJ0nqޠb'l$jM  M}r;-g-a I8PBJ7D'C3D=S6T,ZPRl*8 AB~B2.d$, !AX'$ X$Rh R(`T`B YVЙh8@TT`#̠>T[LT&镯v\/BYQT9EUAh谩""p !%C* {OI͚>VIMnr&$뜃 DXh% ն2>d R8i)]@|(nsI֪ i~ !UVna {nmq6 x?FIE FnXzaHg9G~qo]ƴ фW}Z vnC\A"~Qf!4&@)KַPEHDamYwSTBU (^b$ Og˫vf&/Rd(H8>MFr-IHAE1Q]}hgC* {Ī$JK2'Xj, /&e)(Ёt+zKlI>\GC+Ͻs nv٧8R2f ;XOyG$#A'JbO|"&yYRdUMأ%&i3KDAP_ZP,*Hu c\#!4aȶP*|!3#28WbjM+OPq dP0&oҁ9I.I*@u/T&fҰ)b7t¤qs0 2w@)㦌0l@#Λ9 QNrިXf  TH!G:r^H 7 dHAMo| ݤ]eYwQGH$EET5I`}D /(YU /†{#Ɖ) .،5a" Ȣ!#$ y#FQLr,)HMbYd?2i#EQ\ eSa^dfi:Ig\U"L{Ys) d0G>V PHAPQD_V}@aFAbtg$͑ Ad SNZ]1G5tUV_:"ò6F+JSN~z\mSk΂iB00Vt5Vݢ@ JA0ɴRGAEoUDv*$C1Pq 9 HUTg$[eGUw6 n,˾5Л^z/8 V5VyB Q_PDE PXXTg( C, jel )O,c B7T:E ujF(VIE3ZoIUcS͆t(H\Q7=vo͵35ƺDWtuؠ y7 Y)̐ B!_*nf!!PD60A8'p J) J~JΘA6rг$DM#Rg>q+,DL-*t `*u,݅nϰFR:7/0^{W./K_w ݤ19`Tl^(LeA:fdC47V .Kta\QJd3XL Ҍnbp,,V2F;ٍjՐfYv,Sn0t>__"0X_(#f6};ԡg'P,S >IFi*`4]A@/L r"4`rO|PodK0u Ef7Tg59ydg9$ڀ3;xff|JZĮgAFzF[u*A9p:ڄAJZ/W# d-;{ 0肉M;:PDhXMՖZ?c"$>oA@T"`.(t CD"y.ԵsICr@T1_}@ ` P>/8HX+ަ'&##QP)N O' Uڻ$qV;&wQ@L a|Qx|3ol.w# _B*C0ETQ/~ZRu3en9'Oܮjfj@jL@bKTnZU! 9\/ uhCnv?L;L.?B(`mWtCgC(hgµEGo*~IH!VwQ8B  a>u* BH{+84S+ 9{L#̥ l0@e<"h N(P&tP @ȥS!BJV6P[[]n9n?2JU(x]9P -iA/0J^BSć!v:enhHE*oaXTЅ0! Ǎ+l c80JE:2m3B0"hdz[ DIJS @ vFrVB@)Ј 7oy x0;a62 [p<rve#?#ѯz2IMm~`C~᰺Y͂ (gA>cf}P:!OS"AIT=j@R8 ѓD : @PJ Ta] b$034ؙ@nжJ4 F6pKBd}cGTƲ3Hv; 6;W-t3Ӡ+V4F#,#VbX3Ek Q-VŪ+jx[^:_Wjؓ򵟒/:1.NQ &u\|&)ryL;@U]. w˂22LqtJܸt$S݇w!VNJ>t M{21=}9"7x!]6Z&Iq=>aoO?뜄4oAsSgkΨ(&=5l|5jF-NJпD3 W^#IX;c=!c+;0[*|c*͗W\I"e)f??\%4&u 1) >y–|wJ=  ?QH17 !Lsarxgr'!k9*_~G0UXW(x*e6e\qPq--{SpxlQ\+d#)PBlzh:ȃ QMG8!>!0tpe&XqbP'kae\#F\<;+pQG]S')&^D@Enk6_Fdii `UCn(qE2rH'7U">g!'%'{'6E1z-i?n@s'|W}9;g/G'kx$tz0NQHwbg( 19tZ1؎vwG5jn1R7cw^3pvKd5*BAn-buO`Fi!k)12@9}cap@H9 Pmtu3d@3ȗ7sVC{5QVh.fӓ8SkC}mPWsP8帖ڨ8n6ҧzO%oVtmi{}4{wo_9]R7`tATsCdj2);#I}lhbb1hÔT;sRPP'Q Xf<56SvPT6_xAEdVtgf6[cߤ[`SR+DR'$cR]zbvb1Ā< LcHiF2k8%I h|_[7#GI+-qɓ)2*T]Y1›c([-|# ů4b~k#ɥ@wD%ÍzF9? toGbu$BGkƮn@BZl 6ҁo+zPa]Yb[8!Z[T߅kzl/AHu_ySA*31EE,W&TRM WHD+c&D%*0A}UDL|!<񄣐FCW0%ub- iDYe[uN iIh p0}B4AzjD eHJ+C2< pɠ!= ]p',8̥r3@No+gx/Nx aHH4Oj(\a[h@獰 O@C vP Wj*RA$*>Ԝ|68AED&jІ72b1ђZfGD P_X]̘'ht́8TEH:0 c:9%idDfR/T 3oذys'3 ܄iSf0r 捛