7. cdev_write -> cdevsw_lookup
cdevswを取得するため、cdevsw_lookup() を呼ぶ
/
*
* 番号からキャラクタデバイスを検索する
*
> 呼出し元はデバイスが接続されていることを確認しなければならない
*=
/
*
cntsrc dvw*
os tutces
ces_okpdvtdv
dvwlou(e_ e)
{
d v a o _ m j r / d v a o _ はi t 2 t y e e
e m j r t c a o ; / e m j r t n 3 _ のt p d f
i dv= OE) /#eieNDV (e_)1
f(e =NDV / dfn OE (dvt)
rtr NL)
eun(UL;
c a o a o ( e ) / メジャー番号(デバイスの種類)取得
mjr=mjrdv; /
i cao |cao =mxcess
f(mjr<0| mjr> a_dvw)
rtr NL)
eun(UL;
r t r c e s [ m j r ) / c e s 配列の要素を返す
eun(dvwcao]; / dvw
}
#eiemjrx (dvao_)(un3_)x x0ff0 > )
dfn ao() (emjrt((it2t()&000f0)> 8)
24. comwrite -> device_lookup_private -> device_lookup
/
*
eielou:
*dvc_okp
*
与えられたドライバから e i e
*
d v c インスタンスを検索する
/
*
dvc_
eiet
dvc_okpcdie_ d n nt
eielou(frvrtc,itui)
{
dvc_ v
eietd;
its
n ;
s=cni_ldv_ok) /
o f g a l e s l c ( ; / ロック
KSETmtxond&ldv_t);
ASR(ue_we(alesmx)
i ui |ui =cc_dv)
f(nt<0| nt> d>dnes
d UL
v=NL;
es f(d d>ddv[nt)! UL& v>vdlgn! )
lei (v=cc_esui] =NL &dd_e_e =0
d UL
v=NL;
cni_ldv_noks; /
o f g a l e s u l c ( ) / ロック解除
rtr v
eund;
}
25. comwrite -> device_lookup_private -> device_lookup
dvc_okpcdie_ d n nt
eielou(frvrtc,itui)
{
..
.
s=cni_ldv_ok) /
o f g a l e s l c ( ; / ロック
KSETmtxond&ldv_t);
ASR(ue_we(alesmx)
..
.
cni_ldv_noks; /
o f g a l e s u l c ( ) / ロック解除
sai n
ttcit
cni_ldv_okvi)
ofgaleslc(od
{
mtxetr&ldv_t)
ue_ne(alesmx;
rtr ;
eun0
}
..
.
/AGUE*
*RSSD/
sai od
ttcvi
cni_ldv_nokits
ofgalesulc(n )
{
mtxei(alesmx;
ue_xt&ldv_t)
}
ロックは、mutexを使って実装している
26. comwrite -> device_lookup_private -> device_lookup
dvc_okpcdie_ d n nt
eielou(frvrtc,itui)
{
..
.
i ui |ui =cc_dv)/ nt
f ( n t < 0 | n t > d > d n e s / u i の範囲チェック
d UL
v=NL;
es f(d d>ddv[nt)! UL& v>vdlgn! )
lei (v=cc_esui] =NL &dd_e_e =0
d UL
v=NL;
src frvr{
tutcdie
..
.
dvc_ c_es / eie on /
eiet*ddv; *dvcsfud*
..
.
itc_dv; / ieo ddv ra /
n dnes *sz fc_esary*
..
.
}
;
unitの値をチェックしてからcd_devsのunit番目のdevice_tを取得する。
取得したdeviceのdv_del_genが0でないなら取得失敗。
27. comwrite -> device_lookup_private -> device_lookup
dv->dv_del_genとは何か
dvc_okpcdie_ d n nt
eielou(frvrtc,itui)
..
.
es f(d d>ddv[nt)! UL& v>vdlgn! )
lei (v=cc_esui] =NL &dd_e_e =0
d UL
v=NL;
detach 関数で値を入れられている
it
n
cni_eahdvc_ e,itfas
ofgdtc(eietdv n lg)
..
.
i alesnrt =0& ldv_ra =0
f(ldv_wie= &alesned= )
cni_euln(e,&fa_abg)
ofgdvnikdv a.fgrae;
es
le{
dv>vdlgn=alesgn
ed_e_e ldv_e;
alesgrae=tu;
ldv_abg re
}
作成時は0にセットされているメンバ変数で、GCのフラグのようだ。
0でないと回収対象なので、チェックしているのではないか
28. comwrite -> device_lookup_private -> device_lookup
*
与えられたドライバから e i e
d v c インスタンスを検索する
/
*
dvc_
eiet
dvc_okpcdie_ d n nt
eielou(frvrtc,itui)
{
dvc_ v
eietd;
its
n ;
s=cni_ldv_ok) /
o f g a l e s l c ( ; / ロック
KSETmtxond&ldv_t);
ASR(ue_we(alesmx)
i ui |ui =cc_dv)/ nt
f ( n t < 0 | n t > d > d n e s / u i の範囲チェック
d UL
v=NL;
es f(d d>ddv[nt)! UL& v>vdlgn! )
lei (v=cc_esui] =NL &dd_e_e =0
d UL
v=NL;
/ デバイスが有効かチェック
/↑
cni_ldv_noks; /
o f g a l e s u l c ( ) / ロック解除
rtr v
eund;
}
device_lookup() は、
cfdriver(com_cd) と unit番号から、deviceを取得する関数でした
30. comwrite -> device_lookup_private -> device_private
vi
od*
dvc_rvt(eietdv
eiepiaedvc_ e)
{
/
*
e i e p i a e N L ) は多くのユーザスペースの要求ハンドラ
*dvc_rvt(UL
すなわち、c b e ハンドラー)
*(
/dv
の作業を簡略化するために許可されている.
* それらがN L かどうかをテストする必要がなくなり、ただd v c _ r v t を
UL
eiepiae
* 呼ぶだけでよくなる.
/
*
rtr e =NL UL:dv>vpiae
eundv= UL?NL ed_rvt;
}
引数のdeviceがNULLだったらNULLを返し、そうでなければdv_privateを返す
関数でした。
31. comwrite -> device_lookup_private -> device_private
dev->dv_privateは何か
vi
od*
dvc_rvt(eietdv
eiepiaedvc_ e)
{
..
.
rtr e =NL UL:dv>vpiae
eundv= UL?NL ed_rvt;
}
src eie
tutdvc;
tpdfsrc eie*eiet
yee tutdvc dvc_;
src eie{
tutdvc
..
.
vi *vpiae / hsdvc' rvt trg /
od d_rvt; *ti eiespiaesoae*
..
.
}
デバイスの private storage
34. comwrite -> COM_ISALIVE
#eieCMIAIEs)(s)>nbe =0&
dfn O_SLV(c (ceald! &
eiei_cie(cs_e)
dvc_satv(s)>cdv)
src o_ot
tutcmsfc{
dvc_ cdv /
e i e t s _ e ; / ドライバ非依存の情報
..
.
i t e a l d / t a h p n が代入。d t c 、s u d w で0
n n b e ; / a t c 、o e で1
e a h h t o n 代入
bo
ol
dvc_satv(eietdv
eiei_ciedvc_ e)
{
itatv_lg;
n ciefas
atv_lg V_CIE
ciefas=DFATV;
atv_lg =DFCASSSEDD
ciefas| V_LS_UPNE;
atv_lg =DFDIE_UPNE;
ciefas| V_RVRSSEDD
atv_lg =DFBSSSEDD
ciefas| V_U_UPNE;
rtr dv>vfas&atv_lg)= V_CIE
eun(ed_lg ciefas =DFATV;
}
アクティブかつ、各サスペンドフラグが落ちていれば、
device_is_active() は true
37. comwrite -> tty->t_linesw->l_write
/
*
iedsiln(
* L n i c p i e 回線制御) s i c a l
wthtbe
/
*
src iew{
tutlns
cntca lnm;/ iewnm /
os hr*_ae *Lns ae*
LS_NR(iew _it
ITETYlns)lls;
uit lrfn; / okdb tlicls_lc /
_n _ect *lce ytyds_itsok*
itln; / eaydsiln ubr(o ICED /
n _o *lgc icpienme frTOGT)*
it(loe) (e_,src t )
n *_pn dvt tutty*;
it(lcoe (tutty* n)
n *_ls) src t ,it;
it(lra) (tutty* tutuo* n)
n *_ed src t ,src i ,it;
it(lwie (tutty* tutuo* n)
n *_rt) src t ,src i ,it;
it(licl (tutty* _og od* n,
n *_ot) src t ,uln,vi ,it
src w )
tutlp*;
it(lrn) (n,src t )
n *_it it tutty*;
it(lsat (tutty*;
n *_tr) src t )
it(lmdm (tutty* n)
n *_oe) src t ,it;
it(lpl) (tutty* n,src w )
n *_ol src t ,it tutlp*;
}
;
cdevswのようにアクセス用のテーブルになっている
41. comwrite おまけ
バックトレースだとcdev_wirte() -> ttwrite() になっていて、
間にあるcomwrite()が見えませんが、
comwrite()はttwrite()をコールした後の処理がないので、
スタックを戻した後、jmp命令でttwrite()に遷移しているからでした。
c2a3 cmrt>
0597<owie:
c2a3: 5 ps ep
0597 5 uh %b
c2a3: 8 5 mv ep%b
0598 9e o %s,ep
c2a3: 5 ps ei
059a 7 uh %d
c2a3: 5 ps ei
059b 6 uh %s
c2a3: 5 ps ex
059c 3 uh %b
c2a3: 8 c1 sb 01,ep
059d 3e c u $xc%s
..
.
c2aa: 8 41 ad 01,ep
059a 3c c d $xc%s
c2aa: 5 pp ex
059d b o %b
c2aa: 5 pp ei
059e e o %s
c2aa: 5 pp ei
059f f o %d
c2ab: 5 pp ep
0590 d o %b
c2ab: f 0 jp %a / trtへ
0591 fe m *ex /twie